Skip to content

Commit d7c901f

Browse files
authored
Merge pull request #8828 from kamarabbas99/experimental-cpu-boost-v2
CPU startup boost: add tests
2 parents 4b40a55 + 1c2f5c0 commit d7c901f

File tree

7 files changed

+136
-12
lines changed

7 files changed

+136
-12
lines changed

vertical-pod-autoscaler/charts/vertical-pod-autoscaler/crds/vpa-v1-crd-gen.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ spec:
408408
factor:
409409
description: |-
410410
factor specifies the factor to apply to the resource request.
411-
This field is to be used only when Type is "Factor".
411+
This field is required when Type is "Factor".
412412
format: int32
413413
type: integer
414414
quantity:
@@ -418,7 +418,7 @@ spec:
418418
description: |-
419419
quantity specifies the absolute resource quantity to be used as the
420420
resource request and limit during the boost phase.
421-
This field is to be used only when Type is "Quantity".
421+
This field is required when Type is "Quantity".
422422
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
423423
x-kubernetes-int-or-string: true
424424
type:
@@ -453,7 +453,7 @@ spec:
453453
factor:
454454
description: |-
455455
factor specifies the factor to apply to the resource request.
456-
This field is to be used only when Type is "Factor".
456+
This field is required when Type is "Factor".
457457
format: int32
458458
type: integer
459459
quantity:
@@ -463,7 +463,7 @@ spec:
463463
description: |-
464464
quantity specifies the absolute resource quantity to be used as the
465465
resource request and limit during the boost phase.
466-
This field is to be used only when Type is "Quantity".
466+
This field is required when Type is "Quantity".
467467
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
468468
x-kubernetes-int-or-string: true
469469
type:

vertical-pod-autoscaler/deploy/vpa-v1-crd-gen.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ spec:
408408
factor:
409409
description: |-
410410
factor specifies the factor to apply to the resource request.
411-
This field is to be used only when Type is "Factor".
411+
This field is required when Type is "Factor".
412412
format: int32
413413
type: integer
414414
quantity:
@@ -418,7 +418,7 @@ spec:
418418
description: |-
419419
quantity specifies the absolute resource quantity to be used as the
420420
resource request and limit during the boost phase.
421-
This field is to be used only when Type is "Quantity".
421+
This field is required when Type is "Quantity".
422422
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
423423
x-kubernetes-int-or-string: true
424424
type:
@@ -453,7 +453,7 @@ spec:
453453
factor:
454454
description: |-
455455
factor specifies the factor to apply to the resource request.
456-
This field is to be used only when Type is "Factor".
456+
This field is required when Type is "Factor".
457457
format: int32
458458
type: integer
459459
quantity:
@@ -463,7 +463,7 @@ spec:
463463
description: |-
464464
quantity specifies the absolute resource quantity to be used as the
465465
resource request and limit during the boost phase.
466-
This field is to be used only when Type is "Quantity".
466+
This field is required when Type is "Quantity".
467467
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
468468
x-kubernetes-int-or-string: true
469469
type:

vertical-pod-autoscaler/enhancements/7862-cpu-startup-boost/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ type CPUStartupBoost struct {
159159

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

vertical-pod-autoscaler/pkg/admission-controller/resource/pod/patch/resource_updates_test.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -730,6 +730,75 @@ func TestCalculatePatches_StartupBoost(t *testing.T) {
730730
GetAddAnnotationPatch(ResourceUpdatesAnnotation, "Pod resources updated by name: container 0: cpu request"),
731731
},
732732
},
733+
{
734+
name: "startup boost invalid type",
735+
pod: &core.Pod{
736+
Spec: core.PodSpec{
737+
Containers: []core.Container{
738+
{
739+
Name: "container1",
740+
Resources: core.ResourceRequirements{
741+
Requests: core.ResourceList{
742+
cpu: resource.MustParse("1m"),
743+
},
744+
},
745+
},
746+
},
747+
},
748+
},
749+
vpa: test.VerticalPodAutoscaler().WithName("name").WithContainer("container1").WithCPUStartupBoost("Invalid", &factor2, nil, "10s").Get(),
750+
recommendResources: []vpa_api_util.ContainerResources{
751+
{
752+
Requests: core.ResourceList{
753+
cpu: resource.MustParse("100m"),
754+
},
755+
},
756+
},
757+
maxAllowedCpu: resource.QuantityValue{},
758+
featureGateEnabled: true,
759+
expectError: fmt.Errorf("unsupported startup boost type: Invalid"),
760+
},
761+
{
762+
name: "startup boost container policy takes precedence",
763+
pod: &core.Pod{
764+
Spec: core.PodSpec{
765+
Containers: []core.Container{
766+
{
767+
Name: "container1",
768+
Resources: core.ResourceRequirements{
769+
Requests: core.ResourceList{
770+
cpu: resource.MustParse("1m"),
771+
},
772+
Limits: core.ResourceList{
773+
cpu: resource.MustParse("1m"),
774+
},
775+
},
776+
},
777+
},
778+
},
779+
},
780+
vpa: test.VerticalPodAutoscaler().WithName("name").WithContainer("container1").
781+
WithCPUStartupBoost(vpa_types.FactorStartupBoostType, &factor2, nil, "10s").
782+
WithContainerCPUStartupBoost("container1", vpa_types.FactorStartupBoostType, &factor3, nil, "10s").Get(),
783+
recommendResources: []vpa_api_util.ContainerResources{
784+
{
785+
Requests: core.ResourceList{
786+
cpu: resource.MustParse("100m"),
787+
},
788+
Limits: core.ResourceList{
789+
cpu: resource.MustParse("100m"),
790+
},
791+
},
792+
},
793+
maxAllowedCpu: resource.QuantityValue{},
794+
featureGateEnabled: true,
795+
expectPatches: []resource_admission.PatchRecord{
796+
GetAddAnnotationPatch(annotations.StartupCPUBoostAnnotation, "{\"requests\":{\"cpu\":\"1m\"},\"limits\":{\"cpu\":\"1m\"}}"),
797+
addResourceRequestPatch(0, cpu, "300m"),
798+
addResourceLimitPatch(0, cpu, "300m"),
799+
GetAddAnnotationPatch(ResourceUpdatesAnnotation, "Pod resources updated by name: container 0: cpu request, cpu limit"),
800+
},
801+
},
733802
}
734803
for _, tc := range tests {
735804
t.Run(tc.name, func(t *testing.T) {

vertical-pod-autoscaler/pkg/admission-controller/resource/vpa/handler_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -602,6 +602,37 @@ func TestValidateVPA(t *testing.T) {
602602
},
603603
isCreate: true,
604604
},
605+
{
606+
name: "top-level and container startupBoost",
607+
vpa: vpa_types.VerticalPodAutoscaler{
608+
Spec: vpa_types.VerticalPodAutoscalerSpec{
609+
TargetRef: &autoscaling.CrossVersionObjectReference{
610+
Kind: "Deployment",
611+
Name: "my-app",
612+
},
613+
StartupBoost: &vpa_types.StartupBoost{
614+
CPU: &vpa_types.GenericStartupBoost{
615+
Type: validCPUBoostTypeFactor,
616+
Factor: &validCPUBoostFactor,
617+
},
618+
},
619+
ResourcePolicy: &vpa_types.PodResourcePolicy{
620+
ContainerPolicies: []vpa_types.ContainerResourcePolicy{
621+
{
622+
ContainerName: "loot box",
623+
StartupBoost: &vpa_types.StartupBoost{
624+
CPU: &vpa_types.GenericStartupBoost{
625+
Type: validCPUBoostTypeQuantity,
626+
Quantity: &validCPUBoostQuantity,
627+
},
628+
},
629+
},
630+
},
631+
},
632+
},
633+
},
634+
isCreate: true,
635+
},
605636
{
606637
name: "per-vpa config active and used",
607638
vpa: vpa_types.VerticalPodAutoscaler{

vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1/types.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,14 +131,14 @@ type GenericStartupBoost struct {
131131
// +required
132132
Type StartupBoostType `json:"type" protobuf:"bytes,1,opt,name=type"`
133133
// factor specifies the factor to apply to the resource request.
134-
// This field is to be used only when Type is "Factor".
134+
// This field is required when Type is "Factor".
135135
// +unionMember=Factor
136136
// +optional
137137
Factor *int32 `json:"factor,omitempty" protobuf:"bytes,2,opt,name=factor"`
138138

139139
// quantity specifies the absolute resource quantity to be used as the
140140
// resource request and limit during the boost phase.
141-
// This field is to be used only when Type is "Quantity".
141+
// This field is required when Type is "Quantity".
142142
// +unionMember=Quantity
143143
// +optional
144144
Quantity *resource.Quantity `json:"quantity,omitempty" protobuf:"bytes,3,opt,name=quantity"`

vertical-pod-autoscaler/pkg/utils/test/test_vpa.go

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ type VerticalPodAutoscalerBuilder interface {
5151
WithOOMBumpUpRatio(ratio *resource.Quantity) VerticalPodAutoscalerBuilder
5252
WithOOMMinBumpUp(minBumpUp *resource.Quantity) VerticalPodAutoscalerBuilder
5353
WithCPUStartupBoost(boostType vpa_types.StartupBoostType, factor *int32, quantity *resource.Quantity, duration string) VerticalPodAutoscalerBuilder
54+
WithContainerCPUStartupBoost(containerName string, boostType vpa_types.StartupBoostType, factor *int32, quantity *resource.Quantity, duration string) VerticalPodAutoscalerBuilder
5455
AppendCondition(conditionType vpa_types.VerticalPodAutoscalerConditionType,
5556
status core.ConditionStatus, reason, message string, lastTransitionTime time.Time) VerticalPodAutoscalerBuilder
5657
AppendRecommendation(vpa_types.RecommendedContainerResources) VerticalPodAutoscalerBuilder
@@ -71,6 +72,7 @@ func VerticalPodAutoscaler() VerticalPodAutoscalerBuilder {
7172
maxAllowed: map[string]core.ResourceList{},
7273
controlledValues: map[string]*vpa_types.ContainerControlledValues{},
7374
scalingMode: map[string]*vpa_types.ContainerScalingMode{},
75+
containerStartupBoost: map[string]*vpa_types.StartupBoost{},
7476
}
7577
}
7678

@@ -85,6 +87,7 @@ type verticalPodAutoscalerBuilder struct {
8587
maxAllowed map[string]core.ResourceList
8688
controlledValues map[string]*vpa_types.ContainerControlledValues
8789
scalingMode map[string]*vpa_types.ContainerScalingMode
90+
containerStartupBoost map[string]*vpa_types.StartupBoost
8891
startupBoost *vpa_types.StartupBoost
8992
recommendation RecommendationBuilder
9093
conditions []vpa_types.VerticalPodAutoscalerCondition
@@ -260,7 +263,8 @@ func (b *verticalPodAutoscalerBuilder) WithCPUStartupBoost(boostType vpa_types.S
260263
}
261264
if factor != nil {
262265
cpuStartupBoost.Factor = factor
263-
} else {
266+
}
267+
if quantity != nil {
264268
cpuStartupBoost.Quantity = quantity
265269
}
266270
c.startupBoost = &vpa_types.StartupBoost{
@@ -269,6 +273,25 @@ func (b *verticalPodAutoscalerBuilder) WithCPUStartupBoost(boostType vpa_types.S
269273
return &c
270274
}
271275

276+
func (b *verticalPodAutoscalerBuilder) WithContainerCPUStartupBoost(containerName string, boostType vpa_types.StartupBoostType, factor *int32, quantity *resource.Quantity, duration string) VerticalPodAutoscalerBuilder {
277+
c := *b
278+
parsedDuration, _ := time.ParseDuration(duration)
279+
cpuStartupBoost := &vpa_types.GenericStartupBoost{
280+
Type: boostType,
281+
Duration: &meta.Duration{Duration: parsedDuration},
282+
}
283+
if factor != nil {
284+
cpuStartupBoost.Factor = factor
285+
}
286+
if quantity != nil {
287+
cpuStartupBoost.Quantity = quantity
288+
}
289+
c.containerStartupBoost[containerName] = &vpa_types.StartupBoost{
290+
CPU: cpuStartupBoost,
291+
}
292+
return &c
293+
}
294+
272295
func (b *verticalPodAutoscalerBuilder) Get() *vpa_types.VerticalPodAutoscaler {
273296
if len(b.containerNames) == 0 {
274297
panic("Must call WithContainer() before Get()")
@@ -289,6 +312,7 @@ func (b *verticalPodAutoscalerBuilder) Get() *vpa_types.VerticalPodAutoscaler {
289312
Mode: &scalingModeAuto,
290313
OOMBumpUpRatio: b.oomBumpUpRatio,
291314
OOMMinBumpUp: b.oomMinBumpUp,
315+
StartupBoost: b.containerStartupBoost[containerName],
292316
}
293317
if scalingMode, ok := b.scalingMode[containerName]; ok {
294318
containerResourcePolicy.Mode = scalingMode

0 commit comments

Comments
 (0)