Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ spec:
factor:
description: |-
factor specifies the factor to apply to the resource request.
This field is to be used only when Type is "Factor".
This field is required when Type is "Factor".
format: int32
type: integer
quantity:
Expand All @@ -418,7 +418,7 @@ spec:
description: |-
quantity specifies the absolute resource quantity to be used as the
resource request and limit during the boost phase.
This field is to be used only when Type is "Quantity".
This field is required 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:
Expand Down Expand Up @@ -453,7 +453,7 @@ spec:
factor:
description: |-
factor specifies the factor to apply to the resource request.
This field is to be used only when Type is "Factor".
This field is required when Type is "Factor".
format: int32
type: integer
quantity:
Expand All @@ -463,7 +463,7 @@ spec:
description: |-
quantity specifies the absolute resource quantity to be used as the
resource request and limit during the boost phase.
This field is to be used only when Type is "Quantity".
This field is required 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:
Expand Down
8 changes: 4 additions & 4 deletions vertical-pod-autoscaler/deploy/vpa-v1-crd-gen.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ spec:
factor:
description: |-
factor specifies the factor to apply to the resource request.
This field is to be used only when Type is "Factor".
This field is required when Type is "Factor".
format: int32
type: integer
quantity:
Expand All @@ -418,7 +418,7 @@ spec:
description: |-
quantity specifies the absolute resource quantity to be used as the
resource request and limit during the boost phase.
This field is to be used only when Type is "Quantity".
This field is required 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:
Expand Down Expand Up @@ -453,7 +453,7 @@ spec:
factor:
description: |-
factor specifies the factor to apply to the resource request.
This field is to be used only when Type is "Factor".
This field is required when Type is "Factor".
format: int32
type: integer
quantity:
Expand All @@ -463,7 +463,7 @@ spec:
description: |-
quantity specifies the absolute resource quantity to be used as the
resource request and limit during the boost phase.
This field is to be used only when Type is "Quantity".
This field is required 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:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ type CPUStartupBoost struct {

> [!IMPORTANT]
> The boosted CPU value will be capped by
> [`--container-recommendation-max-allowed-cpu`](https://github.com/kubernetes/autoscaler/blob/4d294562e505431d518a81e8833accc0ec99c9b8/vertical-pod-autoscaler/pkg/recommender/main.go#L122)
> [`--max-allowed-cpu-boost`](https://github.com/kubernetes/autoscaler/blob/4b40a55bebd2ce184b289cd028969182d15f412c/vertical-pod-autoscaler/pkg/admission-controller/main.go#L86C1-L86C2)
> flag value, if set.

> [!NOTE]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -730,6 +730,75 @@ func TestCalculatePatches_StartupBoost(t *testing.T) {
GetAddAnnotationPatch(ResourceUpdatesAnnotation, "Pod resources updated by name: container 0: cpu request"),
},
},
{
name: "startup boost invalid type",
pod: &core.Pod{
Spec: core.PodSpec{
Containers: []core.Container{
{
Name: "container1",
Resources: core.ResourceRequirements{
Requests: core.ResourceList{
cpu: resource.MustParse("1m"),
},
},
},
},
},
},
vpa: test.VerticalPodAutoscaler().WithName("name").WithContainer("container1").WithCPUStartupBoost("Invalid", &factor2, nil, "10s").Get(),
recommendResources: []vpa_api_util.ContainerResources{
{
Requests: core.ResourceList{
cpu: resource.MustParse("100m"),
},
},
},
maxAllowedCpu: resource.QuantityValue{},
featureGateEnabled: true,
expectError: fmt.Errorf("unsupported startup boost type: Invalid"),
},
{
name: "startup boost container policy takes precedence",
pod: &core.Pod{
Spec: core.PodSpec{
Containers: []core.Container{
{
Name: "container1",
Resources: core.ResourceRequirements{
Requests: core.ResourceList{
cpu: resource.MustParse("1m"),
},
Limits: core.ResourceList{
cpu: resource.MustParse("1m"),
},
},
},
},
},
},
vpa: test.VerticalPodAutoscaler().WithName("name").WithContainer("container1").
WithCPUStartupBoost(vpa_types.FactorStartupBoostType, &factor2, nil, "10s").
WithContainerCPUStartupBoost("container1", vpa_types.FactorStartupBoostType, &factor3, nil, "10s").Get(),
recommendResources: []vpa_api_util.ContainerResources{
{
Requests: core.ResourceList{
cpu: resource.MustParse("100m"),
},
Limits: core.ResourceList{
cpu: resource.MustParse("100m"),
},
},
},
maxAllowedCpu: resource.QuantityValue{},
featureGateEnabled: true,
expectPatches: []resource_admission.PatchRecord{
GetAddAnnotationPatch(annotations.StartupCPUBoostAnnotation, "{\"requests\":{\"cpu\":\"1m\"},\"limits\":{\"cpu\":\"1m\"}}"),
addResourceRequestPatch(0, cpu, "300m"),
addResourceLimitPatch(0, cpu, "300m"),
GetAddAnnotationPatch(ResourceUpdatesAnnotation, "Pod resources updated by name: container 0: cpu request, cpu limit"),
},
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,37 @@ func TestValidateVPA(t *testing.T) {
},
isCreate: true,
},
{
name: "top-level and container startupBoost",
vpa: vpa_types.VerticalPodAutoscaler{
Spec: vpa_types.VerticalPodAutoscalerSpec{
TargetRef: &autoscaling.CrossVersionObjectReference{
Kind: "Deployment",
Name: "my-app",
},
StartupBoost: &vpa_types.StartupBoost{
CPU: &vpa_types.GenericStartupBoost{
Type: validCPUBoostTypeFactor,
Factor: &validCPUBoostFactor,
},
},
ResourcePolicy: &vpa_types.PodResourcePolicy{
ContainerPolicies: []vpa_types.ContainerResourcePolicy{
{
ContainerName: "loot box",
StartupBoost: &vpa_types.StartupBoost{
CPU: &vpa_types.GenericStartupBoost{
Type: validCPUBoostTypeQuantity,
Quantity: &validCPUBoostQuantity,
},
},
},
},
},
},
},
isCreate: true,
},
{
name: "per-vpa config active and used",
vpa: vpa_types.VerticalPodAutoscaler{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,14 +131,14 @@ type GenericStartupBoost struct {
// +required
Type StartupBoostType `json:"type" protobuf:"bytes,1,opt,name=type"`
// factor specifies the factor to apply to the resource request.
// This field is to be used only when Type is "Factor".
// This field is required when Type is "Factor".
Copy link
Contributor

Choose a reason for hiding this comment

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

The schema sets this to +optional. How are we going to inforce this conditional requirement?

Copy link
Member

Choose a reason for hiding this comment

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

It may be best to rather review #8813, this PR is just addressing comments made in that PR, and it's missing lots of context. (note that this is a PR into a feature branch)

See https://github.com/kubernetes/autoscaler/pull/8813/files#diff-ad66c76a76541b7991631925641b989fc402901440d8e0dcbc3591009eef52b9

Copy link
Contributor

Choose a reason for hiding this comment

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

We will error out in the handler, which should be then exposed to the user that the object is miconfigured. Sadly we can't express that condition in through annotations.

// +unionMember=Factor
// +optional
Factor *int32 `json:"factor,omitempty" protobuf:"bytes,2,opt,name=factor"`

// quantity specifies the absolute resource quantity to be used as the
// resource request and limit during the boost phase.
// This field is to be used only when Type is "Quantity".
// This field is required when Type is "Quantity".
// +unionMember=Quantity
// +optional
Quantity *resource.Quantity `json:"quantity,omitempty" protobuf:"bytes,3,opt,name=quantity"`
Expand Down
26 changes: 25 additions & 1 deletion vertical-pod-autoscaler/pkg/utils/test/test_vpa.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ type VerticalPodAutoscalerBuilder interface {
WithOOMBumpUpRatio(ratio *resource.Quantity) VerticalPodAutoscalerBuilder
WithOOMMinBumpUp(minBumpUp *resource.Quantity) VerticalPodAutoscalerBuilder
WithCPUStartupBoost(boostType vpa_types.StartupBoostType, factor *int32, quantity *resource.Quantity, duration string) VerticalPodAutoscalerBuilder
WithContainerCPUStartupBoost(containerName string, boostType vpa_types.StartupBoostType, factor *int32, quantity *resource.Quantity, duration string) VerticalPodAutoscalerBuilder
AppendCondition(conditionType vpa_types.VerticalPodAutoscalerConditionType,
status core.ConditionStatus, reason, message string, lastTransitionTime time.Time) VerticalPodAutoscalerBuilder
AppendRecommendation(vpa_types.RecommendedContainerResources) VerticalPodAutoscalerBuilder
Expand All @@ -71,6 +72,7 @@ func VerticalPodAutoscaler() VerticalPodAutoscalerBuilder {
maxAllowed: map[string]core.ResourceList{},
controlledValues: map[string]*vpa_types.ContainerControlledValues{},
scalingMode: map[string]*vpa_types.ContainerScalingMode{},
containerStartupBoost: map[string]*vpa_types.StartupBoost{},
}
}

Expand All @@ -85,6 +87,7 @@ type verticalPodAutoscalerBuilder struct {
maxAllowed map[string]core.ResourceList
controlledValues map[string]*vpa_types.ContainerControlledValues
scalingMode map[string]*vpa_types.ContainerScalingMode
containerStartupBoost map[string]*vpa_types.StartupBoost
startupBoost *vpa_types.StartupBoost
recommendation RecommendationBuilder
conditions []vpa_types.VerticalPodAutoscalerCondition
Expand Down Expand Up @@ -260,7 +263,8 @@ func (b *verticalPodAutoscalerBuilder) WithCPUStartupBoost(boostType vpa_types.S
}
if factor != nil {
cpuStartupBoost.Factor = factor
} else {
}
if quantity != nil {
cpuStartupBoost.Quantity = quantity
}
c.startupBoost = &vpa_types.StartupBoost{
Expand All @@ -269,6 +273,25 @@ func (b *verticalPodAutoscalerBuilder) WithCPUStartupBoost(boostType vpa_types.S
return &c
}

func (b *verticalPodAutoscalerBuilder) WithContainerCPUStartupBoost(containerName string, boostType vpa_types.StartupBoostType, factor *int32, quantity *resource.Quantity, duration string) VerticalPodAutoscalerBuilder {
c := *b
parsedDuration, _ := time.ParseDuration(duration)
cpuStartupBoost := &vpa_types.GenericStartupBoost{
Type: boostType,
Duration: &meta.Duration{Duration: parsedDuration},
}
if factor != nil {
cpuStartupBoost.Factor = factor
}
if quantity != nil {
cpuStartupBoost.Quantity = quantity
}
c.containerStartupBoost[containerName] = &vpa_types.StartupBoost{
CPU: cpuStartupBoost,
}
return &c
}

func (b *verticalPodAutoscalerBuilder) Get() *vpa_types.VerticalPodAutoscaler {
if len(b.containerNames) == 0 {
panic("Must call WithContainer() before Get()")
Expand All @@ -289,6 +312,7 @@ func (b *verticalPodAutoscalerBuilder) Get() *vpa_types.VerticalPodAutoscaler {
Mode: &scalingModeAuto,
OOMBumpUpRatio: b.oomBumpUpRatio,
OOMMinBumpUp: b.oomMinBumpUp,
StartupBoost: b.containerStartupBoost[containerName],
}
if scalingMode, ok := b.scalingMode[containerName]; ok {
containerResourcePolicy.Mode = scalingMode
Expand Down