Skip to content

Commit 656a69f

Browse files
authored
Merge pull request #7961 from maxcao13/in-place-updates-admission
VPA: (InPlaceOrRecreate) Allow admission-controller to validate in-place spec
2 parents 4486391 + a0cf017 commit 656a69f

File tree

2 files changed

+57
-8
lines changed

2 files changed

+57
-8
lines changed

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

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,17 @@ import (
3030

3131
"k8s.io/autoscaler/vertical-pod-autoscaler/pkg/admission-controller/resource"
3232
vpa_types "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1"
33+
"k8s.io/autoscaler/vertical-pod-autoscaler/pkg/features"
3334
"k8s.io/autoscaler/vertical-pod-autoscaler/pkg/utils/metrics/admission"
3435
)
3536

3637
var (
3738
possibleUpdateModes = map[vpa_types.UpdateMode]interface{}{
38-
vpa_types.UpdateModeOff: struct{}{},
39-
vpa_types.UpdateModeInitial: struct{}{},
40-
vpa_types.UpdateModeRecreate: struct{}{},
41-
vpa_types.UpdateModeAuto: struct{}{},
39+
vpa_types.UpdateModeOff: struct{}{},
40+
vpa_types.UpdateModeInitial: struct{}{},
41+
vpa_types.UpdateModeRecreate: struct{}{},
42+
vpa_types.UpdateModeAuto: struct{}{},
43+
vpa_types.UpdateModeInPlaceOrRecreate: struct{}{},
4244
}
4345

4446
possibleScalingModes = map[vpa_types.ContainerScalingMode]interface{}{
@@ -121,6 +123,9 @@ func ValidateVPA(vpa *vpa_types.VerticalPodAutoscaler, isCreate bool) error {
121123
if _, found := possibleUpdateModes[*mode]; !found {
122124
return fmt.Errorf("unexpected UpdateMode value %s", *mode)
123125
}
126+
if (*mode == vpa_types.UpdateModeInPlaceOrRecreate) && !features.Enabled(features.InPlaceOrRecreate) && isCreate {
127+
return fmt.Errorf("in order to use UpdateMode %s, you must enable feature gate %s in the admission-controller args", vpa_types.UpdateModeInPlaceOrRecreate, features.InPlaceOrRecreate)
128+
}
124129

125130
if minReplicas := vpa.Spec.UpdatePolicy.MinReplicas; minReplicas != nil && *minReplicas <= 0 {
126131
return fmt.Errorf("MinReplicas has to be positive, got %v", *minReplicas)

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

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@ import (
2424
apiv1 "k8s.io/api/core/v1"
2525
"k8s.io/apimachinery/pkg/api/resource"
2626

27+
featuregatetesting "k8s.io/component-base/featuregate/testing"
28+
2729
vpa_types "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1"
30+
"k8s.io/autoscaler/vertical-pod-autoscaler/pkg/features"
2831
)
2932

3033
const (
@@ -42,11 +45,13 @@ func TestValidateVPA(t *testing.T) {
4245
validScalingMode := vpa_types.ContainerScalingModeAuto
4346
scalingModeOff := vpa_types.ContainerScalingModeOff
4447
controlledValuesRequestsAndLimits := vpa_types.ContainerControlledValuesRequestsAndLimits
48+
inPlaceOrRecreateUpdateMode := vpa_types.UpdateModeInPlaceOrRecreate
4549
tests := []struct {
46-
name string
47-
vpa vpa_types.VerticalPodAutoscaler
48-
isCreate bool
49-
expectError error
50+
name string
51+
vpa vpa_types.VerticalPodAutoscaler
52+
isCreate bool
53+
expectError error
54+
inPlaceOrRecreateFeatureGateDisabled bool
5055
}{
5156
{
5257
name: "empty update",
@@ -78,6 +83,42 @@ func TestValidateVPA(t *testing.T) {
7883
},
7984
expectError: fmt.Errorf("unexpected UpdateMode value bad"),
8085
},
86+
{
87+
name: "creating VPA with InPlaceOrRecreate update mode not allowed by disabled feature gate",
88+
vpa: vpa_types.VerticalPodAutoscaler{
89+
Spec: vpa_types.VerticalPodAutoscalerSpec{
90+
UpdatePolicy: &vpa_types.PodUpdatePolicy{
91+
UpdateMode: &inPlaceOrRecreateUpdateMode,
92+
},
93+
},
94+
},
95+
isCreate: true,
96+
inPlaceOrRecreateFeatureGateDisabled: true,
97+
expectError: fmt.Errorf("in order to use UpdateMode %s, you must enable feature gate %s in the admission-controller args", vpa_types.UpdateModeInPlaceOrRecreate, features.InPlaceOrRecreate),
98+
},
99+
{
100+
name: "updating VPA with InPlaceOrRecreate update mode allowed by disabled feature gate",
101+
vpa: vpa_types.VerticalPodAutoscaler{
102+
Spec: vpa_types.VerticalPodAutoscalerSpec{
103+
UpdatePolicy: &vpa_types.PodUpdatePolicy{
104+
UpdateMode: &inPlaceOrRecreateUpdateMode,
105+
},
106+
},
107+
},
108+
isCreate: false,
109+
inPlaceOrRecreateFeatureGateDisabled: true,
110+
expectError: nil,
111+
},
112+
{
113+
name: "InPlaceOrRecreate update mode enabled by feature gate",
114+
vpa: vpa_types.VerticalPodAutoscaler{
115+
Spec: vpa_types.VerticalPodAutoscalerSpec{
116+
UpdatePolicy: &vpa_types.PodUpdatePolicy{
117+
UpdateMode: &inPlaceOrRecreateUpdateMode,
118+
},
119+
},
120+
},
121+
},
81122
{
82123
name: "zero minReplicas",
83124
vpa: vpa_types.VerticalPodAutoscaler{
@@ -282,6 +323,9 @@ func TestValidateVPA(t *testing.T) {
282323
}
283324
for _, tc := range tests {
284325
t.Run(fmt.Sprintf("test case: %s", tc.name), func(t *testing.T) {
326+
if !tc.inPlaceOrRecreateFeatureGateDisabled {
327+
featuregatetesting.SetFeatureGateDuringTest(t, features.MutableFeatureGate, features.InPlaceOrRecreate, true)
328+
}
285329
err := ValidateVPA(&tc.vpa, tc.isCreate)
286330
if tc.expectError == nil {
287331
assert.NoError(t, err)

0 commit comments

Comments
 (0)