From 9cb7d58b3c7770016bfeddd3349007b2d82af6f8 Mon Sep 17 00:00:00 2001 From: carlory Date: Wed, 30 Oct 2024 10:43:06 +0800 Subject: [PATCH] Tighten validation on the qosClass field of pod status --- pkg/apis/core/validation/validation.go | 3 +++ pkg/apis/core/validation/validation_test.go | 26 +++++++++++++++++++++ pkg/registry/core/pod/strategy.go | 5 ++++ 3 files changed, 34 insertions(+) diff --git a/pkg/apis/core/validation/validation.go b/pkg/apis/core/validation/validation.go index 01d12a036d3..488503db7f4 100644 --- a/pkg/apis/core/validation/validation.go +++ b/pkg/apis/core/validation/validation.go @@ -5373,6 +5373,9 @@ func ValidatePodStatusUpdate(newPod, oldPod *core.Pod, opts PodValidationOptions } } + // Pod QoS is immutable + allErrs = append(allErrs, ValidateImmutableField(newPod.Status.QOSClass, oldPod.Status.QOSClass, fldPath.Child("qosClass"))...) + // If pod should not restart, make sure the status update does not transition // any terminated containers to a non-terminated state. allErrs = append(allErrs, ValidateContainerStateTransition(newPod.Status.ContainerStatuses, oldPod.Status.ContainerStatuses, fldPath.Child("containerStatuses"), oldPod.Spec.RestartPolicy)...) diff --git a/pkg/apis/core/validation/validation_test.go b/pkg/apis/core/validation/validation_test.go index a4e9325e8d1..4a483c766de 100644 --- a/pkg/apis/core/validation/validation_test.go +++ b/pkg/apis/core/validation/validation_test.go @@ -14454,6 +14454,32 @@ func TestValidatePodStatusUpdate(t *testing.T) { ), "", "restartable init container can restart if RestartPolicyAlways", + }, { + *podtest.MakePod("foo", + podtest.SetStatus(core.PodStatus{ + QOSClass: core.PodQOSBurstable, + }), + ), + *podtest.MakePod("foo", + podtest.SetStatus(core.PodStatus{ + QOSClass: core.PodQOSGuaranteed, + }), + ), + "tatus.qosClass: Invalid value: \"Burstable\": field is immutable", + "qosClass can not be changed", + }, { + *podtest.MakePod("foo", + podtest.SetStatus(core.PodStatus{ + QOSClass: core.PodQOSBurstable, + }), + ), + *podtest.MakePod("foo", + podtest.SetStatus(core.PodStatus{ + QOSClass: core.PodQOSBurstable, + }), + ), + "", + "qosClass no change", }, } diff --git a/pkg/registry/core/pod/strategy.go b/pkg/registry/core/pod/strategy.go index 3478fcc69b2..541fc43a220 100644 --- a/pkg/registry/core/pod/strategy.go +++ b/pkg/registry/core/pod/strategy.go @@ -226,6 +226,11 @@ func (podStatusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime. // don't allow the pods/status endpoint to touch owner references since old kubelets corrupt them in a way // that breaks garbage collection newPod.OwnerReferences = oldPod.OwnerReferences + // the Pod QoS is immutable and populated at creation time by the kube-apiserver. + // we need to backfill it for backward compatibility because the old kubelet dropped this field when the pod was rejected. + if newPod.Status.QOSClass == "" { + newPod.Status.QOSClass = oldPod.Status.QOSClass + } } func (podStatusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {