Skip to content

Conversation

omerap12
Copy link
Member

@omerap12 omerap12 commented Apr 5, 2025

What type of PR is this?

/kind feature

What this PR does / why we need it:

This PR adds new options to the Vertical Pod Autoscaler (VPA) to better handle Out of Memory (OOM) events:
It adds two new settings to the VPA configuration:

  • OOMBumpUpRatio: How much to increase memory after an OOM event
  • OOMMinBumpUp: The smallest amount to increase memory after an OOM event

These settings can be set for each container within a VPA's resource policy.
If not set for a specific container, it will use default values from the VPA recommender.

Example:

apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: oom-test-vpa
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: oom-test
  updatePolicy:
    updateMode: Auto
  resourcePolicy:
    containerPolicies:
    - containerName: "*"
     oomBumpUpRatio: "3.5"
     oomMinBumpUp: "100Mi"

Which issue(s) this PR fixes:

part of #7650

Special notes for your reviewer:

Does this PR introduce a user-facing change?

Added OOMBumpUpRatio and OOMMinBumpUp options to VPA for customizing memory increase after OOM events.

Additional documentation e.g., KEPs (Kubernetes Enhancement Proposals), usage docs, etc.:

VPA now supports OOMBumpUpRatio and OOMMinBumpUp for fine-tuning memory recommendations after OOM events, configurable globally or per-VPA.

@k8s-ci-robot k8s-ci-robot added kind/feature Categorizes issue or PR as related to a new feature. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. labels Apr 5, 2025
@k8s-ci-robot k8s-ci-robot added approved Indicates a PR has been approved by an approver from all required OWNERS files. area/vertical-pod-autoscaler size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Apr 5, 2025
@omerap12
Copy link
Member Author

omerap12 commented Apr 6, 2025

We might want to create a proper AEP for this, but this is the general direction I'm thinking. I can open additional issues to track the specific flags we’d like to support for this type of configuration.
What do you think?
cc @voelzmo @raywainman
(Wanted to loop in Adrian as well, but he's currently traveling :) )
/hold
/kind api-change

@k8s-ci-robot k8s-ci-robot added do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. kind/api-change Categorizes issue or PR as related to adding, removing, or otherwise changing an API labels Apr 6, 2025
Copy link
Contributor

@voelzmo voelzmo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @omerap12 thanks for the PR!

I agree it makes sense to be able to configure the OOM bump behavior on VPA level. There's a few questions on how to implement this, though:

  • I'm not sure if we want this to be a configuration on Container level or on Pod level, i.e. should this apply to all Containers controlled by a certain VPA or should this rather be something that's controlled per individual Container? I think so far we've been mostly offering configurations on Container level, probably this would also apply here. Or do we have some indication that people who want to configure custom OOM bumps want to do this for all Containers of a Pod in the same way?
  • I don't think we should introduce a new configuration type recommenderConfig. Technically, all of these properties are configuration options of the recommender (histogram decay options, maxAllowed, minAllowed, which resources to include in the recommendations, etc), so this doesn't seem like a reasonable way to group things. If we agree to make this configuration Container specific, I'd rather add this to the ContainerResourcePolicy
  • Currently, OOM bump configuration is part of the AggregationsConfig, as it is assumed to be globally configured, like all the other options in there. This config is only initialized once, in the main.go:
    model.InitializeAggregationsConfig(model.NewAggregationsConfig(*memoryAggregationInterval, *memoryAggregationIntervalCount, *memoryHistogramDecayHalfLife, *cpuHistogramDecayHalfLife, *oomBumpUpRatio, *oomMinBumpUp))
    • If we, however, want to make this configurable per VPA, I'd rather opt for pushing this configuration down, rather than adding some if-else to the cluster_feeder resulting in having to find the correct VPA for a Pod every time we add an OOM sample
    • IMHO, a possible place to put this configuration options would be the aggregate_container_state, where we already have the necessary methods to re-load the ContainerResourcePolicy options on VPA updates and then read this in cluster.go, right before we add the OOM sample to the ContainerAggregation:
      err := containerState.RecordOOM(timestamp, requestedMemory)

WDYT?

@omerap12
Copy link
Member Author

omerap12 commented Apr 7, 2025

Hey @omerap12 thanks for the PR!

I agree it makes sense to be able to configure the OOM bump behavior on VPA level. There's a few questions on how to implement this, though:

  • I'm not sure if we want this to be a configuration on Container level or on Pod level, i.e. should this apply to all Containers controlled by a certain VPA or should this rather be something that's controlled per individual Container? I think so far we've been mostly offering configurations on Container level, probably this would also apply here. Or do we have some indication that people who want to configure custom OOM bumps want to do this for all Containers of a Pod in the same way?

  • I don't think we should introduce a new configuration type recommenderConfig. Technically, all of these properties are configuration options of the recommender (histogram decay options, maxAllowed, minAllowed, which resources to include in the recommendations, etc), so this doesn't seem like a reasonable way to group things. If we agree to make this configuration Container specific, I'd rather add this to the ContainerResourcePolicy

  • Currently, OOM bump configuration is part of the AggregationsConfig, as it is assumed to be globally configured, like all the other options in there. This config is only initialized once, in the main.go:

    model.InitializeAggregationsConfig(model.NewAggregationsConfig(*memoryAggregationInterval, *memoryAggregationIntervalCount, *memoryHistogramDecayHalfLife, *cpuHistogramDecayHalfLife, *oomBumpUpRatio, *oomMinBumpUp))

    • If we, however, want to make this configurable per VPA, I'd rather opt for pushing this configuration down, rather than adding some if-else to the cluster_feeder resulting in having to find the correct VPA for a Pod every time we add an OOM sample
    • IMHO, a possible place to put this configuration options would be the aggregate_container_state, where we already have the necessary methods to re-load the ContainerResourcePolicy options on VPA updates and then read this in cluster.go, right before we add the OOM sample to the ContainerAggregation:
      err := containerState.RecordOOM(timestamp, requestedMemory)

WDYT?

Thanks for the input!

  1. You're right. it makes sense to keep this as a per-container configuration, in line with most of our existing settings.
  2. The recommenderConfig was just part of my initial POC, so with (1) in mind, we definitely don’t need it.
  3. Agreed. Thanks for pointing out the relevant spot in the code!

So yep, I agree with all of your suggestions :)

@omerap12 omerap12 force-pushed the oom-feat branch 2 times, most recently from 5e23c1d to b7b84de Compare April 7, 2025 16:54
@k8s-ci-robot k8s-ci-robot added area/cluster-autoscaler area/provider/cluster-api Issues or PRs related to Cluster API provider and removed approved Indicates a PR has been approved by an approver from all required OWNERS files. labels Apr 7, 2025
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: omerap12

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Apr 7, 2025
@omerap12
Copy link
Member Author

omerap12 commented Apr 7, 2025

/remove area provider/cluster-api
/remove area/cluster-autoscaler

@omerap12
Copy link
Member Author

omerap12 commented Apr 7, 2025

/remove-area provider/cluster-api
/remove-area cluster-autoscaler

@k8s-ci-robot k8s-ci-robot removed area/provider/cluster-api Issues or PRs related to Cluster API provider area/cluster-autoscaler labels Apr 7, 2025
omerap12 added 5 commits April 7, 2025 17:14
Signed-off-by: Omer Aplatony <[email protected]>
Signed-off-by: Omer Aplatony <[email protected]>
Signed-off-by: Omer Aplatony <[email protected]>
Signed-off-by: Omer Aplatony <[email protected]>
Signed-off-by: Omer Aplatony <[email protected]>
omerap12 and others added 3 commits August 8, 2025 12:58
Co-authored-by: Adrian Moisey <[email protected]>
Signed-off-by: Omer Aplatony <[email protected]>
@k8s-ci-robot k8s-ci-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Aug 12, 2025
@k8s-ci-robot k8s-ci-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Aug 12, 2025
Signed-off-by: Omer Aplatony <[email protected]>
Signed-off-by: Omer Aplatony <[email protected]>
@adrianmoisey
Copy link
Member

/label api-review

@k8s-ci-robot k8s-ci-robot added the api-review Categorizes an issue or PR as actively needing an API review. label Aug 14, 2025
@k8s-ci-robot k8s-ci-robot added the release-note Denotes a PR that will be considered when it comes time to generate release notes. label Aug 21, 2025
Comment on lines +140 to +143
// check that perVPA is on if being used
if err := validatePerVPAFeatureFlag(&policy); err != nil {
return err
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This piece of code made me wonder if we should try move closer to how k/k validates resources. That's something for another day though

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah.. we should create a seperate issue to discuss it.

@liggitt
Copy link
Member

liggitt commented Aug 28, 2025

trying to kick the api-review label to exercise project automation
/remove-label api-review

@k8s-ci-robot k8s-ci-robot removed the api-review Categorizes an issue or PR as actively needing an API review. label Aug 28, 2025
@liggitt
Copy link
Member

liggitt commented Aug 28, 2025

/label api-review

@k8s-ci-robot k8s-ci-robot added the api-review Categorizes an issue or PR as actively needing an API review. label Aug 28, 2025
@liggitt liggitt moved this to Assigned in API Reviews Aug 28, 2025
Copy link

@soltysh soltysh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/hold
just to make sure this doesn't merge before going through proper API review


// oomMinBumpUp is the minimum increase in memory when OOM is detected.
// +optional
OOMMinBumpUp *resource.Quantity `json:"oomMinBumpUp,omitempty" protobuf:"bytes,8,opt,name=oomMinBumpUp"`
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here are several questions from API shadow review pov, and reading through AEP-8026:

  1. How does setting these two work with the global flags? The document does not have clear answer for that, but skimming this PR it seems you're leaving the flags as is, and adding this capability at VPA level.
  2. What alternatives were considered for placing both of these at container level? I don't see any discussion why it's worth setting at VPA level, pod level or container level. Which one is desired and which one makes more sense. I'd suggest thinking through questions do you really want to set it per container, and not per pod, or even per entire workload/app? What benefits you gain or loose by placing that kind of granular control at various levels.
  3. Why you need to have 2 separate fields for something that seems to express the same thing (partially at least). Why not just a single OOBumpUp defined as resource.Quantity isn't sufficient? In which case, you could express both ratio as 1.2 or percentage, or explicit bytes value.
    When you're considering exposing some of the internal configs you don't always have to expose them literally, something simpler might be sufficient here.
  4. What happens when both of these will be set? I haven't found clear answer in the doc to that question, either. Only When both oomBumpUpRatio = 1 and oomMinBumpUp = 0, OOM-based memory increases are completely disabled. Are they mutually exclusive, additive, averaged?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. I thought I had written this in the AEP - I need to check. The idea is that this setting will override the one in the global config. If the user adds it to their VPA object, those values will be applied. otherwise, the global flags will be used.
  2. Good point. We will discuss it.
  3. The core idea is not to introduce a new configuration for the VPA, but simply to expose these settings in the VPA object. I agree that this makes sense (and I’m a little embarrassed I didn’t notice it myself).
  4. This hasn't change - we are taking the max between those two:
    memoryNeeded := ResourceAmountMax(memoryUsed+MemoryAmountFromBytes(GetAggregationsConfig().OOMMinBumpUp),
    ScaleResource(memoryUsed, GetAggregationsConfig().OOMBumpUpRatio))

Copy link

@soltysh soltysh Sep 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. I thought I had written this in the AEP - I need to check. The idea is that this setting will override the one in the global config. If the user adds it to their VPA object, those values will be applied. otherwise, the global flags will be used.

Please update the AEP, and link here the update.

  1. Good point. We will discuss it.

Again, please make sure to update the AEP, accordingly.

  1. The core idea is not to introduce a new configuration for the VPA, but simply to expose these settings in the VPA object. I agree that this makes sense (and I’m a little embarrassed I didn’t notice it myself).

Again, document 😅

  1. This hasn't change - we are taking the max between those two:
    memoryNeeded := ResourceAmountMax(memoryUsed+MemoryAmountFromBytes(GetAggregationsConfig().OOMMinBumpUp),
    ScaleResource(memoryUsed, GetAggregationsConfig().OOMBumpUpRatio))

I believe, once you reconsider question 3, you'll have a better answer and just make sure to write it down.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, we submitted a PR to update the AEP here: #8505
I'll ping you once @adrianmoisey will check that out first

@liggitt liggitt moved this from Assigned to Changes requested in API Reviews Sep 11, 2025
@liggitt
Copy link
Member

liggitt commented Sep 11, 2025

/assign @soltysh @liggitt

@k8s-ci-robot k8s-ci-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Sep 24, 2025
@k8s-ci-robot
Copy link
Contributor

PR needs rebase.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@liggitt liggitt moved this from Changes requested to In progress in API Reviews Sep 24, 2025
@k8s-ci-robot
Copy link
Contributor

@omerap12: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
pull-autoscaling-e2e-vpa-full 697934c link true /test pull-autoscaling-e2e-vpa-full

Full PR test history. Your PR dashboard. Please help us cut down on flakes by linking to an open issue when you hit one in your PR.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api-review Categorizes an issue or PR as actively needing an API review. approved Indicates a PR has been approved by an approver from all required OWNERS files. area/vertical-pod-autoscaler cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. kind/api-change Categorizes issue or PR as related to adding, removing, or otherwise changing an API kind/feature Categorizes issue or PR as related to a new feature. needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. release-note Denotes a PR that will be considered when it comes time to generate release notes. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. tide/merge-method-squash Denotes a PR that should be squashed by tide when it merges.
Projects
Status: In progress
Development

Successfully merging this pull request may close these issues.

8 participants