Skip to content

Introduce API changes and fetaure gate CPU startup boost #8417

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: experimental-cpu-boost
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions vertical-pod-autoscaler/deploy/vpa-v1-crd-gen.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -372,9 +372,94 @@ spec:
- Auto
- "Off"
type: string
startupBoost:
description: |-
StartupBoost specifies the startup boost policy for the container.
This overrides any pod-level startup boost policy.
properties:
cpu:
description: |-
CPU specifies the CPU startup boost policy.
If this field is not set, no startup boost is applied.
properties:
duration:
description: |-
Duration indicates for how long to keep the pod boosted after it goes to Ready.
Defaults to 0s.
type: string
factor:
description: |-
Factor specifies the factor to apply to the CPU request.
This field is to be used only when Type is "Factor".
format: int32
type: integer
quantity:
anyOf:
- type: integer
- type: string
description: |-
Quantity specifies the absolute CPU resource quantity.
This field is to be used only when Type is "Quantity".
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
type:
description: |-
Type specifies the kind of boost to apply.
Supported values are: "Factor", "Quantity".
Defaults to "Factor".
enum:
- Factor
- Quantity
type: string
required:
- type
type: object
type: object
type: object
type: array
type: object
startupBoost:
description: StartupBoost specifies the startup boost policy for the
pod.
properties:
cpu:
description: |-
CPU specifies the CPU startup boost policy.
If this field is not set, no startup boost is applied.
properties:
duration:
description: |-
Duration indicates for how long to keep the pod boosted after it goes to Ready.
Defaults to 0s.
type: string
factor:
description: |-
Factor specifies the factor to apply to the CPU request.
This field is to be used only when Type is "Factor".
format: int32
type: integer
quantity:
anyOf:
- type: integer
- type: string
description: |-
Quantity specifies the absolute CPU resource quantity.
This field is to be used only when Type is "Quantity".
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
type:
description: |-
Type specifies the kind of boost to apply.
Supported values are: "Factor", "Quantity".
Defaults to "Factor".
enum:
- Factor
- Quantity
type: string
required:
- type
type: object
type: object
targetRef:
description: |-
TargetRef points to the controller managing the set of pods for the
Expand Down
64 changes: 61 additions & 3 deletions vertical-pod-autoscaler/docs/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- [CPU Recommendation Rounding](#cpu-recommendation-rounding)
- [Memory Recommendation Rounding](#memory-recommendation-rounding)
- [In-Place Updates](#in-place-updates-inplaceorrecreate)
- [CPU Startup Boost](#cpu-startup-boost)

## Limits control

Expand Down Expand Up @@ -80,7 +81,7 @@ To enable this feature, set the `--round-memory-bytes` flag when running the VPA

## In-Place Updates (`InPlaceOrRecreate`)

> [!WARNING]
> [!WARNING]
> FEATURE STATE: VPA v1.4.0 [alpha]

VPA supports in-place updates to reduce disruption when applying resource recommendations. This feature leverages Kubernetes' in-place update capabilities (which is in beta as of Kubernetes 1.33) to modify container resources without requiring pod recreation.
Expand Down Expand Up @@ -124,7 +125,7 @@ Enable the feature by setting the following flags in VPA components ( for both u

```bash
--feature-gates=InPlaceOrRecreate=true
```
```

### Limitations

Expand All @@ -151,4 +152,61 @@ VPA provides metrics to track in-place update operations:
* `vpa_in_place_updated_pods_total`: Number of pods successfully updated in-place
* `vpa_vpas_with_in_place_updatable_pods_total`: Number of VPAs with pods eligible for in-place updates
* `vpa_vpas_with_in_place_updated_pods_total`: Number of VPAs with successfully in-place updated pods
* `vpa_updater_failed_in_place_update_attempts_total`: Number of failed attempts to update pods in-place.
* `vpa_updater_failed_in_place_update_attempts_total`: Number of failed attempts to update pods in-place.

## CPU Startup Boost

> [!WARNING]
> FEATURE STATE: VPA v1.5.0 [alpha]

The CPU Startup Boost feature allows VPA to temporarily increase CPU requests and limits for containers during pod startup. This can help workloads that have high CPU demands during their initialization phase, such as Java applications, to start faster. Once the pod is considered `Ready` and an optional duration has passed, VPA scales the CPU resources back down to their normal levels using an in-place resize.

For more details, see [AEP-7862: CPU Startup Boost](https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler/enhancements/7862-cpu-startup-boost).

### Usage

CPU Startup Boost is configured via the `startupBoost` field in the `VerticalPodAutoscalerSpec` or within the per-container `containerPolicies`. This allows for both global and per-container boost configurations.

This example enables a startup boost for all containers in the targeted deployment. The CPU will be multiplied by a factor of 3 for 10 seconds after the pod becomes ready.

```yaml
apiVersion: "autoscaling.k8s.io/v1"
kind: VerticalPodAutoscaler
metadata:
name: example-vpa
spec:
targetRef:
apiVersion: "apps/v1"
kind: Deployment
name: example
updatePolicy:
updateMode: "Recreate"
startupBoost:
cpu:
value: "3"
duration: 10s
```

### Behavior

1. When a pod managed by the VPA is created, the VPA Admission Controller applies the CPU boost.
2. The VPA Updater monitors the pod. Once the pod's condition is `Ready` and the `startupBoost.cpu.duration` has elapsed, it scales the CPU resources down in-place.
3. The scale-down/unboost target is either the VPA recommendation (if VPA is enabled for the container) or the original CPU resources defined in the pod spec.

### Requirements

* Kubernetes 1.33+ with the `InPlacePodVerticalScaling` feature gate enabled.
* VPA version 1.5.0+ with the `CPUStartupBoost` feature gate enabled.

### Configuration

Enable the feature by setting the `CPUStartupBoost` feature gate in the VPA admission-controller and updater components:

```bash
--feature-gates=CPUStartupBoost=true
```

The `startupBoost` field has the following sub-fields:
* `cpu.type`: The type of boost. Can be `Factor` (default) to multiply the CPU, or `Quantity` to set a specific CPU value.
* `cpu.value`: The magnitude of the boost. A multiplier (e.g., "2") for `Factor` type, or a resource quantity (e.g., "500m") for `Quantity` type.
* `cpu.duration`: (Optional) How long to keep the boost active *after* the pod becomes `Ready`. Defaults to `0s`.
4 changes: 2 additions & 2 deletions vertical-pod-autoscaler/docs/flags.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ This document is auto-generated from the flag definitions in the VPA admission-c
| `address` | string | ":8944" | The address to expose Prometheus metrics. |
| `alsologtostderr` | | | log to standard error as well as files (no effect when -logtostderr=true) |
| `client-ca-file` | string | "/etc/tls-certs/caCert.pem" | Path to CA PEM file. |
| `feature-gates` | mapStringBool | | A set of key=value pairs that describe feature gates for alpha/experimental features. Options are:<br>AllAlpha=true\|false (ALPHA - default=false)<br>AllBeta=true\|false (BETA - default=false)<br>InPlaceOrRecreate=true\|false (ALPHA - default=false) |
| `feature-gates` | mapStringBool | | A set of key=value pairs that describe feature gates for alpha/experimental features. Options are:<br>AllAlpha=true\|false (ALPHA - default=false)<br>AllBeta=true\|false (BETA - default=false)<br>CPUStartupBoost=true\|false (ALPHA - default=false)<br>InPlaceOrRecreate=true\|false (ALPHA - default=false) |
| `ignored-vpa-object-namespaces` | string | | A comma-separated list of namespaces to ignore when searching for VPA objects. Leave empty to avoid ignoring any namespaces. These namespaces will not be cleaned by the garbage collector. |
| `kube-api-burst` | float | 100 | QPS burst limit when making requests to Kubernetes apiserver |
| `kube-api-qps` | float | 50 | QPS limit when making requests to Kubernetes apiserver |
Expand Down Expand Up @@ -144,7 +144,7 @@ This document is auto-generated from the flag definitions in the VPA updater cod
| `eviction-rate-burst` | int | 1 | Burst of pods that can be evicted. |
| `eviction-rate-limit` | float | | Number of pods that can be evicted per seconds. A rate limit set to 0 or -1 will disable<br>the rate limiter. (default -1) |
| `eviction-tolerance` | float | 0.5 | Fraction of replica count that can be evicted for update, if more than one pod can be evicted. |
| `feature-gates` | mapStringBool | | A set of key=value pairs that describe feature gates for alpha/experimental features. Options are:<br>AllAlpha=true\|false (ALPHA - default=false)<br>AllBeta=true\|false (BETA - default=false)<br>InPlaceOrRecreate=true\|false (ALPHA - default=false) |
| `feature-gates` | mapStringBool | | A set of key=value pairs that describe feature gates for alpha/experimental features. Options are:<br>AllAlpha=true\|false (ALPHA - default=false)<br>AllBeta=true\|false (BETA - default=false)<br>CPUStartupBoost=true\|false (ALPHA - default=false)<br>InPlaceOrRecreate=true\|false (ALPHA - default=false) |
| `ignored-vpa-object-namespaces` | string | | A comma-separated list of namespaces to ignore when searching for VPA objects. Leave empty to avoid ignoring any namespaces. These namespaces will not be cleaned by the garbage collector. |
| `in-recommendation-bounds-eviction-lifetime-threshold` | | 12h0m0s | duration Pods that live for at least that long can be evicted even if their request is within the [MinRecommended...MaxRecommended] range |
| `kube-api-burst` | float | 100 | QPS burst limit when making requests to Kubernetes apiserver |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,9 +163,16 @@ func ValidateVPA(vpa *vpa_types.VerticalPodAutoscaler, isCreate bool) error {
return fmt.Errorf("controlledValues shouldn't be specified if container scaling mode is off")
}
}
if err := validateStartupBoost(policy.StartupBoost, isCreate); err != nil {
return fmt.Errorf("invalid startupBoost in container %s: %v", policy.ContainerName, err)
}
}
}

if err := validateStartupBoost(vpa.Spec.StartupBoost, isCreate); err != nil {
return fmt.Errorf("invalid startupBoost: %v", err)
}

if isCreate && vpa.Spec.TargetRef == nil {
return fmt.Errorf("targetRef is required. If you're using v1beta1 version of the API, please migrate to v1")
}
Expand All @@ -177,6 +184,48 @@ func ValidateVPA(vpa *vpa_types.VerticalPodAutoscaler, isCreate bool) error {
return nil
}

func validateStartupBoost(startupBoost *vpa_types.StartupBoost, isCreate bool) error {
if startupBoost == nil {
return nil
}

if !features.Enabled(features.CPUStartupBoost) && isCreate {
return fmt.Errorf("in order to use startupBoost, you must enable feature gate %s in the admission-controller args", features.CPUStartupBoost)
}

cpuBoost := startupBoost.CPU
if cpuBoost == nil {
return nil
}
boostType := cpuBoost.Type
if boostType == nil {
// Default to Factor when type is not specified.
defaultType := vpa_types.FactorStartupBoostType
boostType = &defaultType
}
Comment on lines +201 to +205
Copy link
Member

Choose a reason for hiding this comment

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

I see that in the API type is marked as required, I'm wondering if that is incorrect?

Copy link
Contributor Author

@kamarabbas99 kamarabbas99 Aug 11, 2025

Choose a reason for hiding this comment

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

Made the API field optional with default value of Factor.


if *boostType != vpa_types.FactorStartupBoostType && *boostType != vpa_types.QuantityStartupBoostType {
return fmt.Errorf("unexpected StartupBoost.CPU.Type value %s", *boostType)
}

if *boostType == vpa_types.FactorStartupBoostType {
if cpuBoost.Factor == nil {
return fmt.Errorf("StartupBoost.CPU.Factor is required when Type is Factor")
}
if *cpuBoost.Factor < 1 {
return fmt.Errorf("invalid StartupBoost.CPU.Factor: must be >= 1 for Type Factor")
}
} else if *boostType == vpa_types.QuantityStartupBoostType {
if cpuBoost.Quantity == nil {
return fmt.Errorf("StartupBoost.CPU.Quantity is required when Type is Quantity")
}
if err := validateCPUResolution(*cpuBoost.Quantity); err != nil {
return fmt.Errorf("invalid StartupBoost.CPU.Quantity: %v", err)
}
}
return nil
Copy link
Contributor

Choose a reason for hiding this comment

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

what about checking if both Factor and Quantity are set at the same time? (So we ensure only one of them is set at a time)

Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

Awesome, I missed that! Thanks @omerap12

}

func validateResourceResolution(name corev1.ResourceName, val apires.Quantity) error {
switch name {
case corev1.ResourceCPU:
Expand Down
Loading
Loading