Skip to content

Commit a7df3cf

Browse files
authored
Merge pull request #8426 from rushmash91/deprecate-auto-updatemode
feat: deprecate UpdateMode `Auto` in VPA
2 parents 172bf01 + 3d22e4c commit a7df3cf

File tree

8 files changed

+132
-6
lines changed

8 files changed

+132
-6
lines changed

vertical-pod-autoscaler/docs/api.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ _Appears in:_
218218
| `Off` | UpdateModeOff means that autoscaler never changes Pod resources.<br />The recommender still sets the recommended resources in the<br />VerticalPodAutoscaler object. This can be used for a "dry run".<br /> |
219219
| `Initial` | UpdateModeInitial means that autoscaler only assigns resources on pod<br />creation and does not change them during the lifetime of the pod.<br /> |
220220
| `Recreate` | UpdateModeRecreate means that autoscaler assigns resources on pod<br />creation and additionally can update them during the lifetime of the<br />pod by deleting and recreating the pod.<br /> |
221-
| `Auto` | UpdateModeAuto means that autoscaler assigns resources on pod creation<br />and additionally can update them during the lifetime of the pod,<br />using any available update method. Currently this is equivalent to<br />Recreate.<br /> |
221+
| `Auto` | **Deprecated** - UpdateModeAuto means that autoscaler assigns resources on pod creation<br />and additionally can update them during the lifetime of the pod,<br />using any available update method. Currently this is equivalent to<br />Recreate. **This mode is deprecated and will be removed in a future API version.**<br />**Use explicit modes like "Recreate", "Initial", or "InPlaceOrRecreate" instead.**<br />See [issue #8424](https://github.com/kubernetes/autoscaler/issues/8424) for more details.<br /> |
222222
| `InPlaceOrRecreate` | UpdateModeInPlaceOrRecreate means that autoscaler tries to assign resources in-place.<br />If this is not possible (e.g., resizing takes too long or is infeasible), it falls back to the<br />"Recreate" update mode.<br />Requires VPA level feature gate "InPlaceOrRecreate" to be enabled<br />on the admission and updater pods.<br />Requires cluster feature gate "InPlacePodVerticalScaling" to be enabled.<br /> |
223223

224224

vertical-pod-autoscaler/docs/faq.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ spec:
210210
kind: Deployment
211211
name: my-app
212212
updatePolicy:
213-
updateMode: "Auto"
213+
updateMode: "Recreate" # Use explicit mode instead of deprecated "Auto"
214214
resourcePolicy:
215215
containerPolicies:
216216
- containerName: "*"

vertical-pod-autoscaler/docs/quickstart.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@ each controller that you want to have automatically computed resource requiremen
1414
This will be most commonly a **Deployment**.
1515
There are five modes in which *VPAs* operate:
1616

17-
- `"Auto"`: VPA assigns resource requests on pod creation as well as updates
17+
- `"Auto"` (**Deprecated**): VPA assigns resource requests on pod creation as well as updates
1818
them on existing pods using the preferred update mechanism. Currently, this is
19-
equivalent to `"Recreate"` (see below).
19+
equivalent to `"Recreate"` (see below). **This mode is deprecated and will be removed in a future API version.**
20+
**Use explicit modes like "Recreate", "Initial", or "InPlaceOrRecreate" instead.**
2021
- `"Recreate"`: VPA assigns resource requests on pod creation as well as updates
2122
them on existing pods by evicting them when the requested resources differ significantly
2223
from the new recommendation (respecting the Pod Disruption Budget, if defined).
@@ -68,7 +69,7 @@ spec:
6869
kind: Deployment
6970
name: my-app
7071
updatePolicy:
71-
updateMode: "Auto"
72+
updateMode: "Recreate" # Use explicit mode instead of deprecated "Auto"
7273
```
7374
7475
## Troubleshooting

vertical-pod-autoscaler/pkg/admission-controller/logic/server.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,19 @@ import (
3131
"k8s.io/autoscaler/vertical-pod-autoscaler/pkg/admission-controller/resource/pod"
3232
"k8s.io/autoscaler/vertical-pod-autoscaler/pkg/admission-controller/resource/pod/patch"
3333
"k8s.io/autoscaler/vertical-pod-autoscaler/pkg/admission-controller/resource/vpa"
34+
vpa_types "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1"
3435
"k8s.io/autoscaler/vertical-pod-autoscaler/pkg/utils/limitrange"
3536
metrics_admission "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/utils/metrics/admission"
3637
)
3738

39+
const (
40+
vpaGroup = "autoscaling.k8s.io"
41+
vpaResource = "verticalpodautoscalers"
42+
autoDeprecationWarning = `UpdateMode "Auto" is deprecated and will be removed in a future API version. ` +
43+
`Use explicit update modes like "Recreate", "Initial", or "InPlaceOrRecreate" instead. ` +
44+
`See https://github.com/kubernetes/autoscaler/issues/8424 for more details.`
45+
)
46+
3847
// AdmissionServer is an admission webhook server that modifies pod resources request based on VPA recommendation
3948
type AdmissionServer struct {
4049
limitsChecker limitrange.LimitRangeCalculator
@@ -58,6 +67,38 @@ func (s *AdmissionServer) RegisterResourceHandler(resourceHandler resource.Handl
5867
s.resourceHandlers[resourceHandler.GroupResource()] = resourceHandler
5968
}
6069

70+
// addDeprecationWarnings adds deprecation warnings to the admission response for VPA objects using deprecated modes
71+
func (s *AdmissionServer) addDeprecationWarnings(req *admissionv1.AdmissionRequest, resp *admissionv1.AdmissionResponse) {
72+
if req.Object.Raw == nil {
73+
return
74+
}
75+
76+
// Check if this is a VPA object
77+
admittedGroupResource := metav1.GroupResource{
78+
Group: req.Resource.Group,
79+
Resource: req.Resource.Resource,
80+
}
81+
82+
if admittedGroupResource.Group != vpaGroup || admittedGroupResource.Resource != vpaResource {
83+
return
84+
}
85+
86+
var vpa vpa_types.VerticalPodAutoscaler
87+
if err := json.Unmarshal(req.Object.Raw, &vpa); err != nil {
88+
klog.V(4).InfoS("Failed to unmarshal VPA object for deprecation warning check", "err", err)
89+
return
90+
}
91+
92+
if vpa.Spec.UpdatePolicy != nil && vpa.Spec.UpdatePolicy.UpdateMode != nil &&
93+
*vpa.Spec.UpdatePolicy.UpdateMode == vpa_types.UpdateModeAuto {
94+
95+
if resp.Warnings == nil {
96+
resp.Warnings = []string{}
97+
}
98+
resp.Warnings = append(resp.Warnings, autoDeprecationWarning)
99+
}
100+
}
101+
61102
func (s *AdmissionServer) admit(ctx context.Context, data []byte) (*admissionv1.AdmissionResponse, metrics_admission.AdmissionStatus, metrics_admission.AdmissionResource) {
62103
// we don't block the admission by default, even on unparsable JSON
63104
response := admissionv1.AdmissionResponse{}
@@ -124,6 +165,9 @@ func (s *AdmissionServer) admit(ctx context.Context, data []byte) (*admissionv1.
124165
metrics_admission.OnAdmittedPod(status == metrics_admission.Applied)
125166
}
126167

168+
// Add deprecation warnings for VPA objects using deprecated modes
169+
s.addDeprecationWarnings(ar.Request, &response)
170+
127171
return &response, status, resource
128172
}
129173

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,8 @@ func (h *resourceHandler) GetPatches(_ context.Context, ar *v1.AdmissionRequest)
9595
patches := []resource.PatchRecord{}
9696
if vpa.Spec.UpdatePolicy == nil {
9797
// Sets the default updatePolicy.
98-
defaultUpdateMode := vpa_types.UpdateModeAuto
98+
// Changed from UpdateModeAuto to UpdateModeRecreate as part of Auto mode deprecation
99+
defaultUpdateMode := vpa_types.UpdateModeRecreate
99100
patches = append(patches, resource.PatchRecord{
100101
Op: "add",
101102
Path: "/spec/updatePolicy",

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,9 @@ const (
170170
// and additionally can update them during the lifetime of the pod,
171171
// using any available update method. Currently this is equivalent to
172172
// Recreate.
173+
// Deprecated: This value is deprecated and will be removed in a future API version.
174+
// Use explicit update modes like "Recreate", "Initial", or "InPlaceOrRecreate" instead.
175+
// See https://github.com/kubernetes/autoscaler/issues/8424 for more details.
173176
UpdateModeAuto UpdateMode = "Auto"
174177
// UpdateModeInPlaceOrRecreate means that autoscaler tries to assign resources in-place.
175178
// If this is not possible (e.g., resizing takes too long or is infeasible), it falls back to the

vertical-pod-autoscaler/pkg/updater/logic/updater.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,16 @@ import (
5151
vpa_api_util "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/utils/vpa"
5252
)
5353

54+
// logDeprecationWarnings logs deprecation warnings for VPAs using deprecated modes
55+
func logDeprecationWarnings(vpa *vpa_types.VerticalPodAutoscaler) {
56+
if vpa.Spec.UpdatePolicy != nil && vpa.Spec.UpdatePolicy.UpdateMode != nil &&
57+
*vpa.Spec.UpdatePolicy.UpdateMode == vpa_types.UpdateModeAuto {
58+
59+
klog.InfoS("VPA uses deprecated UpdateMode 'Auto'. This mode is deprecated and will be removed in a future API version. Please use explicit update modes like 'Recreate', 'Initial', or 'InPlaceOrRecreate'",
60+
"vpa", klog.KObj(vpa), "issue", "https://github.com/kubernetes/autoscaler/issues/8424")
61+
}
62+
}
63+
5464
// Updater performs updates on pods if recommended by Vertical Pod Autoscaler
5565
type Updater interface {
5666
// RunOnce represents single iteration in the main-loop of Updater
@@ -159,6 +169,10 @@ func (u *updater) RunOnce(ctx context.Context) {
159169
klog.V(3).InfoS("Skipping VPA object in ignored namespace", "vpa", klog.KObj(vpa), "namespace", vpa.Namespace)
160170
continue
161171
}
172+
173+
// Log deprecation warnings for VPAs using deprecated modes
174+
logDeprecationWarnings(vpa)
175+
162176
if vpa_api_util.GetUpdateMode(vpa) != vpa_types.UpdateModeRecreate &&
163177
vpa_api_util.GetUpdateMode(vpa) != vpa_types.UpdateModeAuto && vpa_api_util.GetUpdateMode(vpa) != vpa_types.UpdateModeInPlaceOrRecreate {
164178
klog.V(3).InfoS("Skipping VPA object because its mode is not \"InPlaceOrRecreate\", \"Recreate\" or \"Auto\"", "vpa", klog.KObj(vpa))

vertical-pod-autoscaler/pkg/updater/logic/updater_test.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,3 +504,66 @@ func TestNewEventRecorder(t *testing.T) {
504504
})
505505
}
506506
}
507+
508+
func TestLogDeprecationWarnings(t *testing.T) {
509+
tests := []struct {
510+
name string
511+
updateMode *vpa_types.UpdateMode
512+
updatePolicy *vpa_types.PodUpdatePolicy
513+
shouldLogWarning bool
514+
}{
515+
{
516+
name: "Auto mode should trigger deprecation warning logic",
517+
updateMode: &[]vpa_types.UpdateMode{vpa_types.UpdateModeAuto}[0],
518+
shouldLogWarning: true,
519+
},
520+
{
521+
name: "Recreate mode should not trigger warning logic",
522+
updateMode: &[]vpa_types.UpdateMode{vpa_types.UpdateModeRecreate}[0],
523+
shouldLogWarning: false,
524+
},
525+
{
526+
name: "Initial mode should not trigger warning logic",
527+
updateMode: &[]vpa_types.UpdateMode{vpa_types.UpdateModeInitial}[0],
528+
shouldLogWarning: false,
529+
},
530+
{
531+
name: "nil update policy should not trigger warning logic",
532+
updatePolicy: nil,
533+
shouldLogWarning: false,
534+
},
535+
}
536+
537+
for _, tc := range tests {
538+
t.Run(tc.name, func(t *testing.T) {
539+
var updatePolicy *vpa_types.PodUpdatePolicy
540+
if tc.updatePolicy != nil {
541+
updatePolicy = tc.updatePolicy
542+
} else if tc.updateMode != nil {
543+
updatePolicy = &vpa_types.PodUpdatePolicy{
544+
UpdateMode: tc.updateMode,
545+
}
546+
}
547+
548+
vpa := &vpa_types.VerticalPodAutoscaler{
549+
ObjectMeta: metav1.ObjectMeta{
550+
Name: "test-vpa",
551+
Namespace: "default",
552+
},
553+
Spec: vpa_types.VerticalPodAutoscalerSpec{
554+
UpdatePolicy: updatePolicy,
555+
},
556+
}
557+
558+
shouldLogWarning := vpa.Spec.UpdatePolicy != nil &&
559+
vpa.Spec.UpdatePolicy.UpdateMode != nil &&
560+
*vpa.Spec.UpdatePolicy.UpdateMode == vpa_types.UpdateModeAuto
561+
562+
assert.Equal(t, tc.shouldLogWarning, shouldLogWarning,
563+
"Expected shouldLogWarning=%v for test case %s", tc.shouldLogWarning, tc.name)
564+
565+
// Call the function to ensure it doesn't panic
566+
logDeprecationWarnings(vpa)
567+
})
568+
}
569+
}

0 commit comments

Comments
 (0)