From be90f569f35f2a297a9023dbdc61ca497423a3b1 Mon Sep 17 00:00:00 2001 From: Tim Allclair Date: Wed, 4 Nov 2026 00:31:19 +0000 Subject: [PATCH] Remove InPlacePodVerticalScaling feature gate The InPlacePodVerticalScaling feature gate has been GA and locked to true since v1.35, and is now removed. Code paths that handled the disabled state are removed, along with gate overrides in tests. The node version skew check in pod resize validation is also removed: the oldest kubelet supported by a v1.38 apiserver is v1.35, where the feature is always enabled. --- hack/local-up-cluster.sh | 2 +- pkg/api/pod/util.go | 71 ---- pkg/api/pod/util_test.go | 312 ------------------ pkg/apis/core/types.go | 4 - pkg/apis/core/validation/validation.go | 27 -- pkg/apis/core/validation/validation_test.go | 94 +----- pkg/features/kube_features.go | 34 +- pkg/kubeapiserver/options/plugins.go | 2 +- pkg/kubelet/allocation/allocation_manager.go | 18 +- .../allocation/allocation_manager_test.go | 93 +----- pkg/kubelet/allocation/features_linux.go | 3 - pkg/kubelet/kubelet.go | 200 +++++------ pkg/kubelet/kubelet_pods.go | 48 ++- pkg/kubelet/kubelet_pods_test.go | 4 - pkg/kubelet/kubelet_test.go | 4 - .../kuberuntime/kuberuntime_container.go | 33 +- .../kuberuntime/kuberuntime_container_test.go | 4 - .../kuberuntime/kuberuntime_manager.go | 8 - .../kuberuntime/kuberuntime_manager_test.go | 7 - pkg/kubelet/kuberuntime/labels_test.go | 4 - pkg/kubelet/metrics/metrics.go | 16 +- pkg/kubelet/pod_workers.go | 6 +- pkg/kubelet/status/status_manager.go | 24 +- pkg/quota/v1/evaluator/core/pods.go | 2 +- pkg/quota/v1/install/update_filter.go | 4 +- pkg/registry/core/pod/strategy_test.go | 32 +- pkg/registry/core/rest/storage_core.go | 6 +- pkg/scheduler/framework/events.go | 4 +- .../framework/plugins/feature/feature.go | 2 - .../framework/plugins/helper/resource_fit.go | 2 +- .../noderesources/balanced_allocation.go | 13 +- .../framework/plugins/noderesources/fit.go | 24 +- .../plugins/noderesources/fit_test.go | 67 +--- .../noderesources/resource_allocation.go | 3 +- pkg/scheduler/framework/types.go | 8 +- pkg/scheduler/framework/types_test.go | 1 - pkg/scheduler/schedule_one_test.go | 1 - pkg/scheduler/scheduler_test.go | 61 +--- .../admission/limitranger/admission_test.go | 2 - plugin/pkg/admission/podresize/admission.go | 15 +- .../pkg/admission/podresize/admission_test.go | 1 - .../src/k8s.io/api/core/v1/generated.proto | 4 - staging/src/k8s.io/api/core/v1/types.go | 4 - .../component-helpers/resource/helpers.go | 7 +- .../reference/feature_list.md | 17 +- .../reference/versioned_feature_list.yaml | 14 - test/e2e/node/pod_resize.go | 9 +- test/integration/pods/pods_test.go | 2 - .../deferred_resize_preemption_test.go | 7 - test/integration/scheduler/queueing/queue.go | 1 - .../event_handling/performance-config.yaml | 2 - 51 files changed, 223 insertions(+), 1110 deletions(-) diff --git a/hack/local-up-cluster.sh b/hack/local-up-cluster.sh index 9cc35bf10be..4b568d63f26 100755 --- a/hack/local-up-cluster.sh +++ b/hack/local-up-cluster.sh @@ -214,7 +214,7 @@ function usage { echo " CPUMANAGER_POLICY_OPTIONS=full-pcpus-only=\"true\" \\" echo " CPUMANAGER_RECONCILE_PERIOD=\"5s\" \\" echo " KUBELET_FLAGS=\"--kube-reserved=cpu=1,memory=4Gi --system-reserved=cpu=1,memory=1Gi --reserved-memory 0:memory=3Gi;1:memory=2148Mi --resolv-conf=/run/systemd/resolve/resolv.conf\" \\" - echo " hack/local-up-cluster.sh ( run with Topology, CPU, Memory Management policies alongside InPlacePodVerticalScaling, extra flags for etcd and coredns)" + echo " hack/local-up-cluster.sh ( run with Topology, CPU, Memory Management policies alongside InPlacePodVerticalScalingExclusiveCPUs, extra flags for etcd and coredns)" echo "" echo "-d dry-run: prepare for running commands, then show their command lines instead of running them" } diff --git a/pkg/api/pod/util.go b/pkg/api/pod/util.go index f7d4b0ded66..5be3de935f4 100644 --- a/pkg/api/pod/util.go +++ b/pkg/api/pod/util.go @@ -420,7 +420,6 @@ func GetValidationOptionsFromPodSpecAndMeta(podSpec, oldPodSpec *api.PodSpec, po AllowNonLocalProjectedTokenPath: false, PodLevelResourcesEnabled: utilfeature.DefaultFeatureGate.Enabled(features.PodLevelResources), AllowInvalidLabelValueInRequiredNodeAffinity: false, - AllowSidecarResizePolicy: utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling), AllowMatchLabelKeysInPodTopologySpread: utilfeature.DefaultFeatureGate.Enabled(features.MatchLabelKeysInPodTopologySpread), AllowMatchLabelKeysInPodTopologySpreadSelectorMerge: utilfeature.DefaultFeatureGate.Enabled(features.MatchLabelKeysInPodTopologySpreadSelectorMerge), InPlacePodLevelResourcesVerticalScalingEnabled: utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodLevelResourcesVerticalScaling), @@ -478,9 +477,6 @@ func GetValidationOptionsFromPodSpecAndMeta(podSpec, oldPodSpec *api.PodSpec, po } } - // If oldPod has resize policy set on the restartable init container, we must allow it - opts.AllowSidecarResizePolicy = opts.AllowSidecarResizePolicy || hasRestartableInitContainerResizePolicy(oldPodSpec) - opts.AllowContainerRestartPolicyRules = opts.AllowContainerRestartPolicyRules || containerRestartRulesInUse(oldPodSpec) opts.AllowRestartAllContainers = opts.AllowRestartAllContainers || restartAllContainersActionInUse(oldPodSpec) @@ -770,20 +766,6 @@ func dropDisabledFields( dropDisabledGRPCContainerProbeTLS(podSpec, oldPodSpec) dropDisabledEvictionResponders(podSpec, oldPodSpec) - if !utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling) && !inPlacePodVerticalScalingInUse(oldPodSpec) { - // Drop ResizePolicy fields. Don't drop updates to Resources field as template.spec.resources - // field is mutable for certain controllers. Let ValidatePodUpdate handle it. - for i := range podSpec.Containers { - podSpec.Containers[i].ResizePolicy = nil - } - for i := range podSpec.InitContainers { - podSpec.InitContainers[i].ResizePolicy = nil - } - for i := range podSpec.EphemeralContainers { - podSpec.EphemeralContainers[i].ResizePolicy = nil - } - } - if !utilfeature.DefaultFeatureGate.Enabled(features.ContainerRestartRules) && !containerRestartRulesInUse(oldPodSpec) { dropContainerRestartRules(podSpec) } @@ -1043,28 +1025,6 @@ func dropDisabledPodStatusFields(podStatus, oldPodStatus *api.PodStatus, podSpec podStatus.AllocatedResources = nil } - if !utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling) && !inPlacePodVerticalScalingInUse(oldPodSpec) { - // Drop Resources fields - dropResourcesField := func(csl []api.ContainerStatus) { - for i := range csl { - csl[i].Resources = nil - } - } - dropResourcesField(podStatus.ContainerStatuses) - dropResourcesField(podStatus.InitContainerStatuses) - dropResourcesField(podStatus.EphemeralContainerStatuses) - - // Drop AllocatedResources field - dropAllocatedResourcesField := func(csl []api.ContainerStatus) { - for i := range csl { - csl[i].AllocatedResources = nil - } - } - dropAllocatedResourcesField(podStatus.ContainerStatuses) - dropAllocatedResourcesField(podStatus.InitContainerStatuses) - dropAllocatedResourcesField(podStatus.EphemeralContainerStatuses) - } - if !utilfeature.DefaultFeatureGate.Enabled(features.DRAExtendedResource) && !draExendedResourceInUse(oldPodStatus) { podStatus.ExtendedResourceClaimStatus = nil } @@ -1367,23 +1327,6 @@ func podLevelStatusResourcesInUse(podStatus *api.PodStatus) bool { return podStatus.Resources != nil || podStatus.AllocatedResources != nil } -// inPlacePodVerticalScalingInUse returns true if pod spec is non-nil and ResizePolicy is set -func inPlacePodVerticalScalingInUse(podSpec *api.PodSpec) bool { - if podSpec == nil { - return false - } - var inUse bool - containersMask := Containers | InitContainers - VisitContainers(podSpec, containersMask, func(c *api.Container, containerType ContainerType) bool { - if len(c.ResizePolicy) > 0 { - inUse = true - return false - } - return true - }) - return inUse -} - // procMountInUse returns true if the pod spec is non-nil and has a SecurityContext's ProcMount field set to a non-default value func procMountInUse(podSpec *api.PodSpec) bool { if podSpec == nil { @@ -1863,20 +1806,6 @@ func hasUserNamespacesWithVolumeDevices(podSpec *api.PodSpec) bool { return hasVolumeDevices } -// hasRestartableInitContainerResizePolicy returns true if the pod spec is non-nil and -// it has any init container with ContainerRestartPolicyAlways and non-nil ResizePolicy. -func hasRestartableInitContainerResizePolicy(podSpec *api.PodSpec) bool { - if podSpec == nil { - return false - } - for _, c := range podSpec.InitContainers { - if IsRestartableInitContainer(&c) && len(c.ResizePolicy) > 0 { - return true - } - } - return false -} - // hasEmptyImageVolumeReference returns true if the pod spec has any image volume with an empty reference. func hasEmptyImageVolumeReference(podSpec *api.PodSpec) bool { if podSpec == nil { diff --git a/pkg/api/pod/util_test.go b/pkg/api/pod/util_test.go index 26235434cc5..1f122c79dde 100644 --- a/pkg/api/pod/util_test.go +++ b/pkg/api/pod/util_test.go @@ -25,7 +25,6 @@ import ( "time" "github.com/google/go-cmp/cmp" - "github.com/stretchr/testify/assert" "k8s.io/component-base/featuregate" "k8s.io/apimachinery/pkg/api/resource" @@ -2564,145 +2563,6 @@ func TestDropAtomicWriteVolumeUserFields(t *testing.T) { } } -func TestDropInPlacePodVerticalScaling(t *testing.T) { - featuregatetesting.SetFeatureGateEmulationVersionDuringTest(t, utilfeature.DefaultFeatureGate, version.MustParse("1.34")) - podWithInPlaceVerticalScaling := func() *api.Pod { - return &api.Pod{ - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Name: "c1", - Image: "image", - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("100m")}, - Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("200m")}, - }, - ResizePolicy: []api.ContainerResizePolicy{ - {ResourceName: api.ResourceCPU, RestartPolicy: api.NotRequired}, - {ResourceName: api.ResourceMemory, RestartPolicy: api.RestartContainer}, - }, - }, - }, - }, - Status: api.PodStatus{ - ContainerStatuses: []api.ContainerStatus{ - { - Name: "c1", - Image: "image", - AllocatedResources: api.ResourceList{api.ResourceCPU: resource.MustParse("100m")}, - Resources: &api.ResourceRequirements{ - Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("200m")}, - Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("300m")}, - }, - }, - }, - }, - } - } - podWithoutInPlaceVerticalScaling := func() *api.Pod { - return &api.Pod{ - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Name: "c1", - Image: "image", - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("100m")}, - Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("200m")}, - }, - }, - }, - }, - Status: api.PodStatus{ - ContainerStatuses: []api.ContainerStatus{ - { - Name: "c1", - Image: "image", - }, - }, - }, - } - } - - podInfo := []struct { - description string - hasInPlaceVerticalScaling bool - pod func() *api.Pod - }{ - { - description: "has in-place vertical scaling enabled with resources", - hasInPlaceVerticalScaling: true, - pod: podWithInPlaceVerticalScaling, - }, - { - description: "has in-place vertical scaling disabled", - hasInPlaceVerticalScaling: false, - pod: podWithoutInPlaceVerticalScaling, - }, - { - description: "is nil", - hasInPlaceVerticalScaling: false, - pod: func() *api.Pod { return nil }, - }, - } - - for _, ippvsEnabled := range []bool{true, false} { - t.Run(fmt.Sprintf("InPlacePodVerticalScaling=%t", ippvsEnabled), func(t *testing.T) { - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScaling, ippvsEnabled) - - for _, oldPodInfo := range podInfo { - for _, newPodInfo := range podInfo { - oldPodHasInPlaceVerticalScaling, oldPod := oldPodInfo.hasInPlaceVerticalScaling, oldPodInfo.pod() - newPodHasInPlaceVerticalScaling, newPod := newPodInfo.hasInPlaceVerticalScaling, newPodInfo.pod() - if newPod == nil { - continue - } - - t.Run(fmt.Sprintf("old pod %v, new pod %v", oldPodInfo.description, newPodInfo.description), func(t *testing.T) { - var oldPodSpec *api.PodSpec - var oldPodStatus *api.PodStatus - if oldPod != nil { - oldPodSpec = &oldPod.Spec - oldPodStatus = &oldPod.Status - } - dropDisabledFields(&newPod.Spec, nil, oldPodSpec, nil) - dropDisabledPodStatusFields(&newPod.Status, oldPodStatus, &newPod.Spec, oldPodSpec) - - // old pod should never be changed - if !reflect.DeepEqual(oldPod, oldPodInfo.pod()) { - t.Errorf("old pod changed: %v", cmp.Diff(oldPod, oldPodInfo.pod())) - } - - switch { - case ippvsEnabled || oldPodHasInPlaceVerticalScaling: - // new pod shouldn't change if feature enabled or if old pod has ResizePolicy set - expected := newPodInfo.pod() - if !reflect.DeepEqual(newPod, expected) { - t.Errorf("new pod changed: %v", cmp.Diff(newPod, expected)) - } - case newPodHasInPlaceVerticalScaling: - // new pod should be changed - if reflect.DeepEqual(newPod, newPodInfo.pod()) { - t.Errorf("new pod was not changed") - } - // new pod should not have ResizePolicy - if !reflect.DeepEqual(newPod, podWithoutInPlaceVerticalScaling()) { - t.Errorf("new pod has ResizePolicy: %v", cmp.Diff(newPod, podWithoutInPlaceVerticalScaling())) - } - default: - // new pod should not need to be changed - if !reflect.DeepEqual(newPod, newPodInfo.pod()) { - t.Errorf("new pod changed: %v", cmp.Diff(newPod, newPodInfo.pod())) - } - } - }) - } - } - - }) - } -} - func TestDropPodLevelResources(t *testing.T) { containers := []api.Container{ { @@ -3783,178 +3643,6 @@ func TestDropSELinuxChangePolicy(t *testing.T) { } } -func TestValidateAllowSidecarResizePolicy(t *testing.T) { - featuregatetesting.SetFeatureGateEmulationVersionDuringTest(t, utilfeature.DefaultFeatureGate, version.MustParse("1.34")) - restartPolicyAlways := api.ContainerRestartPolicyAlways - testCases := []struct { - name string - oldPodSpec *api.PodSpec - wantOption bool - }{ - { - name: "old pod spec is nil", - wantOption: false, - }, - { - name: "one sidecar container + one regular init container, no resize policy set on any of them", - oldPodSpec: &api.PodSpec{ - InitContainers: []api.Container{ - { - Name: "c1-restartable-init", - Image: "image", - RestartPolicy: &restartPolicyAlways, - }, - { - Name: "c1-init", - Image: "image", - }, - }, - }, - wantOption: false, - }, - { - name: "one sidecar container + one regular init container, resize policy set on regular init container", - oldPodSpec: &api.PodSpec{ - InitContainers: []api.Container{ - { - Name: "c1-restartable-init", - Image: "image", - RestartPolicy: &restartPolicyAlways, - }, - { - Name: "c1-init", - Image: "image", - ResizePolicy: []api.ContainerResizePolicy{ - {ResourceName: api.ResourceCPU, RestartPolicy: api.NotRequired}, - }, - }, - }, - }, - wantOption: false, - }, - { - name: "one sidecar container + one regular init container, resize policy set on sidecar container", - oldPodSpec: &api.PodSpec{ - InitContainers: []api.Container{ - { - Name: "c1-restartable-init", - Image: "image", - RestartPolicy: &restartPolicyAlways, - ResizePolicy: []api.ContainerResizePolicy{ - {ResourceName: api.ResourceCPU, RestartPolicy: api.NotRequired}, - }, - }, - { - Name: "c1-init", - Image: "image", - }, - }, - }, - wantOption: true, - }, - { - name: "one sidecar container + one regular init container, resize policy set on both of them", - oldPodSpec: &api.PodSpec{ - InitContainers: []api.Container{ - { - Name: "c1-restartable-init", - Image: "image", - RestartPolicy: &restartPolicyAlways, - ResizePolicy: []api.ContainerResizePolicy{ - {ResourceName: api.ResourceCPU, RestartPolicy: api.NotRequired}, - }, - }, - { - Name: "c1-init", - Image: "image", - ResizePolicy: []api.ContainerResizePolicy{ - {ResourceName: api.ResourceCPU, RestartPolicy: api.NotRequired}, - }, - }, - }, - }, - wantOption: true, - }, - { - name: "two sidecar containers, resize policy set on one of them", - oldPodSpec: &api.PodSpec{ - InitContainers: []api.Container{ - { - Name: "c1-restartable-init", - Image: "image", - RestartPolicy: &restartPolicyAlways, - ResizePolicy: []api.ContainerResizePolicy{ - {ResourceName: api.ResourceCPU, RestartPolicy: api.NotRequired}, - }, - }, - { - Name: "c2-restartable-init", - Image: "image", - RestartPolicy: &restartPolicyAlways, - }, - }, - }, - wantOption: true, - }, - { - name: "two regular init containers, resize policy set on both of them", - oldPodSpec: &api.PodSpec{ - InitContainers: []api.Container{ - { - Name: "c1-init", - Image: "image", - ResizePolicy: []api.ContainerResizePolicy{ - {ResourceName: api.ResourceCPU, RestartPolicy: api.NotRequired}, - }, - }, - { - Name: "c2-init", - Image: "image", - ResizePolicy: []api.ContainerResizePolicy{ - {ResourceName: api.ResourceCPU, RestartPolicy: api.NotRequired}, - }, - }, - }, - }, - wantOption: false, - }, - { - name: "two non-init containers, resize policy set on both of them", - oldPodSpec: &api.PodSpec{ - Containers: []api.Container{ - { - Name: "c1", - Image: "image", - ResizePolicy: []api.ContainerResizePolicy{ - {ResourceName: api.ResourceCPU, RestartPolicy: api.NotRequired}, - }, - }, - { - Name: "c2", - Image: "image", - ResizePolicy: []api.ContainerResizePolicy{ - {ResourceName: api.ResourceCPU, RestartPolicy: api.NotRequired}, - }, - }, - }, - }, - wantOption: false, - }, - } - - for _, tc := range testCases { - for _, ippvsEnabled := range []bool{true, false} { - t.Run(fmt.Sprintf("%s/%t", tc.name, ippvsEnabled), func(t *testing.T) { - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScaling, ippvsEnabled) - - gotOptions := GetValidationOptionsFromPodSpecAndMeta(&api.PodSpec{}, tc.oldPodSpec, nil, nil) - expected := tc.wantOption || ippvsEnabled - assert.Equal(t, expected, gotOptions.AllowSidecarResizePolicy, "AllowSidecarResizePolicy") - }) - } - } -} - func TestValidateInvalidLabelValueInNodeSelectorOption(t *testing.T) { testCases := []struct { name string diff --git a/pkg/apis/core/types.go b/pkg/apis/core/types.go index e2071a276b7..fdf0560a2b3 100644 --- a/pkg/apis/core/types.go +++ b/pkg/apis/core/types.go @@ -2873,7 +2873,6 @@ type Container struct { Resources ResourceRequirements // Resources resize policy for the container. // This field cannot be set on ephemeral containers. - // +featureGate=InPlacePodVerticalScaling // +optional ResizePolicy []ContainerResizePolicy // RestartPolicy defines the restart behavior of individual containers in a pod. @@ -3238,7 +3237,6 @@ type ContainerStatus struct { AllocatedResources ResourceList // Resources represents the compute resource requests and limits that have been successfully // enacted on the running container after it has been started or has been successfully resized. - // +featureGate=InPlacePodVerticalScaling // +optional Resources *ResourceRequirements // Status of volume mounts. @@ -4759,7 +4757,6 @@ type EphemeralContainerCommon struct { // +optional Resources ResourceRequirements // Resources resize policy for the container. - // +featureGate=InPlacePodVerticalScaling // +optional ResizePolicy []ContainerResizePolicy // Restart policy for the container to manage the restart behavior of each @@ -4975,7 +4972,6 @@ type PodStatus struct { // Deprecated: Resize status is moved to two pod conditions PodResizePending and PodResizeInProgress. // PodResizePending will track states where the spec has been resized, but the Kubelet has not yet allocated the resources. // PodResizeInProgress will track in-progress resizes, and should be present whenever allocated resources != acknowledged resources. - // +featureGate=InPlacePodVerticalScaling // +optional Resize PodResizeStatus diff --git a/pkg/apis/core/validation/validation.go b/pkg/apis/core/validation/validation.go index de0635afdca..2dd97395458 100644 --- a/pkg/apis/core/validation/validation.go +++ b/pkg/apis/core/validation/validation.go @@ -3985,10 +3985,6 @@ func validateInitContainers(containers []core.Container, os *core.PodOS, regular } } - if !opts.AllowSidecarResizePolicy && len(ctr.ResizePolicy) > 0 { - allErrs = append(allErrs, field.Invalid(idxPath.Child("resizePolicy"), ctr.ResizePolicy, "must not be set for init containers")) - } - if !restartAlways && !opts.AllowExistingRestartContainerForNonSidecarInitContainer { for j, p := range ctr.ResizePolicy { if p.RestartPolicy == core.RestartContainer { @@ -4608,8 +4604,6 @@ type PodValidationOptions struct { // Indicates whether InPlacePodVerticalScalingMemoryBackedVolumes feature is enabled // or disabled. InPlacePodVerticalScalingMemoryBackedVolumesEnabled bool - // Allow sidecar containers resize policy for backward compatibility - AllowSidecarResizePolicy bool // Allow invalid label-value in RequiredNodeSelector AllowInvalidLabelValueInRequiredNodeAffinity bool // Allow feature of MatchLabelKeys in TopologySpreadConstraints @@ -6583,10 +6577,6 @@ func ValidatePodResize(newPod, oldPod *core.Pod, opts PodValidationOptions) fiel allErrs = append(allErrs, field.Invalid(specPath, newPod.Status.QOSClass, "Pod QOS Class may not change as a result of resizing")) } - if !isPodResizeRequestSupported(*oldPod) { - allErrs = append(allErrs, field.Forbidden(specPath, "Pod running on node without support for resize")) - } - // Part 2: Validate that changes between pod-level resources in oldPod.Spec.Resources and // newPod.Spec.Resources are allowed. @@ -6973,23 +6963,6 @@ func validatePodLevelResourcesCoverDRA(pod *v1.Pod) (bool, string) { return true, "" } -// isPodResizeRequestSupported checks whether the pod is running on a node with InPlacePodVerticalScaling enabled. -func isPodResizeRequestSupported(pod core.Pod) bool { - // TODO: Remove this after GA+3 releases of InPlacePodVerticalScaling - // This code handles the version skew as described in the KEP. - // For handling version skew we're only allowing to update the Pod's Resources - // if the Pod already has Pod.Status.ContainerStatuses[i].Resources. This means - // that the apiserver would only allow updates to Pods running on Nodes with - // the InPlacePodVerticalScaling feature gate enabled. - for _, c := range pod.Status.ContainerStatuses { - if c.State.Running != nil { - return c.Resources != nil - } - } - // No running containers. We cannot tell whether the node supports resize at this point, so we assume it does. - return true -} - // validateContainerResize validates the changes to the container's resource requirements for a pod resize request. // newRequriements and oldRequirements must be non-nil. func validateContainerResize(newRequirements, oldRequirements *core.ResourceRequirements, resizePolicies []core.ContainerResizePolicy, fldPath *field.Path) field.ErrorList { diff --git a/pkg/apis/core/validation/validation_test.go b/pkg/apis/core/validation/validation_test.go index f654ce50103..21bb22c05cb 100644 --- a/pkg/apis/core/validation/validation_test.go +++ b/pkg/apis/core/validation/validation_test.go @@ -8752,7 +8752,6 @@ func TestValidatePullPolicy(t *testing.T) { } func TestValidateResizePolicy(t *testing.T) { - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScaling, true) tSupportedResizeResources := sets.NewString(string(core.ResourceCPU), string(core.ResourceMemory)) tSupportedResizePolicies := sets.NewString(string(core.NotRequired), string(core.RestartContainer)) type T struct { @@ -10367,7 +10366,7 @@ func TestValidateInitContainers(t *testing.T) { }} var PodRestartPolicy core.RestartPolicy = "Always" - if errs := validateInitContainers(successCase, podOS, containers, volumeDevices, nil, defaultGracePeriod, field.NewPath("field"), PodValidationOptions{AllowSidecarResizePolicy: true, AllowExistingRestartContainerForNonSidecarInitContainer: true}, &PodRestartPolicy, noUserNamespace); len(errs) != 0 { + if errs := validateInitContainers(successCase, podOS, containers, volumeDevices, nil, defaultGracePeriod, field.NewPath("field"), PodValidationOptions{AllowExistingRestartContainerForNonSidecarInitContainer: true}, &PodRestartPolicy, noUserNamespace); len(errs) != 0 { t.Errorf("expected success: %v", errs) } @@ -10742,19 +10741,6 @@ func TestValidateInitContainers(t *testing.T) { }, }}, field.ErrorList{{Type: field.ErrorTypeRequired, Field: "initContainers[0].lifecycle.preStop", BadValue: ""}}, - }, { - "Not supported ResizePolicy: invalid", - line(), - []core.Container{{ - Name: "init", - Image: "image", - ImagePullPolicy: "IfNotPresent", - TerminationMessagePolicy: "File", - ResizePolicy: []core.ContainerResizePolicy{ - {ResourceName: "cpu", RestartPolicy: "NotRequired"}, - }, - }}, - field.ErrorList{{Type: field.ErrorTypeInvalid, Field: "initContainers[0].resizePolicy", BadValue: []core.ContainerResizePolicy{{ResourceName: "cpu", RestartPolicy: "NotRequired"}}}}, }, { "RestartContainer policy forbidden for non-sidecar init container", line(), @@ -10768,10 +10754,6 @@ func TestValidateInitContainers(t *testing.T) { }, }}, field.ErrorList{{ - Type: field.ErrorTypeInvalid, - Field: "initContainers[0].resizePolicy", - BadValue: []core.ContainerResizePolicy{{ResourceName: core.ResourceCPU, RestartPolicy: core.RestartContainer}}, - }, { Type: field.ErrorTypeInvalid, Field: "initContainers[0].resizePolicy[0].restartPolicy", BadValue: core.RestartContainer, @@ -14665,7 +14647,7 @@ func TestValidatePodUpdate(t *testing.T) { ), err: "spec.initContainers[0].resizePolicy[0].restartPolicy: Invalid value: \"RestartContainer\": must not be set to 'RestartContainer' for non-sidecar initContainers", test: "adding RestartContainer resize policy to non-sidecar init container should fail", - opts: PodValidationOptions{AllowSidecarResizePolicy: true, AllowExistingRestartContainerForNonSidecarInitContainer: false}, + opts: PodValidationOptions{AllowExistingRestartContainerForNonSidecarInitContainer: false}, }, { new: *podtest.MakePod("foo", podtest.SetInitContainers(core.Container{ @@ -14681,7 +14663,7 @@ func TestValidatePodUpdate(t *testing.T) { ), err: "", test: "existing RestartContainer resize policy on non-sidecar init container should be allowed on update", - opts: PodValidationOptions{AllowSidecarResizePolicy: true, AllowExistingRestartContainerForNonSidecarInitContainer: true}, + opts: PodValidationOptions{AllowExistingRestartContainerForNonSidecarInitContainer: true}, }, { new: *podtest.MakePod("foo", podtest.SetOS(core.Windows), @@ -30541,75 +30523,6 @@ func TestValidatePodResize(t *testing.T) { ))), disableInitCtrResize: true, err: "Forbidden: resources for non-sidecar init containers are immutable", - }, - - { - test: "Pod with nil Resource field in Status", - old: mkPod(core.ResourceList{}, getResources("100m", "0", "1Gi", ""), podtest.SetStatus(core.PodStatus{ - ContainerStatuses: []core.ContainerStatus{{ - ContainerID: "docker://numbers", - Image: "nginx:alpine", - Name: "main", - Ready: true, - Started: proto.Bool(true), - Resources: nil, - State: core.ContainerState{ - Running: &core.ContainerStateRunning{ - StartedAt: metav1.NewTime(time.Now()), - }, - }, - }}, - })), - new: mkPod(core.ResourceList{}, getResources("200m", "0", "1Gi", "")), - err: "Forbidden: Pod running on node without support for resize", - }, - { - test: "Pod with non-nil Resources field in Status", - old: mkPod(core.ResourceList{}, getResources("100m", "0", "1Gi", ""), podtest.SetStatus(core.PodStatus{ - ContainerStatuses: []core.ContainerStatus{{ - ContainerID: "docker://numbers", - Image: "nginx:alpine", - Name: "main", - Ready: true, - Started: proto.Bool(true), - Resources: &core.ResourceRequirements{}, - State: core.ContainerState{ - Running: &core.ContainerStateRunning{ - StartedAt: metav1.NewTime(time.Now()), - }, - }, - }}, - })), - new: mkPod(core.ResourceList{}, getResources("200m", "0", "1Gi", "")), - err: "", - }, - { - test: "Pod without running containers", - old: mkPod(core.ResourceList{}, getResources("100m", "0", "1Gi", ""), podtest.SetStatus(core.PodStatus{ - ContainerStatuses: []core.ContainerStatus{}, - })), - new: mkPod(core.ResourceList{}, getResources("200m", "0", "1Gi", "")), - err: "", - }, - { - test: "Pod with containers which are not running yet", - old: mkPod(core.ResourceList{}, getResources("100m", "0", "1Gi", ""), podtest.SetStatus(core.PodStatus{ - ContainerStatuses: []core.ContainerStatus{{ - ContainerID: "docker://numbers", - Image: "nginx:alpine", - Name: "main", - Ready: true, - Started: proto.Bool(true), - Resources: &core.ResourceRequirements{}, - State: core.ContainerState{ - Waiting: &core.ContainerStateWaiting{ - Reason: "PodInitializing", - }, - }, - }}, - })), - new: mkPod(core.ResourceList{}, getResources("200m", "0", "1Gi", "")), - err: "", }, { test: "cpu limit change for sidecar containers", old: mkPodWithInitContainers(core.ResourceList{}, getResources("100m", "0", "1Gi", ""), core.ContainerRestartPolicyAlways), @@ -31396,7 +31309,6 @@ func TestValidatePodResize(t *testing.T) { } errs := ValidatePodResize(test.new, test.old, PodValidationOptions{ - AllowSidecarResizePolicy: true, InPlacePodLevelResourcesVerticalScalingEnabled: true, PodLevelResourcesEnabled: true, InPlacePodVerticalScalingMemoryBackedVolumesEnabled: test.enableMemoryBackedVolumesResize, diff --git a/pkg/features/kube_features.go b/pkg/features/kube_features.go index c768d4bc30c..d30c7df6c47 100644 --- a/pkg/features/kube_features.go +++ b/pkg/features/kube_features.go @@ -521,23 +521,17 @@ const ( // Enables specifying resources at pod-level. InPlacePodLevelResourcesVerticalScaling featuregate.Feature = "InPlacePodLevelResourcesVerticalScaling" - // owner: @vinaykul,@tallclair - // kep: http://kep.k8s.io/1287 - // - // Enables In-Place Pod Vertical Scaling - InPlacePodVerticalScaling featuregate.Feature = "InPlacePodVerticalScaling" - // owner: @tallclair @esotsal // // Allow resource resize for containers in Guaranteed pods with integer CPU requests ( default false ). - // Applies only in nodes with InPlacePodVerticalScaling and CPU Manager features enabled, and + // Applies only in nodes with CPU Manager features enabled, and // CPU Manager Static Policy option set. InPlacePodVerticalScalingExclusiveCPUs featuregate.Feature = "InPlacePodVerticalScalingExclusiveCPUs" // owner: @tallclair @pkrishn // // Allow memory resize for containers in Guaranteed pods (default false) when Memory Manager Policy is set to Static. - // Applies only in nodes with InPlacePodVerticalScaling and Memory Manager features enabled. + // Applies only in nodes with Memory Manager features enabled. InPlacePodVerticalScalingExclusiveMemory featuregate.Feature = "InPlacePodVerticalScalingExclusiveMemory" // owner: @natasha41575 @@ -1579,12 +1573,6 @@ var defaultVersionedKubernetesFeatureGates = map[featuregate.Feature]featuregate {Version: version.MustParse("1.36"), Default: true, PreRelease: featuregate.Beta}, }, - InPlacePodVerticalScaling: { - {Version: version.MustParse("1.27"), Default: false, PreRelease: featuregate.Alpha}, - {Version: version.MustParse("1.33"), Default: true, PreRelease: featuregate.Beta}, - {Version: version.MustParse("1.35"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.38 - }, - InPlacePodVerticalScalingExclusiveCPUs: { {Version: version.MustParse("1.32"), Default: false, PreRelease: featuregate.Alpha}, }, @@ -2437,7 +2425,7 @@ var defaultKubernetesFeatureGateDependencies = map[featuregate.Feature][]feature DisableNodeKubeProxyVersion: {}, - DynamicNodeLocalEphemeralVolumes: {InPlacePodVerticalScaling, NodeDeclaredFeatures}, + DynamicNodeLocalEphemeralVolumes: {NodeDeclaredFeatures}, EmptyDirVolumeMode: {}, @@ -2481,19 +2469,17 @@ var defaultKubernetesFeatureGateDependencies = map[featuregate.Feature][]feature ImageVolumeWithDigest: {ImageVolume}, - InPlacePodLevelResourcesVerticalScaling: {InPlacePodVerticalScaling, PodLevelResources, NodeDeclaredFeatures}, + InPlacePodLevelResourcesVerticalScaling: {PodLevelResources, NodeDeclaredFeatures}, - InPlacePodVerticalScaling: {}, + InPlacePodVerticalScalingExclusiveCPUs: {}, - InPlacePodVerticalScalingExclusiveCPUs: {InPlacePodVerticalScaling}, + InPlacePodVerticalScalingExclusiveMemory: {}, - InPlacePodVerticalScalingExclusiveMemory: {InPlacePodVerticalScaling}, + InPlacePodVerticalScalingInitContainers: {NodeDeclaredFeatures}, - InPlacePodVerticalScalingInitContainers: {InPlacePodVerticalScaling, NodeDeclaredFeatures}, + InPlacePodVerticalScalingMemoryBackedVolumes: {NodeDeclaredFeatures}, - InPlacePodVerticalScalingMemoryBackedVolumes: {InPlacePodVerticalScaling, NodeDeclaredFeatures}, - - InPlacePodVerticalScalingSchedulerPreemption: {InPlacePodVerticalScaling}, + InPlacePodVerticalScalingSchedulerPreemption: {}, InterPodAffinityHostnameFastPath: {}, @@ -2503,7 +2489,7 @@ var defaultKubernetesFeatureGateDependencies = map[featuregate.Feature][]feature KubeProxyNFTablesLocalhostNodePorts: {}, - KubeletAllocatedPodsEndpoint: {InPlacePodVerticalScaling}, + KubeletAllocatedPodsEndpoint: {}, KubeletCgroupDriverFromCRI: {}, diff --git a/pkg/kubeapiserver/options/plugins.go b/pkg/kubeapiserver/options/plugins.go index 8691ce99006..508d4cbac14 100644 --- a/pkg/kubeapiserver/options/plugins.go +++ b/pkg/kubeapiserver/options/plugins.go @@ -189,7 +189,7 @@ func DefaultOffAdmissionPlugins() sets.Set[string] { mutatingadmissionpolicy.PluginName, // Mutatingadmissionpolicy, only active when feature gate MutatingAdmissionpolicy is enabled validatingadmissionpolicy.PluginName, // ValidatingAdmissionPolicy, only active when feature gate ValidatingAdmissionPolicy is enabled nodedeclaredfeatures.PluginName, // NodeDeclaredFeatureValidator, only active when feature gate NodeDeclaredFeatures is enabled - podresize.PluginName, // PodResizeValidator, only active when feature gate InPlacePodVerticalScaling is enabled + podresize.PluginName, // PodResizeValidator conditionsenforcer.PluginName, // AuthorizationConditionsEnforcer, only active when feature gate ConditionalAuthorization is enabled ) diff --git a/pkg/kubelet/allocation/allocation_manager.go b/pkg/kubelet/allocation/allocation_manager.go index 0a51e7097c6..7aed5c0dc25 100644 --- a/pkg/kubelet/allocation/allocation_manager.go +++ b/pkg/kubelet/allocation/allocation_manager.go @@ -157,10 +157,6 @@ func NewManager(checkpointDirectory string, } func newStateImpl(logger klog.Logger, checkpointDirectory, checkpointName string) state.State { - if !utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling) { - return state.NewNoopStateCheckpoint() - } - stateImpl, err := state.NewStateCheckpoint(logger, checkpointDirectory, checkpointName, nil) if err != nil { // This is a critical, non-recoverable failure. @@ -515,17 +511,15 @@ func (m *manager) AddPod(ctx context.Context, activePods []*v1.Pod, pod *v1.Pod) m.allocationMutex.Lock() defer m.allocationMutex.Unlock() - if utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling) { - // To handle kubelet restarts, test pod admissibility using AllocatedResources values - // (for cpu & memory) from checkpoint store. If found, that is the source of truth. - pod, _ = m.UpdatePodFromAllocation(pod) - } + // To handle kubelet restarts, test pod admissibility using AllocatedResources values + // (for cpu & memory) from checkpoint store. If found, that is the source of truth. + pod, _ = m.UpdatePodFromAllocation(pod) // Check if we can admit the pod; if so, update the allocation. allocatedPods := m.getAllocatedPods(activePods) ok, reason, message := m.canAdmitPod(ctx, allocatedPods, pod, lifecycle.AddOperation) - if ok && utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling) { + if ok { // Checkpoint the resource values at which the Pod has been admitted or resized. if err := m.SetAllocatedResources(logger, pod); err != nil { // TODO(vinaykul,InPlacePodVerticalScaling): Can we recover from this in some way? Investigate @@ -652,10 +646,6 @@ func (m *manager) canAdmitPod(ctx context.Context, allocatedPods []*v1.Pod, pod } func (m *manager) getAllocatedPods(activePods []*v1.Pod) []*v1.Pod { - if !utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling) { - return activePods - } - allocatedPods := make([]*v1.Pod, 0, len(activePods)) for _, pod := range activePods { // Filter out pods that don't yet have an allocation, which will filter pods that diff --git a/pkg/kubelet/allocation/allocation_manager_test.go b/pkg/kubelet/allocation/allocation_manager_test.go index d23a4a6119f..6197f6e29ff 100644 --- a/pkg/kubelet/allocation/allocation_manager_test.go +++ b/pkg/kubelet/allocation/allocation_manager_test.go @@ -33,7 +33,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/sets" - "k8s.io/apimachinery/pkg/util/version" utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/client-go/kubernetes/fake" "k8s.io/client-go/tools/record" @@ -301,7 +300,6 @@ func TestUpdatePodFromAllocation(t *testing.T) { // of a container is allocated. A field that is added to the API fails it until it is classified // here and, if it is passthrough, copied in copyPassthroughFields. func TestUpdatePodFromAllocationFieldClassification(t *testing.T) { - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScaling, true) featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodLevelResourcesVerticalScaling, true) featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScalingMemoryBackedVolumes, true) @@ -480,7 +478,6 @@ func TestUpdatePodFromAllocationFieldClassification(t *testing.T) { // // TODO: Remove in v1.39 when the V1 checkpoint format is no longer supported. func TestUpdatePodFromAllocationMigratedFromV1(t *testing.T) { - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScaling, true) featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodLevelResourcesVerticalScaling, true) featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScalingMemoryBackedVolumes, true) logger, ctx := ktesting.NewTestContext(t) @@ -588,8 +585,6 @@ func TestUpdatePodFromAllocationMigratedFromV1(t *testing.T) { // // TODO: Remove the checks of the overlay in v1.39 when the V1 checkpoint format is no longer supported. func TestUpdatePodFromAllocationPending(t *testing.T) { - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScaling, true) - cpu := func(quantity string) v1.ResourceRequirements { return v1.ResourceRequirements{Requests: v1.ResourceList{v1.ResourceCPU: resource.MustParse(quantity)}} } @@ -695,7 +690,6 @@ func TestRetryPendingResizes(t *testing.T) { if goruntime.GOOS == "windows" { t.Skip("InPlacePodVerticalScaling is not currently supported for Windows") } - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScaling, true) logger, tCtx := ktesting.NewTestContext(t) containerRestartPolicyAlways := v1.ContainerRestartPolicyAlways @@ -1247,7 +1241,6 @@ func TestRetryPendingResizesGuanteedQOSPods(t *testing.T) { if goruntime.GOOS == "windows" { t.Skip("InPlacePodVerticalScaling is not currently supported for Windows") } - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScaling, true) logger, tCtx := ktesting.NewTestContext(t) nodeConfig := cm.NodeConfig{} @@ -1487,7 +1480,6 @@ func TestRetryPendingResizesMemoryBackedVolumes(t *testing.T) { if goruntime.GOOS == "windows" { t.Skip("InPlacePodVerticalScaling is not currently supported for Windows") } - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScaling, true) tCtx := ktesting.Init(t) logger := klog.FromContext(tCtx) @@ -1692,9 +1684,6 @@ func TestRetryPendingResizesWithSwap(t *testing.T) { metrics.Register() metrics.PodInfeasibleResizes.Reset() - featuregatetesting.SetFeatureGatesDuringTest(t, utilfeature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{ - features.InPlacePodVerticalScaling: true, - }) logger, tCtx := ktesting.NewTestContext(t) noSwapContainerName, swapContainerName := "test-container-noswap", "test-container-limitedswap" @@ -1856,7 +1845,6 @@ func TestRetryPendingResizesMultipleConditions(t *testing.T) { if goruntime.GOOS == "windows" { t.Skip("InPlacePodVerticalScaling is not currently supported for Windows") } - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScaling, true) logger, tCtx := ktesting.NewTestContext(t) cpu500m := resource.MustParse("500m") @@ -2052,7 +2040,6 @@ func TestRetryPendingResizesNonResourceChange(t *testing.T) { if goruntime.GOOS == "windows" { t.Skip("InPlacePodVerticalScaling is not currently supported for Windows") } - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScaling, true) cpu := func(quantity string) v1.ResourceRequirements { return v1.ResourceRequirements{Requests: v1.ResourceList{v1.ResourceCPU: resource.MustParse(quantity)}} @@ -2527,7 +2514,6 @@ func TestAllocationManagerAddPod(t *testing.T) { testCases := []struct { name string - ipprFeatureGate bool initialAllocatedResourcesState map[types.UID]v1.ResourceList currentActivePods []*v1.Pod podToAdd *v1.Pod @@ -2538,8 +2524,7 @@ func TestAllocationManagerAddPod(t *testing.T) { expectedAllocatedResourcesState map[types.UID]v1.ResourceList }{ { - name: "IPPR Enabled - New pod admitted and allocated resources updated", - ipprFeatureGate: true, + name: "New pod admitted and allocated resources updated", initialAllocatedResourcesState: map[types.UID]v1.ResourceList{}, currentActivePods: []*v1.Pod{}, podToAdd: pod1Small, @@ -2549,18 +2534,7 @@ func TestAllocationManagerAddPod(t *testing.T) { expectedAllocatedResourcesState: map[types.UID]v1.ResourceList{pod1UID: cpu1Mem1G}, }, { - name: "IPPR Disabled - New pod admitted but allocated resources not updated", - ipprFeatureGate: false, - initialAllocatedResourcesState: map[types.UID]v1.ResourceList{}, - currentActivePods: []*v1.Pod{}, - podToAdd: pod1Small, - admitFunc: nil, - expectAdmit: true, - expectedAllocatedResourcesState: map[types.UID]v1.ResourceList{}, - }, - { - name: "IPPR Enabled - New pod not admititted due to insufficient resources", - ipprFeatureGate: true, + name: "New pod not admititted due to insufficient resources", initialAllocatedResourcesState: map[types.UID]v1.ResourceList{pod1UID: cpu1Mem1G}, currentActivePods: []*v1.Pod{pod1Small}, podToAdd: pod2Large, @@ -2582,31 +2556,7 @@ func TestAllocationManagerAddPod(t *testing.T) { expectedAllocatedResourcesState: map[types.UID]v1.ResourceList{pod1UID: cpu1Mem1G}, }, { - name: "IPPR Disabled - New pod not admitted due to insufficient resources", - ipprFeatureGate: false, - initialAllocatedResourcesState: map[types.UID]v1.ResourceList{pod1UID: cpu1Mem1G}, - currentActivePods: []*v1.Pod{pod1Small}, - podToAdd: pod2Large, - admitFunc: func(attrs *lifecycle.PodAdmitAttributes) lifecycle.PodAdmitResult { - cpuRequest := attrs.Pod.Spec.Containers[0].Resources.Requests.Cpu().Value() - if cpuRequest > 1 { - return lifecycle.PodAdmitResult{ - Admit: false, - Reason: "OutOfcpu", - Message: fmt.Sprintf("not enough CPUs available for pod %s/%s, requested: %d, available:1", attrs.Pod.Namespace, attrs.Pod.Name, cpuRequest), - } - } - return lifecycle.PodAdmitResult{Admit: true} - }, - expectAdmit: false, - admissionFailureReason: "OutOfcpu", - admissionFailureMessage: "not enough CPUs available for pod ns2/pod2, requested: 2, available:1", - // allocated resources not modified - expectedAllocatedResourcesState: map[types.UID]v1.ResourceList{pod1UID: cpu1Mem1G}, - }, - { - name: "IPPR Enabled - no pod resize request. Resource request same as existing allocation", - ipprFeatureGate: true, + name: "no pod resize request. Resource request same as existing allocation", initialAllocatedResourcesState: map[types.UID]v1.ResourceList{pod1UID: cpu1Mem1G, pod2UID: cpu1Mem1G}, currentActivePods: []*v1.Pod{pod1Small}, podToAdd: pod1Small, @@ -2615,8 +2565,7 @@ func TestAllocationManagerAddPod(t *testing.T) { expectedAllocatedResourcesState: map[types.UID]v1.ResourceList{pod1UID: cpu1Mem1G, pod2UID: cpu1Mem1G}, }, { - name: "IPPR Enabled - current allocation not found for added pod. Allocated resources updated.", - ipprFeatureGate: true, + name: "current allocation not found for added pod. Allocated resources updated.", initialAllocatedResourcesState: map[types.UID]v1.ResourceList{}, currentActivePods: []*v1.Pod{pod1Small}, podToAdd: pod1Large, @@ -2626,8 +2575,7 @@ func TestAllocationManagerAddPod(t *testing.T) { expectedAllocatedResourcesState: map[types.UID]v1.ResourceList{pod1UID: cpu2Mem2G}, }, { - name: "IPPR Enabled - request different from current allocation. Pod still admitted based on existing allocation, but allocated resources remains unchanges.", - ipprFeatureGate: true, + name: "request different from current allocation. Pod still admitted based on existing allocation, but allocated resources remains unchanges.", initialAllocatedResourcesState: map[types.UID]v1.ResourceList{pod1UID: cpu1Mem1G, pod2UID: cpu1Mem1G}, currentActivePods: []*v1.Pod{pod1Small, pod2Small}, podToAdd: pod1Large, @@ -2647,37 +2595,11 @@ func TestAllocationManagerAddPod(t *testing.T) { // allocated Resources state must not be updated. expectedAllocatedResourcesState: map[types.UID]v1.ResourceList{pod1UID: cpu1Mem1G, pod2UID: cpu1Mem1G}, }, - { - name: "IPPR Disabled - request different from current allocation. Admission fails. Allocated resources not updated.", - ipprFeatureGate: false, - initialAllocatedResourcesState: map[types.UID]v1.ResourceList{pod1UID: cpu1Mem1G}, - currentActivePods: []*v1.Pod{pod1Small}, - podToAdd: pod1Large, - admitFunc: func(attrs *lifecycle.PodAdmitAttributes) lifecycle.PodAdmitResult { - cpuRequest := attrs.Pod.Spec.Containers[0].Resources.Requests.Cpu().Value() - if cpuRequest > 1 { - return lifecycle.PodAdmitResult{ - Admit: false, - Reason: "OutOfcpu", - Message: fmt.Sprintf("not enough CPUs available for pod %s/%s, requested: %d, available:1", attrs.Pod.Namespace, attrs.Pod.Name, cpuRequest), - } - } - return lifecycle.PodAdmitResult{Admit: true} - }, - // pod is still admitted as allocated resources are considered during admission. - expectAdmit: false, - admissionFailureReason: "OutOfcpu", - admissionFailureMessage: "not enough CPUs available for pod ns1/pod1, requested: 2, available:1", - // allocated Resources state must not be updated. - expectedAllocatedResourcesState: map[types.UID]v1.ResourceList{pod1UID: cpu1Mem1G}, - }, } for _, tc := range testCases { - featuregatetesting.SetFeatureGateEmulationVersionDuringTest(t, utilfeature.DefaultFeatureGate, version.MustParse("1.34")) t.Run(tc.name, func(t *testing.T) { tCtx := ktesting.Init(t) - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScaling, tc.ipprFeatureGate) allocationManager := makeAllocationManager(t, &containertest.FakeRuntime{}, []*v1.Pod{}, nil) podForAllocation := func(uid types.UID, resources v1.ResourceList) *v1.Pod { @@ -3118,7 +3040,6 @@ func TestAllocationManager_EmptyDirVolumeLimits_AddPod(t *testing.T) { if goruntime.GOOS == "windows" { t.Skip("InPlacePodVerticalScaling is not currently supported for Windows") } - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScaling, true) tCtx := ktesting.Init(t) tests := []struct { @@ -3313,7 +3234,6 @@ func TestAllocationManager_EmptyDirVolumeLimits_UpdatePodFromAllocation(t *testi if goruntime.GOOS == "windows" { t.Skip("InPlacePodVerticalScaling is not currently supported for Windows") } - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScaling, true) tests := []struct { name string @@ -3518,7 +3438,6 @@ func TestAllocationManager_EmptyDirVolumeLimits_RetryPendingResizes(t *testing.T if goruntime.GOOS == "windows" { t.Skip("InPlacePodVerticalScaling is not currently supported for Windows") } - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScaling, true) logger, tCtx := ktesting.NewTestContext(t) tests := []struct { @@ -4166,7 +4085,6 @@ func setupNonAllocatedCapacityTest(t *testing.T) (Manager, *v1.Pod, *v1.Pod, klo if goruntime.GOOS == "windows" { t.Skip("InPlacePodVerticalScaling is not currently supported for Windows") } - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScaling, true) featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.NodeDeclaredFeatures, true) logger, _ := ktesting.NewTestContext(t) @@ -4250,7 +4168,6 @@ func TestRetryPendingResizesTerminatingPods(t *testing.T) { if goruntime.GOOS == "windows" { t.Skip("InPlacePodVerticalScaling is not currently supported for Windows") } - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScaling, true) cpu100m := resource.MustParse("100m") cpu200m := resource.MustParse("200m") diff --git a/pkg/kubelet/allocation/features_linux.go b/pkg/kubelet/allocation/features_linux.go index 142afc415c5..89a354da2a1 100644 --- a/pkg/kubelet/allocation/features_linux.go +++ b/pkg/kubelet/allocation/features_linux.go @@ -25,9 +25,6 @@ import ( ) func IsInPlacePodVerticalScalingAllowed(pod *v1.Pod) (allowed bool, msg, reason string) { - if !utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling) { - return false, "InPlacePodVerticalScaling is disabled", "feature_gate_off" - } return true, "", "" } diff --git a/pkg/kubelet/kubelet.go b/pkg/kubelet/kubelet.go index 00c3818618a..f03882124a6 100644 --- a/pkg/kubelet/kubelet.go +++ b/pkg/kubelet/kubelet.go @@ -2114,19 +2114,17 @@ func (kl *Kubelet) SyncPod(ctx context.Context, updateType kubetypes.SyncPodType } } - if utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling) { - // Check whether a resize is in progress so we can set the PodResizeInProgressCondition accordingly. - if kl.containerRuntime.IsPodResizeInProgress(pod, podStatus) { - kl.statusManager.SetPodResizeInProgressCondition(pod.UID, "", "", pod.Generation) - } else if generation, cleared := kl.statusManager.ClearPodResizeInProgressCondition(pod.UID); cleared { - // (Allocated == Actual) => clear the resize in-progress status. - msg := events.PodResizeCompletedMsg(logger, pod, generation) - kl.recorder.WithLogger(logger).Eventf(pod, v1.EventTypeNormal, events.ResizeCompleted, "%s", msg) - } - // TODO(natasha41575): There is a race condition here, where the goroutine in the - // allocation manager may allocate a new resize and unconditionally set the - // PodResizeInProgressCondition before we set the status below. + // Check whether a resize is in progress so we can set the PodResizeInProgressCondition accordingly. + if kl.containerRuntime.IsPodResizeInProgress(pod, podStatus) { + kl.statusManager.SetPodResizeInProgressCondition(pod.UID, "", "", pod.Generation) + } else if generation, cleared := kl.statusManager.ClearPodResizeInProgressCondition(pod.UID); cleared { + // (Allocated == Actual) => clear the resize in-progress status. + msg := events.PodResizeCompletedMsg(logger, pod, generation) + kl.recorder.WithLogger(logger).Eventf(pod, v1.EventTypeNormal, events.ResizeCompleted, "%s", msg) } + // TODO(natasha41575): There is a race condition here, where the goroutine in the + // allocation manager may allocate a new resize and unconditionally set the + // PodResizeInProgressCondition before we set the status below. // Generate final API pod status with pod and status manager status apiPodStatus := kl.generateAPIPodStatus(ctx, pod, podStatus, SyncPod) @@ -2315,14 +2313,12 @@ func (kl *Kubelet) SyncPod(ctx context.Context, updateType kubetypes.SyncPodType } } - if utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling) { - for _, r := range result.SyncResults { - if r.Action == kubecontainer.ResizePodInPlace && r.Error != nil { - // If the condition already exists, the observedGeneration does not get updated. - if generation, updated := kl.statusManager.SetPodResizeInProgressCondition(pod.UID, v1.PodReasonError, r.Message, pod.Generation); updated { - msg := events.PodResizeErrorMsg(logger, pod, generation, r.Message) - kl.recorder.WithLogger(logger).Eventf(pod, v1.EventTypeWarning, events.ResizeError, "%s", msg) - } + for _, r := range result.SyncResults { + if r.Action == kubecontainer.ResizePodInPlace && r.Error != nil { + // If the condition already exists, the observedGeneration does not get updated. + if generation, updated := kl.statusManager.SetPodResizeInProgressCondition(pod.UID, v1.PodReasonError, r.Message, pod.Generation); updated { + msg := events.PodResizeErrorMsg(logger, pod, generation, r.Message) + kl.recorder.WithLogger(logger).Eventf(pod, v1.EventTypeWarning, events.ResizeError, "%s", msg) } } } @@ -2965,14 +2961,12 @@ func (kl *Kubelet) HandlePodAdditions(ctx context.Context, pods []*v1.Pod) { kl.podCertificateManager.TrackPod(ctx, pod) - if utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling) { - // Backfill the queue of pending resizes, but only after all the pods have - // been added. This ensures that no resizes get resolved until all the - // existing pods are added. - _, updatedFromAllocation := kl.allocationManager.UpdatePodFromAllocation(pod) - if updatedFromAllocation { - pendingResizes = append(pendingResizes, pod.UID) - } + // Backfill the queue of pending resizes, but only after all the pods have + // been added. This ensures that no resizes get resolved until all the + // existing pods are added. + _, updatedFromAllocation := kl.allocationManager.UpdatePodFromAllocation(pod) + if updatedFromAllocation { + pendingResizes = append(pendingResizes, pod.UID) } } kl.podWorkers.UpdatePod(ctx, UpdatePodOptions{ @@ -2982,16 +2976,14 @@ func (kl *Kubelet) HandlePodAdditions(ctx context.Context, pods []*v1.Pod) { StartTime: start, }) } - if utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling) { - kl.statusManager.BackfillPodResizeConditions(pods) - // Admitted pods with DeletionTimestamp set are still pushed here so RetryPendingResizes - // clears any backfilled PodResizePending condition with DeferredResizeResolutionTerminated. - for _, uid := range pendingResizes { - kl.allocationManager.PushPendingResize(logger, uid) - } - if len(pendingResizes) > 0 { - kl.allocationManager.RetryPendingResizes(ctx, allocation.TriggerReasonPodsAdded) - } + kl.statusManager.BackfillPodResizeConditions(pods) + // Admitted pods with DeletionTimestamp set are still pushed here so RetryPendingResizes + // clears any backfilled PodResizePending condition with DeferredResizeResolutionTerminated. + for _, uid := range pendingResizes { + kl.allocationManager.PushPendingResize(logger, uid) + } + if len(pendingResizes) > 0 { + kl.allocationManager.RetryPendingResizes(ctx, allocation.TriggerReasonPodsAdded) } } @@ -3004,13 +2996,11 @@ func (kl *Kubelet) HandlePodUpdates(ctx context.Context, pods []*v1.Pod) { oldPod, _ := kl.podManager.GetPodByUID(pod.UID) kl.podManager.UpdatePod(pod) - if utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling) { - // Skip pods that haven't been allocated yet to avoid counting them against - // node capacity before they've been admitted. - if !kl.allocationManager.HasPodAllocatedResources(pod.UID) { - logger.V(4).Info("Skipping pod update for non-allocated pod", "pod", klog.KObj(pod), "podUID", pod.UID) - continue - } + // Skip pods that haven't been allocated yet to avoid counting them against + // node capacity before they've been admitted. + if !kl.allocationManager.HasPodAllocatedResources(pod.UID) { + logger.V(4).Info("Skipping pod update for non-allocated pod", "pod", klog.KObj(pod), "podUID", pod.UID) + continue } pod, mirrorPod, wasMirror := kl.podManager.GetPodAndMirrorPod(pod) @@ -3021,21 +3011,19 @@ func (kl *Kubelet) HandlePodUpdates(ctx context.Context, pods []*v1.Pod) { } } - if utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling) { - recordResizeOperations(oldPod, pod) - _, updatedFromAllocation := kl.allocationManager.UpdatePodFromAllocation(pod) - if updatedFromAllocation { - if !kl.IsPodTerminatingOrTerminal(pod) { - kl.allocationManager.PushPendingResize(logger, pod.UID) - } - // TODO(natasha41575): If the resize is immediately actuated, it will trigger a pod sync - // and we will end up calling UpdatePod twice. Figure out if there is a way to avoid this. - kl.allocationManager.RetryPendingResizes(ctx, allocation.TriggerReasonPodUpdated) - } else { - // We can hit this case if a pending resize has been reverted, - // so we need to clear the pending resize condition. - kl.statusManager.ClearPodResizePendingCondition(pod.UID, metrics.DeferredResizeResolutionReverted) + recordResizeOperations(oldPod, pod) + _, updatedFromAllocation := kl.allocationManager.UpdatePodFromAllocation(pod) + if updatedFromAllocation { + if !kl.IsPodTerminatingOrTerminal(pod) { + kl.allocationManager.PushPendingResize(logger, pod.UID) } + // TODO(natasha41575): If the resize is immediately actuated, it will trigger a pod sync + // and we will end up calling UpdatePod twice. Figure out if there is a way to avoid this. + kl.allocationManager.RetryPendingResizes(ctx, allocation.TriggerReasonPodUpdated) + } else { + // We can hit this case if a pending resize has been reverted, + // so we need to clear the pending resize condition. + kl.statusManager.ClearPodResizePendingCondition(pod.UID, metrics.DeferredResizeResolutionReverted) } if utilfeature.DefaultFeatureGate.Enabled(features.NodeDeclaredFeatures) && oldPod != nil { @@ -3082,10 +3070,6 @@ func recordResizeOperations(oldPod, newPod *v1.Pod) { // recordPodLevelResourceResizeOperations records if any of the pod level resources need to be resized. func recordPodLevelResourceResizeOperations(oldPod, newPod *v1.Pod) { - if !utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling) { - return - } - // TODO(ndixita): add metrics for pod-level resources resize. } @@ -3182,9 +3166,7 @@ func (kl *Kubelet) HandlePodRemoves(ctx context.Context, pods []*v1.Pod) { } } - if utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling) { - kl.allocationManager.RetryPendingResizes(ctx, allocation.TriggerReasonPodsRemoved) - } + kl.allocationManager.RetryPendingResizes(ctx, allocation.TriggerReasonPodsRemoved) } // HandlePodReconcile is the callback in the SyncHandler interface for pods @@ -3211,46 +3193,44 @@ func (kl *Kubelet) HandlePodReconcile(ctx context.Context, pods []*v1.Pod) { // Static pods should be reconciled the same way as regular pods } - if utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling) { - if hasPendingResizes && !retryPendingResizes && oldPod != nil { - // If the pod has reached a terminal phase, we retry all pending resizes. - // A terminated pod releases capacity even if its allocation has already - // been purged, so check this before the non-allocated skip below. - if podutil.IsPodTerminal(pod) && !podutil.IsPodTerminal(oldPod) { - retryPendingResizes = true - triggerReason = allocation.TriggerReasonPodTerminated - } - - // If there are pending resizes, check whether the requests shrank as a result of the status - // resources changing. - opts := resourcehelper.PodResourcesOptions{ - UseStatusResources: true, - SkipPodLevelResources: !utilfeature.DefaultFeatureGate.Enabled(features.PodLevelResources), - InPlacePodLevelResourcesVerticalScalingEnabled: utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodLevelResourcesVerticalScaling), - UseDRANodeAllocatableResourceClaimStatus: utilfeature.DefaultFeatureGate.Enabled(features.DRANodeAllocatableResources), - } - - // Ignore desired resources when aggregating the resources. - allocatedOldPod, _ := kl.allocationManager.UpdatePodFromAllocation(oldPod) - allocatedPod, _ := kl.allocationManager.UpdatePodFromAllocation(pod) - - oldRequest := resourcehelper.PodRequests(allocatedOldPod, opts) - newRequest := resourcehelper.PodRequests(allocatedPod, opts) - - // If cpu or memory requests shrank, then retry the pending resizes. - if newRequest.Memory().Cmp(*oldRequest.Memory()) < 0 || - newRequest.Cpu().Cmp(*oldRequest.Cpu()) < 0 { - retryPendingResizes = true - triggerReason = allocation.TriggerReasonPodResized - } + if hasPendingResizes && !retryPendingResizes && oldPod != nil { + // If the pod has reached a terminal phase, we retry all pending resizes. + // A terminated pod releases capacity even if its allocation has already + // been purged, so check this before the non-allocated skip below. + if podutil.IsPodTerminal(pod) && !podutil.IsPodTerminal(oldPod) { + retryPendingResizes = true + triggerReason = allocation.TriggerReasonPodTerminated } - // Skip further reconciliation for pods that haven't been allocated yet. - // We still updated podManager above to keep status in sync with the API server. - if !kl.allocationManager.HasPodAllocatedResources(pod.UID) { - logger.V(4).Info("Skipping pod reconcile operations for non-allocated pod", "pod", klog.KObj(pod), "podUID", pod.UID) - continue + // If there are pending resizes, check whether the requests shrank as a result of the status + // resources changing. + opts := resourcehelper.PodResourcesOptions{ + UseStatusResources: true, + SkipPodLevelResources: !utilfeature.DefaultFeatureGate.Enabled(features.PodLevelResources), + InPlacePodLevelResourcesVerticalScalingEnabled: utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodLevelResourcesVerticalScaling), + UseDRANodeAllocatableResourceClaimStatus: utilfeature.DefaultFeatureGate.Enabled(features.DRANodeAllocatableResources), } + + // Ignore desired resources when aggregating the resources. + allocatedOldPod, _ := kl.allocationManager.UpdatePodFromAllocation(oldPod) + allocatedPod, _ := kl.allocationManager.UpdatePodFromAllocation(pod) + + oldRequest := resourcehelper.PodRequests(allocatedOldPod, opts) + newRequest := resourcehelper.PodRequests(allocatedPod, opts) + + // If cpu or memory requests shrank, then retry the pending resizes. + if newRequest.Memory().Cmp(*oldRequest.Memory()) < 0 || + newRequest.Cpu().Cmp(*oldRequest.Cpu()) < 0 { + retryPendingResizes = true + triggerReason = allocation.TriggerReasonPodResized + } + } + + // Skip further reconciliation for pods that haven't been allocated yet. + // We still updated podManager above to keep status in sync with the API server. + if !kl.allocationManager.HasPodAllocatedResources(pod.UID) { + logger.V(4).Info("Skipping pod reconcile operations for non-allocated pod", "pod", klog.KObj(pod), "podUID", pod.UID) + continue } // TODO: reconcile being calculated in the config manager is questionable, and avoiding @@ -3282,10 +3262,8 @@ func (kl *Kubelet) HandlePodReconcile(ctx context.Context, pods []*v1.Pod) { } } - if utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling) { - if retryPendingResizes { - kl.allocationManager.RetryPendingResizes(ctx, triggerReason) - } + if retryPendingResizes { + kl.allocationManager.RetryPendingResizes(ctx, triggerReason) } } @@ -3701,12 +3679,10 @@ func (a *allocatedPodManager) getAllocatedPod(pod *v1.Pod) (*v1.Pod, bool) { if pod == nil { return nil, false } - if utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling) { - if allocatedPod, ok := a.allocationManager.UpdatePodFromAllocation(pod); ok { - return allocatedPod, true - } + if allocatedPod, ok := a.allocationManager.UpdatePodFromAllocation(pod); ok { + return allocatedPod, true } - // When the feature gate is disabled or there is no allocation stored for this pod, return the pod as-is. + // When there is no allocation stored for this pod, return the pod as-is. return pod, true } diff --git a/pkg/kubelet/kubelet_pods.go b/pkg/kubelet/kubelet_pods.go index d69ae8f4330..ea9b1363e70 100644 --- a/pkg/kubelet/kubelet_pods.go +++ b/pkg/kubelet/kubelet_pods.go @@ -245,10 +245,6 @@ func (kl *Kubelet) GetActivePods() []*v1.Pod { // allocated state. func (kl *Kubelet) getAllocatedPods() []*v1.Pod { activePods := kl.GetActivePods() - if !utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling) { - return activePods - } - allocatedPods := make([]*v1.Pod, len(activePods)) for i, pod := range activePods { allocatedPods[i], _ = kl.allocationManager.UpdatePodFromAllocation(pod) @@ -2024,18 +2020,16 @@ func (kl *Kubelet) generateAPIPodStatus(ctx context.Context, pod *v1.Pod, podSta s.Conditions = append(s.Conditions, c) } } - if utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling) { - resizeStatus := kl.determinePodResizeStatus(pod, podState) - for _, c := range resizeStatus { - // Clear the condition's observed generation if BOTH The FG is disabled AND the condition's - // observed generation is not already set. We avoid overwriting the condition's observedGeneration - // in other cases, because the condition may be reflecting an older podspec. - gen := podutil.CalculatePodConditionObservedGeneration(&oldPodStatus, pod.Generation, c.Type) - if gen == 0 { - c.ObservedGeneration = 0 - } - s.Conditions = append(s.Conditions, *c) + resizeStatus := kl.determinePodResizeStatus(pod, podState) + for _, c := range resizeStatus { + // Clear the condition's observed generation if BOTH The FG is disabled AND the condition's + // observed generation is not already set. We avoid overwriting the condition's observedGeneration + // in other cases, because the condition may be reflecting an older podspec. + gen := podutil.CalculatePodConditionObservedGeneration(&oldPodStatus, pod.Generation, c.Type) + if gen == 0 { + c.ObservedGeneration = 0 } + s.Conditions = append(s.Conditions, *c) } // copy over the pod disruption conditions from state which is already @@ -2752,19 +2746,17 @@ func (kl *Kubelet) convertToAPIContainerStatuses(ctx context.Context, pod *v1.Po } } - if utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling) { - allocatedContainer := kubecontainer.GetContainerSpec(pod, cName) - if allocatedContainer != nil { - // status.Resources reflects cgroup-actuated resources. If the container is running, - // it is populated from CRI status. - status.Resources = convertContainerStatusResources(allocatedContainer, status, cStatus, oldStatuses) - // status.AllocatedResources represents the desired cgroup resource state for resize, - // and is strictly based on the uninflated standard cgroup resources requested in the spec. - // DRA based allocations are not included in AllocatedResources at the container level. - // This is because the claims can be shared across containers in the pod and can be - // shared unevenly (enforced by the DRA driver). - status.AllocatedResources = allocatedContainer.Resources.Requests - } + allocatedContainer := kubecontainer.GetContainerSpec(pod, cName) + if allocatedContainer != nil { + // status.Resources reflects cgroup-actuated resources. If the container is running, + // it is populated from CRI status. + status.Resources = convertContainerStatusResources(allocatedContainer, status, cStatus, oldStatuses) + // status.AllocatedResources represents the desired cgroup resource state for resize, + // and is strictly based on the uninflated standard cgroup resources requested in the spec. + // DRA based allocations are not included in AllocatedResources at the container level. + // This is because the claims can be shared across containers in the pod and can be + // shared unevenly (enforced by the DRA driver). + status.AllocatedResources = allocatedContainer.Resources.Requests } status.User = convertContainerStatusUser(cStatus) diff --git a/pkg/kubelet/kubelet_pods_test.go b/pkg/kubelet/kubelet_pods_test.go index e2ff477afa4..c1d1c8e0546 100644 --- a/pkg/kubelet/kubelet_pods_test.go +++ b/pkg/kubelet/kubelet_pods_test.go @@ -6202,7 +6202,6 @@ func Test_generateAPIPodStatusForInPlaceVPAEnabled(t *testing.T) { if goruntime.GOOS != "linux" { t.Skip("InPlacePodVerticalScaling cgroup resource reporting is only supported on Linux") } - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScaling, true) testContainerName := "ctr0" testContainerID := kubecontainer.ContainerID{Type: "test", ID: testContainerName} @@ -7024,7 +7023,6 @@ func TestConvertToAPIContainerStatusesForResources(t *testing.T) { if goruntime.GOOS != "linux" { t.Skip("InPlacePodVerticalScaling cgroup resource reporting is only supported on Linux") } - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScaling, true) nowTime := time.Now() testContainerName := "ctr0" @@ -10175,8 +10173,6 @@ func TestMakeMountsBindMountOptions(t *testing.T) { } func TestGenerateAPIPodStatusResizeConditionsByPodWorkerState(t *testing.T) { - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScaling, true) - tests := []struct { name string podState PodWorkerState diff --git a/pkg/kubelet/kubelet_test.go b/pkg/kubelet/kubelet_test.go index bc6bb876280..1a4235ef634 100644 --- a/pkg/kubelet/kubelet_test.go +++ b/pkg/kubelet/kubelet_test.go @@ -2855,7 +2855,6 @@ func TestHandlePodAdditionsTracksCertificatesOnlyForAdmittedPods(t *testing.T) { func TestPodResourceAllocationReset(t *testing.T) { logger, tCtx := ktesting.NewTestContext(t) - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScaling, true) testKubelet := newTestKubelet(t, false) defer testKubelet.Cleanup() kubelet := testKubelet.kubelet @@ -5215,7 +5214,6 @@ func TestHandlePodUpdates_VolumeResize(t *testing.T) { t.Skip("InPlacePodVerticalScaling is not currently supported for Windows") } - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScaling, true) featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScalingMemoryBackedVolumes, true) tCtx := ktesting.Init(t) @@ -5456,7 +5454,6 @@ func TestHandlePodReconcile_RetryPendingResizes(t *testing.T) { if goruntime.GOOS == "windows" { t.Skip("InPlacePodVerticalScaling is not currently supported for Windows") } - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScaling, true) featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.DRANodeAllocatableResources, true) logger, tCtx := ktesting.NewTestContext(t) @@ -6000,7 +5997,6 @@ func TestHandlePodUpdates_ResizeTerminatingPods(t *testing.T) { if goruntime.GOOS == "windows" { t.Skip("InPlacePodVerticalScaling is not currently supported for Windows") } - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScaling, true) metrics.Register() const podUID types.UID = "pod-1" diff --git a/pkg/kubelet/kuberuntime/kuberuntime_container.go b/pkg/kubelet/kuberuntime/kuberuntime_container.go index 0effa1e43b6..222798cf90f 100644 --- a/pkg/kubelet/kuberuntime/kuberuntime_container.go +++ b/pkg/kubelet/kuberuntime/kuberuntime_container.go @@ -701,25 +701,22 @@ func (m *kubeGenericRuntimeManager) getPodContainerStatuses(ctx context.Context, func (m *kubeGenericRuntimeManager) toKubeContainerStatus(ctx context.Context, podUID kubetypes.UID, status *runtimeapi.ContainerStatus, runtimeName string) *kubecontainer.Status { annotatedInfo := getContainerInfoFromAnnotations(ctx, status.Annotations) labeledInfo := getContainerInfoFromLabels(ctx, status.Labels) - var cStatusResources *kubecontainer.ContainerResources - if utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling) { - // If runtime reports cpu & memory resources info, add it to container status - cStatusResources = toKubeContainerResources(status.Resources) + // If runtime reports cpu & memory resources info, add it to container status + cStatusResources := toKubeContainerResources(status.Resources) - // Fill missing resource values from the actuated resources. - if cStatusResources == nil || cStatusResources.MemoryRequest == nil { - if actuatedResources, ok := m.actuatedState.GetContainerResources(podUID, labeledInfo.ContainerName); ok { - if cStatusResources == nil { - cStatusResources = &kubecontainer.ContainerResources{ - CPURequest: actuatedResources.Requests.Cpu(), - CPULimit: actuatedResources.Limits.Cpu(), - MemoryRequest: actuatedResources.Requests.Memory(), - MemoryLimit: actuatedResources.Limits.Memory(), - } - } else if cStatusResources.MemoryRequest == nil { - if memReq := actuatedResources.Requests[v1.ResourceMemory]; !memReq.IsZero() { - cStatusResources.MemoryRequest = &memReq - } + // Fill missing resource values from the actuated resources. + if cStatusResources == nil || cStatusResources.MemoryRequest == nil { + if actuatedResources, ok := m.actuatedState.GetContainerResources(podUID, labeledInfo.ContainerName); ok { + if cStatusResources == nil { + cStatusResources = &kubecontainer.ContainerResources{ + CPURequest: actuatedResources.Requests.Cpu(), + CPULimit: actuatedResources.Limits.Cpu(), + MemoryRequest: actuatedResources.Requests.Memory(), + MemoryLimit: actuatedResources.Limits.Memory(), + } + } else if cStatusResources.MemoryRequest == nil { + if memReq := actuatedResources.Requests[v1.ResourceMemory]; !memReq.IsZero() { + cStatusResources.MemoryRequest = &memReq } } } diff --git a/pkg/kubelet/kuberuntime/kuberuntime_container_test.go b/pkg/kubelet/kuberuntime/kuberuntime_container_test.go index 0c09c5a0139..ad703adfe3f 100644 --- a/pkg/kubelet/kuberuntime/kuberuntime_container_test.go +++ b/pkg/kubelet/kuberuntime/kuberuntime_container_test.go @@ -32,8 +32,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/intstr" - utilfeature "k8s.io/apiserver/pkg/util/feature" - featuregatetesting "k8s.io/component-base/featuregate/testing" v1 "k8s.io/api/core/v1" runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1" @@ -42,7 +40,6 @@ import ( apitest "k8s.io/cri-api/pkg/apis/testing" kubelettypes "k8s.io/kubelet/pkg/types" podutil "k8s.io/kubernetes/pkg/api/v1/pod" - "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/kubelet/cm" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" containertest "k8s.io/kubernetes/pkg/kubelet/container/testing" @@ -316,7 +313,6 @@ func TestToKubeContainerStatusWithResources(t *testing.T) { if goruntime.GOOS == "windows" { t.Skip("InPlacePodVerticalScaling is not currently supported on Windows.") } - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScaling, true) logger, tCtx := ktesting.NewTestContext(t) const ( diff --git a/pkg/kubelet/kuberuntime/kuberuntime_manager.go b/pkg/kubelet/kuberuntime/kuberuntime_manager.go index 90b959534ba..7ed5f1c988c 100644 --- a/pkg/kubelet/kuberuntime/kuberuntime_manager.go +++ b/pkg/kubelet/kuberuntime/kuberuntime_manager.go @@ -831,9 +831,6 @@ func (m *kubeGenericRuntimeManager) computePodResizeAction(ctx context.Context, // TODO: Move InitializeActuatedPod, UpdateActuatedPodLevelResources, and IsPodResizeInProgress // out of the runtime now that actuatedState is owned by the Kubelet. func (m *kubeGenericRuntimeManager) InitializeActuatedPod(logger klog.Logger, allocatedPod *v1.Pod) { - if !utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling) { - return - } stored, hasPod := m.actuatedState.GetPod(allocatedPod.UID) // TODO: In v1.39, when the V1 checkpoint format is no longer supported, we will still need to // check stored.Name == "" (and preserve stored.Spec.Resources and stored.Spec.Volumes below) @@ -2371,11 +2368,6 @@ func (m *kubeGenericRuntimeManager) ListPodSandboxMetrics(ctx context.Context) ( } func (m *kubeGenericRuntimeManager) UpdateActuatedPodLevelResources(logger klog.Logger, actuatedPod *v1.Pod) error { - - if !utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling) { - return nil - } - if actuatedPod.Spec.Resources == nil { return nil } diff --git a/pkg/kubelet/kuberuntime/kuberuntime_manager_test.go b/pkg/kubelet/kuberuntime/kuberuntime_manager_test.go index f992b195afe..9ee96677e0b 100644 --- a/pkg/kubelet/kuberuntime/kuberuntime_manager_test.go +++ b/pkg/kubelet/kuberuntime/kuberuntime_manager_test.go @@ -3118,7 +3118,6 @@ func TestComputePodActionsForPodResize(t *testing.T) { if goruntime.GOOS == "windows" { t.Skip("InPlacePodVerticalScaling is currently not supported on Windows") } - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScaling, true) logger, tCtx := ktesting.NewTestContext(t) _, _, m, err := createTestRuntimeManager(tCtx) @@ -4041,7 +4040,6 @@ func TestComputePodResizeActionForOOMKilledContainer(t *testing.T) { t.Skip("in-place resize is only supported on Linux") } logger, tCtx := ktesting.NewTestContext(t) - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScaling, true) _, _, m, err := createTestRuntimeManager(tCtx) m.machineInfo.MemoryCapacity = 17179860387 // 16GB require.NoError(t, err) @@ -4088,7 +4086,6 @@ func TestComputePodResizeActionForOOMKilledInitContainer(t *testing.T) { t.Skip("in-place resize is only supported on Linux") } logger, tCtx := ktesting.NewTestContext(t) - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScaling, true) _, _, m, err := createTestRuntimeManager(tCtx) m.machineInfo.MemoryCapacity = 17179860387 // 16GB require.NoError(t, err) @@ -4149,7 +4146,6 @@ func TestComputePodResizeActionForOOMKilledSidecarContainer(t *testing.T) { t.Skip("in-place resize is only supported on Linux") } logger, tCtx := ktesting.NewTestContext(t) - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScaling, true) _, _, m, err := createTestRuntimeManager(tCtx) m.machineInfo.MemoryCapacity = 17179860387 // 16GB require.NoError(t, err) @@ -4223,7 +4219,6 @@ func TestUpdatePodContainerResources(t *testing.T) { } tCtx := ktesting.Init(t) - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScaling, true) fakeRuntime, _, m, err := createTestRuntimeManager(tCtx) m.machineInfo.MemoryCapacity = 17179860387 // 16GB m.cpuCFSQuota = true @@ -4519,7 +4514,6 @@ func TestDoPodResizeAction(t *testing.T) { tCtx := ktesting.Init(t) logger := tCtx.Logger() - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScaling, true) metrics.Register() metrics.PodResizeDurationMilliseconds.Reset() @@ -7173,7 +7167,6 @@ func TestSyncResultErrorsMetric(t *testing.T) { func TestInitializeActuatedPod_PreservesActuatedVolumes(t *testing.T) { tCtx := ktesting.Init(t) featuregatetesting.SetFeatureGatesDuringTest(t, utilfeature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{ - features.InPlacePodVerticalScaling: true, features.InPlacePodLevelResourcesVerticalScaling: true, features.InPlacePodVerticalScalingMemoryBackedVolumes: true, }) diff --git a/pkg/kubelet/kuberuntime/labels_test.go b/pkg/kubelet/kuberuntime/labels_test.go index a051895a091..46fe92c1519 100644 --- a/pkg/kubelet/kuberuntime/labels_test.go +++ b/pkg/kubelet/kuberuntime/labels_test.go @@ -23,10 +23,7 @@ import ( v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" - utilfeature "k8s.io/apiserver/pkg/util/feature" - featuregatetesting "k8s.io/component-base/featuregate/testing" "k8s.io/ktesting" - "k8s.io/kubernetes/pkg/features" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" ) @@ -163,7 +160,6 @@ func TestContainerAnnotations(t *testing.T) { PreStopHandler: container.Lifecycle.PreStop, } - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScaling, true) // Test whether we can get right information from label annotations := newContainerAnnotations(tCtx, container, pod, restartCount, opts) containerInfo := getContainerInfoFromAnnotations(tCtx, annotations) diff --git a/pkg/kubelet/metrics/metrics.go b/pkg/kubelet/metrics/metrics.go index 26e471f4772..7a1d98ddd89 100644 --- a/pkg/kubelet/metrics/metrics.go +++ b/pkg/kubelet/metrics/metrics.go @@ -1598,15 +1598,13 @@ func Register() { legacyregistry.MustRegister(ImageVolumeMountedErrorsTotal) } - if utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling) { - legacyregistry.MustRegister(ContainerRequestedResizes) - legacyregistry.MustRegister(PodResizeDurationMilliseconds) - legacyregistry.MustRegister(PodPendingResizes) - legacyregistry.MustRegister(PodInfeasibleResizes) - legacyregistry.MustRegister(PodInProgressResizes) - legacyregistry.MustRegister(PodDeferredAcceptedResizes) - legacyregistry.MustRegister(PodDeferredResizeDurationSeconds) - } + legacyregistry.MustRegister(ContainerRequestedResizes) + legacyregistry.MustRegister(PodResizeDurationMilliseconds) + legacyregistry.MustRegister(PodPendingResizes) + legacyregistry.MustRegister(PodInfeasibleResizes) + legacyregistry.MustRegister(PodInProgressResizes) + legacyregistry.MustRegister(PodDeferredAcceptedResizes) + legacyregistry.MustRegister(PodDeferredResizeDurationSeconds) if utilfeature.DefaultFeatureGate.Enabled(features.PodLevelResourceManagers) { legacyregistry.MustRegister(ResourceManagerAllocationsTotal) diff --git a/pkg/kubelet/pod_workers.go b/pkg/kubelet/pod_workers.go index 4c79fbf4801..cc6b5119998 100644 --- a/pkg/kubelet/pod_workers.go +++ b/pkg/kubelet/pod_workers.go @@ -29,11 +29,9 @@ import ( "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/util/wait" - utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/client-go/tools/record" runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1" "k8s.io/klog/v2" - "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/kubelet/allocation" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" "k8s.io/kubernetes/pkg/kubelet/events" @@ -998,9 +996,7 @@ func (p *podWorkers) UpdatePod(ctx context.Context, options UpdatePodOptions) { // notify the pod worker there is a pending update status.pendingUpdate = &options - if utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling) { - status.pendingUpdate.Pod, _ = p.allocationManager.UpdatePodFromAllocation(options.Pod) - } + status.pendingUpdate.Pod, _ = p.allocationManager.UpdatePodFromAllocation(options.Pod) status.working = true updateLogger.V(4).Info("Notifying pod of pending update", "workType", status.WorkType()) select { diff --git a/pkg/kubelet/status/status_manager.go b/pkg/kubelet/status/status_manager.go index 11ebc1889ad..ed919911b85 100644 --- a/pkg/kubelet/status/status_manager.go +++ b/pkg/kubelet/status/status_manager.go @@ -1133,13 +1133,11 @@ func (m *manager) deletePodStatus(uid types.UID) { defer m.podStatusesLock.Unlock() delete(m.podStatuses, uid) m.podStartupLatencyHelper.DeletePodStartupState(uid) - if utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling) { - if conds, exists := m.podResizeConditions[uid]; exists { - m.observeDeferredResizeDuration(uid, conds.PodResizePending, metrics.DeferredResizeResolutionTerminated) - delete(m.podResizeConditions, uid) - m.recordInProgressResizeCount() - m.observePendingResizeCount() - } + if conds, exists := m.podResizeConditions[uid]; exists { + m.observeDeferredResizeDuration(uid, conds.PodResizePending, metrics.DeferredResizeResolutionTerminated) + delete(m.podResizeConditions, uid) + m.recordInProgressResizeCount() + m.observePendingResizeCount() } } @@ -1151,13 +1149,11 @@ func (m *manager) RemoveOrphanedStatuses(logger klog.Logger, podUIDs map[types.U if _, ok := podUIDs[key]; !ok { logger.V(5).Info("Removing pod from status map", "podUID", key) delete(m.podStatuses, key) - if utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling) { - if conds, exists := m.podResizeConditions[key]; exists { - m.observeDeferredResizeDuration(key, conds.PodResizePending, metrics.DeferredResizeResolutionTerminated) - delete(m.podResizeConditions, key) - m.recordInProgressResizeCount() - m.observePendingResizeCount() - } + if conds, exists := m.podResizeConditions[key]; exists { + m.observeDeferredResizeDuration(key, conds.PodResizePending, metrics.DeferredResizeResolutionTerminated) + delete(m.podResizeConditions, key) + m.recordInProgressResizeCount() + m.observePendingResizeCount() } } } diff --git a/pkg/quota/v1/evaluator/core/pods.go b/pkg/quota/v1/evaluator/core/pods.go index 00c364298bd..31631be7be6 100644 --- a/pkg/quota/v1/evaluator/core/pods.go +++ b/pkg/quota/v1/evaluator/core/pods.go @@ -399,7 +399,7 @@ func PodUsageFunc(obj runtime.Object, clock clock.Clock) (corev1.ResourceList, e } opts := resourcehelper.PodResourcesOptions{ - UseStatusResources: feature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling), + UseStatusResources: true, // SkipPodLevelResources is set to false when PodLevelResources feature is enabled. SkipPodLevelResources: !feature.DefaultFeatureGate.Enabled(features.PodLevelResources), } diff --git a/pkg/quota/v1/install/update_filter.go b/pkg/quota/v1/install/update_filter.go index 9a4ce799727..1313ec2703d 100644 --- a/pkg/quota/v1/install/update_filter.go +++ b/pkg/quota/v1/install/update_filter.go @@ -20,9 +20,7 @@ import ( v1 "k8s.io/api/core/v1" apiequality "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apiserver/pkg/util/feature" podutil "k8s.io/kubernetes/pkg/api/v1/pod" - "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/quota/v1/evaluator/core" "k8s.io/utils/clock" ) @@ -35,7 +33,7 @@ func DefaultUpdateFilter() func(resource schema.GroupVersionResource, oldObj, ne oldPod := oldObj.(*v1.Pod) newPod := newObj.(*v1.Pod) // when Resources changed - if feature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling) && hasResourcesChanged(oldPod, newPod) { + if hasResourcesChanged(oldPod, newPod) { return true } diff --git a/pkg/registry/core/pod/strategy_test.go b/pkg/registry/core/pod/strategy_test.go index 20a1a4a3d20..6536543b3f3 100644 --- a/pkg/registry/core/pod/strategy_test.go +++ b/pkg/registry/core/pod/strategy_test.go @@ -4932,34 +4932,7 @@ func TestStatusPrepareForUpdate(t *testing.T) { }, }, { - description: "drop disabled status fields/InPlacePodVerticalScaling=false", - features: map[featuregate.Feature]bool{ - features.InPlacePodVerticalScaling: false, - }, - oldPod: &api.Pod{ - ObjectMeta: metav1.ObjectMeta{Name: "pod"}, - Status: api.PodStatus{}, - }, - newPod: &api.Pod{ - ObjectMeta: metav1.ObjectMeta{Name: "pod"}, - Status: api.PodStatus{ - ContainerStatuses: []api.ContainerStatus{ - {Resources: &api.ResourceRequirements{}}, - }, - }, - }, - expected: &api.Pod{ - ObjectMeta: metav1.ObjectMeta{Name: "pod"}, - Status: api.PodStatus{ - ContainerStatuses: []api.ContainerStatus{{}}, - }, - }, - }, - { - description: "drop disabled status fields/InPlacePodVerticalScaling=true", - features: map[featuregate.Feature]bool{ - features.InPlacePodVerticalScaling: true, - }, + description: "preserve container status resources", oldPod: &api.Pod{ ObjectMeta: metav1.ObjectMeta{Name: "pod"}, Status: api.PodStatus{}, @@ -5500,9 +5473,6 @@ func TestStatusPrepareForUpdate(t *testing.T) { for _, tc := range testCases { t.Run(tc.description, func(t *testing.T) { - if v, ok := tc.features[features.InPlacePodVerticalScaling]; ok && !v { - featuregatetesting.SetFeatureGateEmulationVersionDuringTest(t, utilfeature.DefaultFeatureGate, version.MustParse("1.34")) - } featuregatetesting.SetFeatureGatesDuringTest(t, utilfeature.DefaultFeatureGate, tc.features) StatusStrategy.PrepareForUpdate(genericapirequest.NewContext(), tc.newPod, tc.oldPod) if !cmp.Equal(tc.expected, tc.newPod) { diff --git a/pkg/registry/core/rest/storage_core.go b/pkg/registry/core/rest/storage_core.go index c91b03e7a29..4f528b9ed95 100644 --- a/pkg/registry/core/rest/storage_core.go +++ b/pkg/registry/core/rest/storage_core.go @@ -33,7 +33,6 @@ import ( "k8s.io/apiserver/pkg/registry/rest" genericapiserver "k8s.io/apiserver/pkg/server" serverstorage "k8s.io/apiserver/pkg/server/storage" - utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/apiserver/pkg/util/proxy" "k8s.io/client-go/kubernetes" admissionregistrationv1client "k8s.io/client-go/kubernetes/typed/admissionregistration/v1" @@ -42,7 +41,6 @@ import ( "k8s.io/kubernetes/pkg/api/legacyscheme" api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/cluster/ports" - "k8s.io/kubernetes/pkg/features" kubeletclient "k8s.io/kubernetes/pkg/kubelet/client" "k8s.io/kubernetes/pkg/registry/core/componentstatus" endpointsstore "k8s.io/kubernetes/pkg/registry/core/endpoint/storage" @@ -245,9 +243,7 @@ func (p *legacyProvider) NewRESTStorage(apiResourceConfigSource serverstorage.AP storage[resource+"/eviction"] = podStorage.Eviction } storage[resource+"/ephemeralcontainers"] = podStorage.EphemeralContainers - if utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling) { - storage[resource+"/resize"] = podStorage.Resize - } + storage[resource+"/resize"] = podStorage.Resize } if resource := "bindings"; apiResourceConfigSource.ResourceEnabled(corev1.SchemeGroupVersion.WithResource(resource)) { storage[resource] = podStorage.LegacyBinding diff --git a/pkg/scheduler/framework/events.go b/pkg/scheduler/framework/events.go index fc939fb6643..c56bafa853d 100644 --- a/pkg/scheduler/framework/events.go +++ b/pkg/scheduler/framework/events.go @@ -107,7 +107,7 @@ type podChangeExtractor func(newPod *v1.Pod, oldPod *v1.Pod) fwk.ActionType // extractPodScaleDown interprets the update of a pod and returns PodRequestScaledDown event if any pod's resource request(s) is scaled down. func extractPodScaleDown(newPod, oldPod *v1.Pod) fwk.ActionType { opt := resource.PodResourcesOptions{ - UseStatusResources: utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling), + UseStatusResources: true, InPlacePodLevelResourcesVerticalScalingEnabled: utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodLevelResourcesVerticalScaling), } newPodRequests := resource.PodRequests(newPod, opt) @@ -132,7 +132,7 @@ func extractPodScaleDown(newPod, oldPod *v1.Pod) fwk.ActionType { // extractPodScaleUp interprets the update of a pod and returns PodRequestScaledUp event if any pod's resource request(s) is scaled up. func extractPodScaleUp(newPod, oldPod *v1.Pod) fwk.ActionType { opt := resource.PodResourcesOptions{ - UseStatusResources: utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling), + UseStatusResources: true, InPlacePodLevelResourcesVerticalScalingEnabled: utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodLevelResourcesVerticalScaling), } newPodRequests := resource.PodRequests(newPod, opt) diff --git a/pkg/scheduler/framework/plugins/feature/feature.go b/pkg/scheduler/framework/plugins/feature/feature.go index 3de8ba3ceff..8e2545fa923 100644 --- a/pkg/scheduler/framework/plugins/feature/feature.go +++ b/pkg/scheduler/framework/plugins/feature/feature.go @@ -45,7 +45,6 @@ type Features struct { EnableVolumeLimitScaling bool EnableNodeInclusionPolicyInPodTopologySpread bool EnableMatchLabelKeysInPodTopologySpread bool - EnableInPlacePodVerticalScaling bool EnableAsyncPreemption bool EnablePodLevelResources bool EnableStorageCapacityScoring bool @@ -81,7 +80,6 @@ func NewSchedulerFeaturesFromGates(featureGate featuregate.FeatureGate) Features EnableVolumeLimitScaling: featureGate.Enabled(features.VolumeLimitScaling), EnableNodeInclusionPolicyInPodTopologySpread: featureGate.Enabled(features.NodeInclusionPolicyInPodTopologySpread), EnableMatchLabelKeysInPodTopologySpread: featureGate.Enabled(features.MatchLabelKeysInPodTopologySpread), - EnableInPlacePodVerticalScaling: featureGate.Enabled(features.InPlacePodVerticalScaling), EnableAsyncPreemption: featureGate.Enabled(features.SchedulerAsyncPreemption), EnablePodLevelResources: featureGate.Enabled(features.PodLevelResources), EnableDRAPartitionableDevices: featureGate.Enabled(features.DRAPartitionableDevices), diff --git a/pkg/scheduler/framework/plugins/helper/resource_fit.go b/pkg/scheduler/framework/plugins/helper/resource_fit.go index 4de2e115a61..a426e235d26 100644 --- a/pkg/scheduler/framework/plugins/helper/resource_fit.go +++ b/pkg/scheduler/framework/plugins/helper/resource_fit.go @@ -88,7 +88,7 @@ func ShouldDelegateResourceToDRA(rName v1.ResourceName, nodeInfo fwk.NodeInfo, d // // Result: CPU: 3, Memory: 3G func ComputePodResourceRequest(pod *v1.Pod, opts ResourceRequestsOptions) framework.Resource { - // pod hasn't scheduled yet so we don't need to worry about InPlacePodVerticalScalingEnabled + // pod hasn't scheduled yet so we don't need to worry about UseStatusResources reqs := resource.PodRequests(pod, resource.PodResourcesOptions{ // SkipPodLevelResources is set to false when PodLevelResources feature is enabled. SkipPodLevelResources: !opts.EnablePodLevelResources, diff --git a/pkg/scheduler/framework/plugins/noderesources/balanced_allocation.go b/pkg/scheduler/framework/plugins/noderesources/balanced_allocation.go index 73519332f2a..d909e307b4e 100644 --- a/pkg/scheduler/framework/plugins/noderesources/balanced_allocation.go +++ b/pkg/scheduler/framework/plugins/noderesources/balanced_allocation.go @@ -189,13 +189,12 @@ func NewBalancedAllocation(_ context.Context, baArgs runtime.Object, h fwk.Handl return &BalancedAllocation{ handle: h, resourceAllocationScorer: resourceAllocationScorer{ - Name: BalancedAllocationName, - enableInPlacePodVerticalScaling: fts.EnableInPlacePodVerticalScaling, - enablePodLevelResources: fts.EnablePodLevelResources, - enableDRAExtendedResource: fts.EnableDRAExtendedResource, - scorer: balancedResourceScorer, - useRequested: true, - resources: args.Resources, + Name: BalancedAllocationName, + enablePodLevelResources: fts.EnablePodLevelResources, + enableDRAExtendedResource: fts.EnableDRAExtendedResource, + scorer: balancedResourceScorer, + useRequested: true, + resources: args.Resources, enableInPlacePodLevelResourcesVerticalScaling: fts.EnableInPlacePodLevelResourcesVerticalScaling, draManager: h.SharedDRAManager(), }, diff --git a/pkg/scheduler/framework/plugins/noderesources/fit.go b/pkg/scheduler/framework/plugins/noderesources/fit.go index e528c2d3734..6b6138fdb8b 100644 --- a/pkg/scheduler/framework/plugins/noderesources/fit.go +++ b/pkg/scheduler/framework/plugins/noderesources/fit.go @@ -92,7 +92,6 @@ var nodeResourceStrategyTypeMap = map[config.ScoringStrategyType]scorer{ type Fit struct { ignoredResources sets.Set[string] ignoredResourceGroups sets.Set[string] - enableInPlacePodVerticalScaling bool enablePodLevelResources bool enableDRAExtendedResource bool enableInPlacePodLevelResourcesVerticalScaling bool @@ -203,7 +202,6 @@ func getScorer(strategy *config.ScoringStrategy, fts feature.Features) (*resourc return nil, fmt.Errorf("scoring strategy %s is not supported", strategy.Type) } scorer := scorerFactory(strategy) - scorer.enableInPlacePodVerticalScaling = fts.EnableInPlacePodVerticalScaling scorer.enablePodLevelResources = fts.EnablePodLevelResources scorer.enableInPlacePodLevelResourcesVerticalScaling = fts.EnableInPlacePodLevelResourcesVerticalScaling return scorer, nil @@ -236,12 +234,11 @@ func NewFit(_ context.Context, plArgs runtime.Object, h fwk.Handle, fts feature. } pl := &Fit{ - ignoredResources: sets.New(args.IgnoredResources...), - ignoredResourceGroups: sets.New(args.IgnoredResourceGroups...), - enableInPlacePodVerticalScaling: fts.EnableInPlacePodVerticalScaling, - handle: h, - enablePodLevelResources: fts.EnablePodLevelResources, - enableDRAExtendedResource: fts.EnableDRAExtendedResource, + ignoredResources: sets.New(args.IgnoredResources...), + ignoredResourceGroups: sets.New(args.IgnoredResourceGroups...), + handle: h, + enablePodLevelResources: fts.EnablePodLevelResources, + enableDRAExtendedResource: fts.EnableDRAExtendedResource, enableInPlacePodLevelResourcesVerticalScaling: fts.EnableInPlacePodLevelResourcesVerticalScaling, @@ -313,19 +310,14 @@ func (f *Fit) EventsToRegister(_ context.Context) ([]fwk.ClusterEventWithHint, e events := []fwk.ClusterEventWithHint{ {Event: fwk.ClusterEvent{Resource: fwk.AssignedPod, ActionType: fwk.Delete}, QueueingHintFn: f.isSchedulableAfterAssignedPodDelete}, {Event: fwk.ClusterEvent{Resource: fwk.Node, ActionType: fwk.Add | fwk.UpdateNodeAllocatable}, QueueingHintFn: f.isSchedulableAfterNodeChange}, + {Event: fwk.ClusterEvent{Resource: fwk.AssignedPod, ActionType: fwk.UpdatePodScaleDown}, QueueingHintFn: f.isSchedulableAfterAssignedPodScaleDown}, + {Event: fwk.ClusterEvent{Resource: fwk.TargetPod, ActionType: fwk.UpdatePodScaleDown}, QueueingHintFn: f.isSchedulableAfterTargetPodScaleDown}, } if f.enableDRAExtendedResource { events = append(events, // A pod might be waiting for an exteneded resurce from a class to get created or modified. fwk.ClusterEventWithHint{Event: fwk.ClusterEvent{Resource: fwk.DeviceClass, ActionType: fwk.Add | fwk.Update}, QueueingHintFn: f.isSchedulableAfterDeviceClassEvent}) } - if f.enableInPlacePodVerticalScaling { - // If InPlacePodVerticalScaling (KEP 1287) is enabled, then UpdatePodScaleDown event should be registered - // for this plugin since a Pod update may free up resources that make other Pods schedulable. - events = append(events, - fwk.ClusterEventWithHint{Event: fwk.ClusterEvent{Resource: fwk.AssignedPod, ActionType: fwk.UpdatePodScaleDown}, QueueingHintFn: f.isSchedulableAfterAssignedPodScaleDown}, - fwk.ClusterEventWithHint{Event: fwk.ClusterEvent{Resource: fwk.TargetPod, ActionType: fwk.UpdatePodScaleDown}, QueueingHintFn: f.isSchedulableAfterTargetPodScaleDown}) - } if f.enableInPlacePodVerticalScalingSchedulerPreemption { events = append(events, fwk.ClusterEventWithHint{Event: fwk.ClusterEvent{Resource: fwk.AssignedPod, ActionType: fwk.UpdatePodScaleUp}, QueueingHintFn: f.isSchedulableAfterAssignedPodScaleUp}, @@ -436,7 +428,7 @@ func (f *Fit) haveEnoughRelevantResourcesDecreased(targetPod *v1.Pod, originalPo // the other pod was scheduled, so modification or deletion may free up some resources. originalMaxResourceReq, modifiedMaxResourceReq := &framework.Resource{}, &framework.Resource{} - opts := resource.PodResourcesOptions{UseStatusResources: f.enableInPlacePodVerticalScaling, InPlacePodLevelResourcesVerticalScalingEnabled: f.enableInPlacePodLevelResourcesVerticalScaling} + opts := resource.PodResourcesOptions{UseStatusResources: true, InPlacePodLevelResourcesVerticalScalingEnabled: f.enableInPlacePodLevelResourcesVerticalScaling} originalMaxResourceReq.SetMaxResource(resource.PodRequests(originalPod, opts)) modifiedMaxResourceReq.SetMaxResource(resource.PodRequests(modifiedPod, opts)) diff --git a/pkg/scheduler/framework/plugins/noderesources/fit_test.go b/pkg/scheduler/framework/plugins/noderesources/fit_test.go index a9e43a8bc7e..db3f1ffe573 100644 --- a/pkg/scheduler/framework/plugins/noderesources/fit_test.go +++ b/pkg/scheduler/framework/plugins/noderesources/fit_test.go @@ -1459,14 +1459,12 @@ func BenchmarkTestFitScore(b *testing.B) { func TestEventsToRegister(t *testing.T) { tests := []struct { - name string - enableInPlacePodVerticalScaling bool - enableDRAExtendedResource bool - expectedClusterEvents []fwk.ClusterEventWithHint + name string + enableDRAExtendedResource bool + expectedClusterEvents []fwk.ClusterEventWithHint }{ { - name: "Register events with InPlacePodVerticalScaling feature enabled", - enableInPlacePodVerticalScaling: true, + name: "Register events with default features", expectedClusterEvents: []fwk.ClusterEventWithHint{ {Event: fwk.ClusterEvent{Resource: fwk.AssignedPod, ActionType: fwk.Delete}}, {Event: fwk.ClusterEvent{Resource: fwk.Node, ActionType: fwk.Add | fwk.UpdateNodeAllocatable}}, @@ -1474,19 +1472,14 @@ func TestEventsToRegister(t *testing.T) { {Event: fwk.ClusterEvent{Resource: fwk.TargetPod, ActionType: fwk.UpdatePodScaleDown}}, }, }, - { - name: "Register events with default features", - expectedClusterEvents: []fwk.ClusterEventWithHint{ - {Event: fwk.ClusterEvent{Resource: fwk.AssignedPod, ActionType: fwk.Delete}}, - {Event: fwk.ClusterEvent{Resource: fwk.Node, ActionType: fwk.Add | fwk.UpdateNodeAllocatable}}, - }, - }, { name: "Register events with DRAExtendedResource feature enabled", enableDRAExtendedResource: true, expectedClusterEvents: []fwk.ClusterEventWithHint{ {Event: fwk.ClusterEvent{Resource: fwk.AssignedPod, ActionType: fwk.Delete}}, {Event: fwk.ClusterEvent{Resource: fwk.Node, ActionType: fwk.Add | fwk.UpdateNodeAllocatable}}, + {Event: fwk.ClusterEvent{Resource: fwk.AssignedPod, ActionType: fwk.UpdatePodScaleDown}}, + {Event: fwk.ClusterEvent{Resource: fwk.TargetPod, ActionType: fwk.UpdatePodScaleDown}}, {Event: fwk.ClusterEvent{Resource: fwk.DeviceClass, ActionType: fwk.Add | fwk.Update}}, }, }, @@ -1494,7 +1487,7 @@ func TestEventsToRegister(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - fp := &Fit{enableInPlacePodVerticalScaling: test.enableInPlacePodVerticalScaling, enableDRAExtendedResource: test.enableDRAExtendedResource} + fp := &Fit{enableDRAExtendedResource: test.enableDRAExtendedResource} _, ctx := ktesting.NewTestContext(t) actualClusterEvents, err := fp.EventsToRegister(ctx) if err != nil { @@ -1594,9 +1587,7 @@ func Test_isSchedulableAfterTargetPodScaleDown(t *testing.T) { for name, tc := range testcases { t.Run(name, func(t *testing.T) { logger, ctx := ktesting.NewTestContext(t) - p, err := NewFit(ctx, &config.NodeResourcesFitArgs{ScoringStrategy: defaultScoringStrategy}, nil, plfeature.Features{ - EnableInPlacePodVerticalScaling: true, - }) + p, err := NewFit(ctx, &config.NodeResourcesFitArgs{ScoringStrategy: defaultScoringStrategy}, nil, plfeature.Features{}) if err != nil { t.Fatal(err) } @@ -1678,7 +1669,6 @@ func Test_isSchedulableAfterAssignedPodScaleDown(t *testing.T) { t.Run(name, func(t *testing.T) { logger, ctx := ktesting.NewTestContext(t) p, err := NewFit(ctx, &config.NodeResourcesFitArgs{ScoringStrategy: defaultScoringStrategy}, nil, plfeature.Features{ - EnableInPlacePodVerticalScaling: true, EnableInPlacePodVerticalScalingSchedulerPreemption: true, }) if err != nil { @@ -3042,7 +3032,7 @@ func TestScorePlacement_Resources(t *testing.T) { expectedScore: 30, }, { - name: "Ignores container status resources when InPlacePodVerticalScaling is disabled", + name: "Honors container status resources", nodes: []*v1.Node{ st.MakeNode().Name("node1").Capacity(cpuAndMemory("5000m", "5000")).Obj(), st.MakeNode().Name("node2").Capacity(cpuAndMemory("5000m", "5000")).Obj(), @@ -3056,25 +3046,6 @@ func TestScorePlacement_Resources(t *testing.T) { {Name: "cpu", Weight: 1}, {Name: "memory", Weight: 1}, }, - features: plfeature.Features{EnableInPlacePodVerticalScaling: false}, - expectedScore: 10, - }, - { - name: "Honors container status resources when InPlacePodVerticalScaling is enabled", - nodes: []*v1.Node{ - st.MakeNode().Name("node1").Capacity(cpuAndMemory("5000m", "5000")).Obj(), - st.MakeNode().Name("node2").Capacity(cpuAndMemory("5000m", "5000")).Obj(), - }, - placementNodeNames: []string{"node1", "node2"}, - podGroupPods: []*v1.Pod{ - withContainerStatusResources(st.MakePod().UID("foo").Req(cpuAndMemory("1000m", "1000")).Obj(), cpuAndMemory("4000m", "4000")), - }, - podGroupAssignments: map[types.UID]string{"foo": "node1"}, - resourceSpec: []config.ResourceSpec{ - {Name: "cpu", Weight: 1}, - {Name: "memory", Weight: 1}, - }, - features: plfeature.Features{EnableInPlacePodVerticalScaling: true}, expectedScore: 40, }, { @@ -3097,7 +3068,6 @@ func TestScorePlacement_Resources(t *testing.T) { }, features: plfeature.Features{ EnablePodLevelResources: true, - EnableInPlacePodVerticalScaling: true, EnableInPlacePodLevelResourcesVerticalScaling: false, }, expectedScore: 10, @@ -3122,7 +3092,6 @@ func TestScorePlacement_Resources(t *testing.T) { }, features: plfeature.Features{ EnablePodLevelResources: true, - EnableInPlacePodVerticalScaling: true, EnableInPlacePodLevelResourcesVerticalScaling: true, }, expectedScore: 40, @@ -3880,25 +3849,11 @@ func TestFitScoreFeatureGates(t *testing.T) { }, }, { - name: "InPlacePodVerticalScaling disabled ignores container status resources", + name: "Uses container status resources", pod: withContainerStatusResources( st.MakePod().Req(cpuAndMemory("1000m", "400Mi")).Obj(), cpuAndMemory("2000m", "800Mi"), ), - features: plfeature.Features{EnableInPlacePodVerticalScaling: false}, - expectedScores: map[config.ScoringStrategyType]fwk.NodeScoreList{ - config.LeastAllocated: {{Name: "node1", Score: 80}, {Name: "node2", Score: 85}}, - config.MostAllocated: {{Name: "node1", Score: 20}, {Name: "node2", Score: 15}}, - config.RequestedToCapacityRatio: {{Name: "node1", Score: 40}, {Name: "node2", Score: 30}}, - }, - }, - { - name: "InPlacePodVerticalScaling enabled uses container status resources", - pod: withContainerStatusResources( - st.MakePod().Req(cpuAndMemory("1000m", "400Mi")).Obj(), - cpuAndMemory("2000m", "800Mi"), - ), - features: plfeature.Features{EnableInPlacePodVerticalScaling: true}, expectedScores: map[config.ScoringStrategyType]fwk.NodeScoreList{ config.LeastAllocated: {{Name: "node1", Score: 60}, {Name: "node2", Score: 70}}, config.MostAllocated: {{Name: "node1", Score: 40}, {Name: "node2", Score: 30}}, @@ -3916,7 +3871,6 @@ func TestFitScoreFeatureGates(t *testing.T) { ), features: plfeature.Features{ EnablePodLevelResources: true, - EnableInPlacePodVerticalScaling: true, EnableInPlacePodLevelResourcesVerticalScaling: false, }, expectedScores: map[config.ScoringStrategyType]fwk.NodeScoreList{ @@ -3936,7 +3890,6 @@ func TestFitScoreFeatureGates(t *testing.T) { ), features: plfeature.Features{ EnablePodLevelResources: true, - EnableInPlacePodVerticalScaling: true, EnableInPlacePodLevelResourcesVerticalScaling: true, }, // Effective request: cpu=3000m, memory=1200Mi -> node1: 60% cpu, 60% mem; node2: 30% cpu, 60% mem diff --git a/pkg/scheduler/framework/plugins/noderesources/resource_allocation.go b/pkg/scheduler/framework/plugins/noderesources/resource_allocation.go index b5e1824048c..c46cc2b48b6 100644 --- a/pkg/scheduler/framework/plugins/noderesources/resource_allocation.go +++ b/pkg/scheduler/framework/plugins/noderesources/resource_allocation.go @@ -53,7 +53,6 @@ type DRACaches struct { // resourceAllocationScorer contains information to calculate resource allocation score. type resourceAllocationScorer struct { Name string - enableInPlacePodVerticalScaling bool enablePodLevelResources bool enableDRAExtendedResource bool enableInPlacePodLevelResourcesVerticalScaling bool @@ -238,7 +237,7 @@ func (r *resourceAllocationScorer) calculateResourceAllocatableRequest( func (r *resourceAllocationScorer) calculatePodResourceRequest(pod *v1.Pod, resourceName v1.ResourceName) int64 { opts := resourcehelper.PodResourcesOptions{ - UseStatusResources: r.enableInPlacePodVerticalScaling, + UseStatusResources: true, InPlacePodLevelResourcesVerticalScalingEnabled: r.enableInPlacePodLevelResourcesVerticalScaling, // SkipPodLevelResources is set to false when PodLevelResources feature is enabled. SkipPodLevelResources: !r.enablePodLevelResources, diff --git a/pkg/scheduler/framework/types.go b/pkg/scheduler/framework/types.go index dd1a2fbe12d..c0a3a881785 100644 --- a/pkg/scheduler/framework/types.go +++ b/pkg/scheduler/framework/types.go @@ -1283,8 +1283,7 @@ type PodInfo struct { PreferredAffinityTerms []fwk.WeightedAffinityTerm PreferredAntiAffinityTerms []fwk.WeightedAffinityTerm // cachedResource contains precomputed resources for Pod (podResource). - // The value can change only if InPlacePodVerticalScaling is enabled. - // In that case, the whole PodInfo object is recreated (for assigned pods in cache). + // When a pod is resized in-place, the whole PodInfo object is recreated (for assigned pods in cache). // cachedResource contains a podResource, computed when adding a scheduled pod to NodeInfo. // When removing a pod from a NodeInfo, i.e. finding victims for preemption or removing a pod from a cluster, // cachedResource is used instead, what provides a noticeable performance boost. @@ -1355,13 +1354,12 @@ func (pi *PodInfo) CalculateResource() fwk.PodResource { if pi.cachedResource != nil { return *pi.cachedResource } - inPlacePodVerticalScalingEnabled := utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling) podLevelResourcesEnabled := utilfeature.DefaultFeatureGate.Enabled(features.PodLevelResources) inPlacePodLevelResourcesVerticalScalingEnabled := utilfeature.DefaultMutableFeatureGate.Enabled(features.InPlacePodLevelResourcesVerticalScaling) nodeAllocatableResourcesDRAEnabled := utilfeature.DefaultFeatureGate.Enabled(features.DRANodeAllocatableResources) requests := resourcehelper.PodRequests(pi.Pod, resourcehelper.PodResourcesOptions{ - UseStatusResources: inPlacePodVerticalScalingEnabled, + UseStatusResources: true, InPlacePodLevelResourcesVerticalScalingEnabled: inPlacePodLevelResourcesVerticalScalingEnabled, // SkipPodLevelResources is set to false when PodLevelResources feature is enabled. SkipPodLevelResources: !podLevelResourcesEnabled, @@ -1372,7 +1370,7 @@ func (pi *PodInfo) CalculateResource() fwk.PodResource { non0Requests := requests if len(nonMissingContainerRequests) > 0 { non0Requests = resourcehelper.PodRequests(pi.Pod, resourcehelper.PodResourcesOptions{ - UseStatusResources: inPlacePodVerticalScalingEnabled, + UseStatusResources: true, InPlacePodLevelResourcesVerticalScalingEnabled: inPlacePodLevelResourcesVerticalScalingEnabled, // SkipPodLevelResources is set to false when PodLevelResources feature is enabled. SkipPodLevelResources: !podLevelResourcesEnabled, diff --git a/pkg/scheduler/framework/types_test.go b/pkg/scheduler/framework/types_test.go index dbd01a61099..c5e7bf757d9 100644 --- a/pkg/scheduler/framework/types_test.go +++ b/pkg/scheduler/framework/types_test.go @@ -3159,7 +3159,6 @@ func TestPodInfoCalculateResources(t *testing.T) { } func TestCalculatePodResourcesWithResize(t *testing.T) { - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScaling, true) featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.NodeDeclaredFeatures, true) featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodLevelResourcesVerticalScaling, true) diff --git a/pkg/scheduler/schedule_one_test.go b/pkg/scheduler/schedule_one_test.go index c45330b44d5..ca7b8008a6d 100644 --- a/pkg/scheduler/schedule_one_test.go +++ b/pkg/scheduler/schedule_one_test.go @@ -1404,7 +1404,6 @@ func TestHandleSchedulingFailureSkipsRecreatedPod(t *testing.T) { } func TestHandleSchedulingFailureForDeferredResizePod(t *testing.T) { - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScaling, true) featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScalingSchedulerPreemption, true) logger, ctx := ktesting.NewTestContext(t) diff --git a/pkg/scheduler/scheduler_test.go b/pkg/scheduler/scheduler_test.go index 5f2145408fc..cc7c34154e6 100644 --- a/pkg/scheduler/scheduler_test.go +++ b/pkg/scheduler/scheduler_test.go @@ -20,7 +20,6 @@ import ( "context" "errors" "fmt" - "slices" "sort" "strings" "sync" @@ -36,7 +35,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/sets" - "k8s.io/apimachinery/pkg/util/version" "k8s.io/apiserver/pkg/util/feature" clientfeatures "k8s.io/client-go/features" clientfeaturestesting "k8s.io/client-go/features/testing" @@ -925,11 +923,10 @@ func Test_buildQueueingHintMap(t *testing.T) { // It verifies that a given set of plugins is correctly registered for a specific set of cluster events. func Test_UnionedGVKs(t *testing.T) { tests := []struct { - name string - plugins schedulerapi.PluginSet - want map[fwk.EventResource]fwk.ActionType - enableInPlacePodVerticalScaling bool - enableGenericWorkload bool + name string + plugins schedulerapi.PluginSet + want map[fwk.EventResource]fwk.ActionType + enableGenericWorkload bool }{ { name: "filter without EnqueueExtensions plugin", @@ -981,8 +978,7 @@ func Test_UnionedGVKs(t *testing.T) { fwk.DeviceClass: fwk.All, fwk.PodGroup: fwk.All, }, - enableGenericWorkload: true, - enableInPlacePodVerticalScaling: true, + enableGenericWorkload: true, }, { name: "node plugin", @@ -1044,25 +1040,6 @@ func Test_UnionedGVKs(t *testing.T) { }, want: map[fwk.EventResource]fwk.ActionType{}, }, - { - name: "plugins with default profile (InPlacePodVerticalScaling disabled)", - plugins: schedulerapi.PluginSet{Enabled: defaults.PluginsV1.MultiPoint.Enabled}, - want: map[fwk.EventResource]fwk.ActionType{ - fwk.AssignedPod: fwk.Add | fwk.UpdatePodLabel | fwk.Delete, - fwk.TargetPod: fwk.UpdatePodLabel | fwk.UpdatePodGeneratedResourceClaim | fwk.UpdatePodToleration | fwk.UpdatePodSchedulingGatesEliminated, - fwk.Node: fwk.Add | fwk.UpdateNodeAllocatable | fwk.UpdateNodeLabel | fwk.UpdateNodeTaint | fwk.Delete, - fwk.CSINode: fwk.All - fwk.Delete, - fwk.CSIDriver: fwk.Update, - fwk.CSIStorageCapacity: fwk.All - fwk.Delete, - fwk.PersistentVolume: fwk.All - fwk.Delete, - fwk.PersistentVolumeClaim: fwk.All - fwk.Delete, - fwk.StorageClass: fwk.All - fwk.Delete, - fwk.VolumeAttachment: fwk.Delete, - fwk.DeviceClass: fwk.All - fwk.Delete, - fwk.ResourceClaim: fwk.All, - fwk.ResourceSlice: fwk.All - fwk.Delete, - }, - }, { name: "plugins with default profile", plugins: defaults.PluginsV1.MultiPoint, @@ -1083,7 +1060,6 @@ func Test_UnionedGVKs(t *testing.T) { fwk.ResourceClaim: fwk.All, fwk.ResourceSlice: fwk.All - fwk.Delete, }, - enableInPlacePodVerticalScaling: true, }, { name: "plugin registering to a specific pod resource 'AssignedPod'", @@ -1119,38 +1095,15 @@ func Test_UnionedGVKs(t *testing.T) { fwk.ResourceSlice: fwk.All - fwk.Delete, fwk.PodGroup: fwk.Add | fwk.Update, }, - enableGenericWorkload: true, - enableInPlacePodVerticalScaling: true, + enableGenericWorkload: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { pluginConfig := defaults.PluginConfigsV1 - if !tt.enableInPlacePodVerticalScaling { - // In place pod resize GA'd in 1.35. Set emulation version to 1.34 for tests that do not have the flag set - featuregatetesting.SetFeatureGateEmulationVersionDuringTest(t, feature.DefaultFeatureGate, version.MustParse("1.34")) - // DRADeviceBindingConditions is alpha in 1.34 (disabled by default). - // Strip BindingTimeout from DynamicResources args to avoid validation failure. - // StorageCapacityScoring is alpha in 1.34 (disabled by default). - // Strip Shape from VolumeBinding args to avoid validation failure. - // BindTimeoutSeconds: 600 is the default value of VolumeBindingArgs when StorageCapacityScoring is disabled. - pluginConfig = slices.Clone(pluginConfig) - for i := range pluginConfig { - switch pluginConfig[i].Name { - case "DynamicResources": - pluginConfig[i].Args = &schedulerapi.DynamicResourcesArgs{} - case "VolumeBinding": - pluginConfig[i].Args = &schedulerapi.VolumeBindingArgs{BindTimeoutSeconds: 600} - } - } - } else { - featuregatetesting.SetFeatureGatesDuringTest(t, feature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{ - features.GenericWorkload: tt.enableGenericWorkload, - }) - } featuregatetesting.SetFeatureGatesDuringTest(t, feature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{ - features.InPlacePodVerticalScaling: tt.enableInPlacePodVerticalScaling, + features.GenericWorkload: tt.enableGenericWorkload, }) _, ctx := ktesting.NewTestContext(t) diff --git a/plugin/pkg/admission/limitranger/admission_test.go b/plugin/pkg/admission/limitranger/admission_test.go index e45aa976bef..1329f53c8b1 100644 --- a/plugin/pkg/admission/limitranger/admission_test.go +++ b/plugin/pkg/admission/limitranger/admission_test.go @@ -821,7 +821,6 @@ func TestLimitRangerAllowPodResize(t *testing.T) { informerFactory.Start(wait.NeverStop) testPod := validPod("testPod", 1, api.ResourceRequirements{}) - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScaling, true) err = handler.Validate(context.TODO(), admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "resize", admission.Update, &metav1.UpdateOptions{}, false, nil), nil) if err == nil { t.Errorf("expect error, but got nil") @@ -833,7 +832,6 @@ func TestLimitRangerAllowPodResize(t *testing.T) { // already holds is valid by definition and must not be rejected by a constraint // it no longer satisfies; a value the resize changes is checked as on create. func TestLimitRangerValidatePodResize(t *testing.T) { - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScaling, true) featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PodLevelResources, true) cpu := func(request, limit string) api.ResourceRequirements { diff --git a/plugin/pkg/admission/podresize/admission.go b/plugin/pkg/admission/podresize/admission.go index c9f4a0de042..c3d1d593716 100644 --- a/plugin/pkg/admission/podresize/admission.go +++ b/plugin/pkg/admission/podresize/admission.go @@ -30,11 +30,9 @@ import ( genericadmissioninitializer "k8s.io/apiserver/pkg/admission/initializer" "k8s.io/client-go/informers" corev1listers "k8s.io/client-go/listers/core/v1" - "k8s.io/component-base/featuregate" "k8s.io/component-helpers/resource" "k8s.io/kubernetes/pkg/apis/core" v1 "k8s.io/kubernetes/pkg/apis/core/v1" - "k8s.io/kubernetes/pkg/features" ) const ( @@ -55,8 +53,7 @@ func Register(plugins *admission.Plugins) { // Plugin is an admission controller that validates pod resize requests against the node's capabilities. type Plugin struct { *admission.Handler - nodeLister corev1listers.NodeLister - inPlacePodVerticalScalingEnabled bool + nodeLister corev1listers.NodeLister } var _ admission.ValidationInterface = &Plugin{} @@ -76,11 +73,6 @@ func (p *Plugin) SetExternalKubeInformerFactory(f informers.SharedInformerFactor p.SetReadyFunc(nodeInformer.Informer().HasSynced) } -// InspectFeatureGates sets the feature gates for the plugin. -func (p *Plugin) InspectFeatureGates(featureGates featuregate.FeatureGate) { - p.inPlacePodVerticalScalingEnabled = featureGates.Enabled(features.InPlacePodVerticalScaling) -} - // ValidateInitialization ensures that the plugin is properly initialized. func (p *Plugin) ValidateInitialization() error { if p.nodeLister == nil { @@ -92,11 +84,6 @@ func (p *Plugin) ValidateInitialization() error { // Validate is the core of the admission controller logic. func (p *Plugin) Validate(ctx context.Context, a admission.Attributes, o admission.ObjectInterfaces) error { - // Ignore if the feature gate is not enabled. - if !p.inPlacePodVerticalScalingEnabled { - return nil - } - if a.GetOperation() != admission.Update { return nil } diff --git a/plugin/pkg/admission/podresize/admission_test.go b/plugin/pkg/admission/podresize/admission_test.go index 4d357ba0ef7..7753601c22c 100644 --- a/plugin/pkg/admission/podresize/admission_test.go +++ b/plugin/pkg/admission/podresize/admission_test.go @@ -255,7 +255,6 @@ func TestResizeAdmission(t *testing.T) { plugin, err := NewPlugin() require.NoError(t, err) plugin.SetExternalKubeInformerFactory(informerFactory) - plugin.inPlacePodVerticalScalingEnabled = true stopCh := make(chan struct{}) defer close(stopCh) diff --git a/staging/src/k8s.io/api/core/v1/generated.proto b/staging/src/k8s.io/api/core/v1/generated.proto index 47925834a41..28e05bcd362 100644 --- a/staging/src/k8s.io/api/core/v1/generated.proto +++ b/staging/src/k8s.io/api/core/v1/generated.proto @@ -801,7 +801,6 @@ message Container { // resizePolicy is the resize policy for the container. // This field cannot be set on ephemeral containers. - // +featureGate=InPlacePodVerticalScaling // +optional // +listType=atomic repeated ContainerResizePolicy resizePolicy = 23; @@ -1176,7 +1175,6 @@ message ContainerStatus { // resources represents the compute resource requests and limits that have been successfully // enacted on the running container after it has been started or has been successfully resized. - // +featureGate=InPlacePodVerticalScaling // +optional optional ResourceRequirements resources = 11; @@ -1630,7 +1628,6 @@ message EphemeralContainerCommon { optional ResourceRequirements resources = 8; // resizePolicy is the resources resize policy for the container. - // +featureGate=InPlacePodVerticalScaling // +optional // +listType=atomic repeated ContainerResizePolicy resizePolicy = 23; @@ -5275,7 +5272,6 @@ message PodStatus { // Deprecated: Resize status is moved to two pod conditions PodResizePending and PodResizeInProgress. // PodResizePending will track states where the spec has been resized, but the Kubelet has not yet allocated the resources. // PodResizeInProgress will track in-progress resizes, and should be present whenever allocated resources != acknowledged resources. - // +featureGate=InPlacePodVerticalScaling // +optional optional string resize = 14; diff --git a/staging/src/k8s.io/api/core/v1/types.go b/staging/src/k8s.io/api/core/v1/types.go index bceec47d1c8..66ecf4ef153 100644 --- a/staging/src/k8s.io/api/core/v1/types.go +++ b/staging/src/k8s.io/api/core/v1/types.go @@ -3327,7 +3327,6 @@ type Container struct { Resources ResourceRequirements `json:"resources,omitempty" protobuf:"bytes,8,opt,name=resources"` // resizePolicy is the resize policy for the container. // This field cannot be set on ephemeral containers. - // +featureGate=InPlacePodVerticalScaling // +optional // +listType=atomic ResizePolicy []ContainerResizePolicy `json:"resizePolicy,omitempty" protobuf:"bytes,23,rep,name=resizePolicy"` @@ -3721,7 +3720,6 @@ type ContainerStatus struct { AllocatedResources ResourceList `json:"allocatedResources,omitempty" protobuf:"bytes,10,rep,name=allocatedResources,casttype=ResourceList,castkey=ResourceName"` // resources represents the compute resource requests and limits that have been successfully // enacted on the running container after it has been started or has been successfully resized. - // +featureGate=InPlacePodVerticalScaling // +optional Resources *ResourceRequirements `json:"resources,omitempty" protobuf:"bytes,11,opt,name=resources"` // volumeMounts represents the status of volume mounts. @@ -5656,7 +5654,6 @@ type EphemeralContainerCommon struct { // +optional Resources ResourceRequirements `json:"resources,omitempty" protobuf:"bytes,8,opt,name=resources"` // resizePolicy is the resources resize policy for the container. - // +featureGate=InPlacePodVerticalScaling // +optional // +listType=atomic ResizePolicy []ContainerResizePolicy `json:"resizePolicy,omitempty" protobuf:"bytes,23,rep,name=resizePolicy"` @@ -5958,7 +5955,6 @@ type PodStatus struct { // Deprecated: Resize status is moved to two pod conditions PodResizePending and PodResizeInProgress. // PodResizePending will track states where the spec has been resized, but the Kubelet has not yet allocated the resources. // PodResizeInProgress will track in-progress resizes, and should be present whenever allocated resources != acknowledged resources. - // +featureGate=InPlacePodVerticalScaling // +optional Resize PodResizeStatus `json:"resize,omitempty" protobuf:"bytes,14,opt,name=resize,casttype=PodResizeStatus"` diff --git a/staging/src/k8s.io/component-helpers/resource/helpers.go b/staging/src/k8s.io/component-helpers/resource/helpers.go index 237d7deec6f..9d98d2c49d5 100644 --- a/staging/src/k8s.io/component-helpers/resource/helpers.go +++ b/staging/src/k8s.io/component-helpers/resource/helpers.go @@ -41,8 +41,7 @@ type PodResourcesOptions struct { // functions. All existing values in Reuse will be lost. Reuse v1.ResourceList // UseStatusResources indicates whether resources reported by the PodStatus should be considered - // when evaluating the pod resources. This MUST be false if the InPlacePodVerticalScaling - // feature is not enabled. + // when evaluating the pod resources. UseStatusResources bool // InPlacePodLevelResourcesVerticalScalingEnabled indicates whether resources reported by the // PodStatus should be considered when evaluating the pod resources. @@ -313,7 +312,7 @@ func AggregateContainerRequests(pod *v1.Pod, opts PodResourcesOptions) v1.Resour var allocatedReqs, actuatedReqs v1.ResourceList // When pod-level status maps are populated, they already contain the aggregate values across all containers. // When unpopulated (e.g., at creation time or when feature gates are disabled), we fall back to container status aggregation. - // Once InPlacePodLevelResourcesVerticalScaling and InPlacePodVerticalScaling are GA and feature gates are removed, + // Once InPlacePodLevelResourcesVerticalScaling is GA and its feature gate is removed, // container-level fallback becomes redundant because max(spec, actuated, allocated) naturally evaluates to spec at creation time. if opts.InPlacePodLevelResourcesVerticalScalingEnabled && pod.Status.AllocatedResources != nil && pod.Status.Resources != nil && pod.Status.Resources.Requests != nil { allocatedReqs = pod.Status.AllocatedResources @@ -461,7 +460,7 @@ func AggregateContainerLimits(pod *v1.Pod, opts PodResourcesOptions) v1.Resource var actuatedLimits v1.ResourceList // When pod-level status maps are populated, they already contain the aggregate values across all containers. // When unpopulated (e.g., at creation time or when feature gates are disabled), we fall back to container status aggregation. - // Once InPlacePodLevelResourcesVerticalScaling and InPlacePodVerticalScaling are GA and feature gates are removed, + // Once InPlacePodLevelResourcesVerticalScaling is GA and its feature gate is removed, // container-level fallback becomes redundant because max(spec, actuated) naturally evaluates to spec at creation time. if opts.InPlacePodLevelResourcesVerticalScalingEnabled && pod.Status.Resources != nil && pod.Status.Resources.Limits != nil { actuatedLimits = pod.Status.Resources.Limits diff --git a/test/compatibility_lifecycle/reference/feature_list.md b/test/compatibility_lifecycle/reference/feature_list.md index 038a798f86c..e705b8f7b30 100644 --- a/test/compatibility_lifecycle/reference/feature_list.md +++ b/test/compatibility_lifecycle/reference/feature_list.md @@ -81,7 +81,7 @@ | DetectCacheInconsistency | :ballot_box_with_check: 1.34+ | | | 1.34– | | | | [code](https://cs.k8s.io/?q=%5CbDetectCacheInconsistency%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbDetectCacheInconsistency%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | DisableCPUQuotaWithExclusiveCPUs | :ballot_box_with_check: 1.33+ | :closed_lock_with_key: 1.37+ | | 1.33–1.35 | | 1.36– | | [code](https://cs.k8s.io/?q=%5CbDisableCPUQuotaWithExclusiveCPUs%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbDisableCPUQuotaWithExclusiveCPUs%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | DisableNodeKubeProxyVersion | :ballot_box_with_check: 1.33+ | :closed_lock_with_key: 1.36+ | 1.29–1.30 | | | 1.31– | | [code](https://cs.k8s.io/?q=%5CbDisableNodeKubeProxyVersion%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbDisableNodeKubeProxyVersion%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | -| DynamicNodeLocalEphemeralVolumes | | | 1.38– | | | | InPlacePodVerticalScaling
NodeDeclaredFeatures | [code](https://cs.k8s.io/?q=%5CbDynamicNodeLocalEphemeralVolumes%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbDynamicNodeLocalEphemeralVolumes%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | +| DynamicNodeLocalEphemeralVolumes | | | 1.38– | | | | NodeDeclaredFeatures | [code](https://cs.k8s.io/?q=%5CbDynamicNodeLocalEphemeralVolumes%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbDynamicNodeLocalEphemeralVolumes%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | EmptyDirVolumeMode | | | 1.37– | | | | | [code](https://cs.k8s.io/?q=%5CbEmptyDirVolumeMode%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbEmptyDirVolumeMode%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | EnvFiles | :ballot_box_with_check: 1.35+ | :closed_lock_with_key: 1.38+ | 1.34 | 1.35–1.37 | 1.38– | | | [code](https://cs.k8s.io/?q=%5CbEnvFiles%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbEnvFiles%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | EtcdRangeStream | :ballot_box_with_check: 1.37+ | | | 1.37– | | | | [code](https://cs.k8s.io/?q=%5CbEtcdRangeStream%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbEtcdRangeStream%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | @@ -107,20 +107,19 @@ | ImageVolumeWithDigest | | | 1.35– | | | | ImageVolume | [code](https://cs.k8s.io/?q=%5CbImageVolumeWithDigest%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbImageVolumeWithDigest%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | InOrderInformers | :ballot_box_with_check: 1.33+ | :closed_lock_with_key: 1.36+ | | 1.33–1.35 | 1.36– | | | [code](https://cs.k8s.io/?q=%5CbInOrderInformers%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbInOrderInformers%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | InOrderInformersBatchProcess | :ballot_box_with_check: 1.35+ | | | 1.35– | | | | [code](https://cs.k8s.io/?q=%5CbInOrderInformersBatchProcess%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbInOrderInformersBatchProcess%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | -| InPlacePodLevelResourcesVerticalScaling | :ballot_box_with_check: 1.36+ | | 1.35 | 1.36– | | | InPlacePodVerticalScaling
NodeDeclaredFeatures
PodLevelResources | [code](https://cs.k8s.io/?q=%5CbInPlacePodLevelResourcesVerticalScaling%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbInPlacePodLevelResourcesVerticalScaling%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | -| InPlacePodVerticalScaling | :ballot_box_with_check: 1.33+ | :closed_lock_with_key: 1.35+ | 1.27–1.32 | 1.33–1.34 | 1.35– | | | [code](https://cs.k8s.io/?q=%5CbInPlacePodVerticalScaling%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbInPlacePodVerticalScaling%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | -| InPlacePodVerticalScalingExclusiveCPUs | | | 1.32– | | | | InPlacePodVerticalScaling | [code](https://cs.k8s.io/?q=%5CbInPlacePodVerticalScalingExclusiveCPUs%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbInPlacePodVerticalScalingExclusiveCPUs%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | -| InPlacePodVerticalScalingExclusiveMemory | | | 1.34– | | | | InPlacePodVerticalScaling | [code](https://cs.k8s.io/?q=%5CbInPlacePodVerticalScalingExclusiveMemory%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbInPlacePodVerticalScalingExclusiveMemory%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | -| InPlacePodVerticalScalingInitContainers | :ballot_box_with_check: 1.36+ | :closed_lock_with_key: 1.37+ | | 1.36 | 1.37– | | InPlacePodVerticalScaling
NodeDeclaredFeatures | [code](https://cs.k8s.io/?q=%5CbInPlacePodVerticalScalingInitContainers%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbInPlacePodVerticalScalingInitContainers%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | -| InPlacePodVerticalScalingMemoryBackedVolumes | | | 1.37– | | | | InPlacePodVerticalScaling
NodeDeclaredFeatures | [code](https://cs.k8s.io/?q=%5CbInPlacePodVerticalScalingMemoryBackedVolumes%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbInPlacePodVerticalScalingMemoryBackedVolumes%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | -| InPlacePodVerticalScalingSchedulerPreemption | | | 1.37– | | | | InPlacePodVerticalScaling | [code](https://cs.k8s.io/?q=%5CbInPlacePodVerticalScalingSchedulerPreemption%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbInPlacePodVerticalScalingSchedulerPreemption%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | +| InPlacePodLevelResourcesVerticalScaling | :ballot_box_with_check: 1.36+ | | 1.35 | 1.36– | | | NodeDeclaredFeatures
PodLevelResources | [code](https://cs.k8s.io/?q=%5CbInPlacePodLevelResourcesVerticalScaling%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbInPlacePodLevelResourcesVerticalScaling%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | +| InPlacePodVerticalScalingExclusiveCPUs | | | 1.32– | | | | | [code](https://cs.k8s.io/?q=%5CbInPlacePodVerticalScalingExclusiveCPUs%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbInPlacePodVerticalScalingExclusiveCPUs%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | +| InPlacePodVerticalScalingExclusiveMemory | | | 1.34– | | | | | [code](https://cs.k8s.io/?q=%5CbInPlacePodVerticalScalingExclusiveMemory%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbInPlacePodVerticalScalingExclusiveMemory%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | +| InPlacePodVerticalScalingInitContainers | :ballot_box_with_check: 1.36+ | :closed_lock_with_key: 1.37+ | | 1.36 | 1.37– | | NodeDeclaredFeatures | [code](https://cs.k8s.io/?q=%5CbInPlacePodVerticalScalingInitContainers%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbInPlacePodVerticalScalingInitContainers%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | +| InPlacePodVerticalScalingMemoryBackedVolumes | | | 1.37– | | | | NodeDeclaredFeatures | [code](https://cs.k8s.io/?q=%5CbInPlacePodVerticalScalingMemoryBackedVolumes%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbInPlacePodVerticalScalingMemoryBackedVolumes%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | +| InPlacePodVerticalScalingSchedulerPreemption | | | 1.37– | | | | | [code](https://cs.k8s.io/?q=%5CbInPlacePodVerticalScalingSchedulerPreemption%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbInPlacePodVerticalScalingSchedulerPreemption%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | InformerResourceVersion | :ballot_box_with_check: 1.35+ | | 1.30–1.34 | | 1.35– | | | [code](https://cs.k8s.io/?q=%5CbInformerResourceVersion%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbInformerResourceVersion%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | InterPodAffinityHostnameFastPath | | | 1.37– | | | | | [code](https://cs.k8s.io/?q=%5CbInterPodAffinityHostnameFastPath%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbInterPodAffinityHostnameFastPath%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | KMSv1 | :ballot_box_with_check: 1.0+ | | | | 1.0–1.27 | 1.28– | | [code](https://cs.k8s.io/?q=%5CbKMSv1%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbKMSv1%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | KubeAPIServerWorkloadsTrust | | | 1.38– | | | | ClusterTrustBundle
ClusterTrustBundleProjection | [code](https://cs.k8s.io/?q=%5CbKubeAPIServerWorkloadsTrust%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbKubeAPIServerWorkloadsTrust%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | KubeProxyIPVS | :ballot_box_with_check: 1.0+ | | | | 1.0–1.36 | 1.37– | | [code](https://cs.k8s.io/?q=%5CbKubeProxyIPVS%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbKubeProxyIPVS%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | KubeProxyNFTablesLocalhostNodePorts | :ballot_box_with_check: 1.38+ | | 1.37 | 1.38– | | | | [code](https://cs.k8s.io/?q=%5CbKubeProxyNFTablesLocalhostNodePorts%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbKubeProxyNFTablesLocalhostNodePorts%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | -| KubeletAllocatedPodsEndpoint | | | 1.37– | | | | InPlacePodVerticalScaling | [code](https://cs.k8s.io/?q=%5CbKubeletAllocatedPodsEndpoint%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbKubeletAllocatedPodsEndpoint%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | +| KubeletAllocatedPodsEndpoint | | | 1.37– | | | | | [code](https://cs.k8s.io/?q=%5CbKubeletAllocatedPodsEndpoint%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbKubeletAllocatedPodsEndpoint%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | KubeletCgroupDriverFromCRI | :ballot_box_with_check: 1.31+ | :closed_lock_with_key: 1.34+ | 1.28–1.30 | 1.31–1.33 | 1.34– | | | [code](https://cs.k8s.io/?q=%5CbKubeletCgroupDriverFromCRI%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbKubeletCgroupDriverFromCRI%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | KubeletCrashLoopBackOffMax | :ballot_box_with_check: 1.35+ | | 1.32–1.34 | 1.35– | | | | [code](https://cs.k8s.io/?q=%5CbKubeletCrashLoopBackOffMax%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbKubeletCrashLoopBackOffMax%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | KubeletEnsureSecretPulledImages | :ballot_box_with_check: 1.35+ | | 1.33–1.34 | 1.35– | | | | [code](https://cs.k8s.io/?q=%5CbKubeletEnsureSecretPulledImages%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbKubeletEnsureSecretPulledImages%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | diff --git a/test/compatibility_lifecycle/reference/versioned_feature_list.yaml b/test/compatibility_lifecycle/reference/versioned_feature_list.yaml index 53576b16ca7..a99f1c59e70 100644 --- a/test/compatibility_lifecycle/reference/versioned_feature_list.yaml +++ b/test/compatibility_lifecycle/reference/versioned_feature_list.yaml @@ -917,20 +917,6 @@ lockToDefault: false preRelease: Beta version: "1.36" -- name: InPlacePodVerticalScaling - versionedSpecs: - - default: false - lockToDefault: false - preRelease: Alpha - version: "1.27" - - default: true - lockToDefault: false - preRelease: Beta - version: "1.33" - - default: true - lockToDefault: true - preRelease: GA - version: "1.35" - name: InPlacePodVerticalScalingExclusiveCPUs versionedSpecs: - default: false diff --git a/test/e2e/node/pod_resize.go b/test/e2e/node/pod_resize.go index fc746be47cb..9f58209e507 100644 --- a/test/e2e/node/pod_resize.go +++ b/test/e2e/node/pod_resize.go @@ -1317,7 +1317,7 @@ func doPodResizeDeferredPreemptionTests(f *framework.Framework) { }) } -var _ = SIGDescribe(framework.WithSerial(), "Pod InPlace Resize Container (scheduler-focused)", framework.WithFeatureGate(features.InPlacePodVerticalScaling), func() { +var _ = SIGDescribe(framework.WithSerial(), "Pod InPlace Resize Container (scheduler-focused)", func() { f := framework.NewDefaultFramework("pod-resize-scheduler-tests") ginkgo.BeforeEach(func(ctx context.Context) { node, err := e2enode.GetRandomReadySchedulableNode(ctx, f.ClientSet) @@ -1329,7 +1329,7 @@ var _ = SIGDescribe(framework.WithSerial(), "Pod InPlace Resize Container (sched doPodResizeSchedulerTests(f) }) -var _ = SIGDescribe(framework.WithSerial(), "Pod InPlace Resize Container (deferred-resizes)", framework.WithFeatureGate(features.InPlacePodVerticalScaling), func() { +var _ = SIGDescribe(framework.WithSerial(), "Pod InPlace Resize Container (deferred-resizes)", func() { f := framework.NewDefaultFramework("pod-resize-deferred-resize-tests") ginkgo.BeforeEach(func(ctx context.Context) { node, err := e2enode.GetRandomReadySchedulableNode(ctx, f.ClientSet) @@ -1341,7 +1341,7 @@ var _ = SIGDescribe(framework.WithSerial(), "Pod InPlace Resize Container (defer doPodResizeRetryDeferredTests(f) }) -var _ = SIGDescribe("Pod InPlace Resize Container (resource-quota)", framework.WithFeatureGate(features.InPlacePodVerticalScaling), func() { +var _ = SIGDescribe("Pod InPlace Resize Container (resource-quota)", func() { f := framework.NewDefaultFramework("pod-resize-resource-quota-tests") ginkgo.BeforeEach(func(ctx context.Context) { @@ -1354,7 +1354,7 @@ var _ = SIGDescribe("Pod InPlace Resize Container (resource-quota)", framework.W doPodResizeResourceQuotaTests(f) }) -var _ = SIGDescribe("Pod InPlace Resize Container (limit-ranger)", framework.WithFeatureGate(features.InPlacePodVerticalScaling), func() { +var _ = SIGDescribe("Pod InPlace Resize Container (limit-ranger)", func() { f := framework.NewDefaultFramework("pod-resize-limit-ranger-tests") ginkgo.BeforeEach(func(ctx context.Context) { @@ -1368,7 +1368,6 @@ var _ = SIGDescribe("Pod InPlace Resize Container (limit-ranger)", framework.Wit }) var _ = SIGDescribe(framework.WithSerial(), framework.WithSlow(), "Pod InPlace Resize Container (deferred-resize-preemption)", - framework.WithFeatureGate(features.InPlacePodVerticalScaling), framework.WithFeatureGate(features.InPlacePodVerticalScalingSchedulerPreemption), func() { f := framework.NewDefaultFramework("pod-resize-deferred-preemption-tests") diff --git a/test/integration/pods/pods_test.go b/test/integration/pods/pods_test.go index 0ab687f35f1..6ccc48bd53b 100644 --- a/test/integration/pods/pods_test.go +++ b/test/integration/pods/pods_test.go @@ -857,7 +857,6 @@ func TestPodUpdateEphemeralContainers(t *testing.T) { } func TestPodResizeRBAC(t *testing.T) { - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScaling, true) server := kubeapiservertesting.StartTestServerOrDie(t, nil, append(framework.DefaultTestServerFlags(), "--authorization-mode=RBAC"), framework.SharedEtcd()) defer server.TearDownFn() @@ -961,7 +960,6 @@ func TestPodResizeRBAC(t *testing.T) { } func TestPodResize(t *testing.T) { - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScaling, true) // Disable ServiceAccount admission plugin as we don't have serviceaccount controller running. server := kubeapiservertesting.StartTestServerOrDie(t, nil, framework.DefaultTestServerFlags(), framework.SharedEtcd()) defer server.TearDownFn() diff --git a/test/integration/scheduler/preemption/deferred_resize_preemption_test.go b/test/integration/scheduler/preemption/deferred_resize_preemption_test.go index 2d3f8ce3468..7e04c96a4d1 100644 --- a/test/integration/scheduler/preemption/deferred_resize_preemption_test.go +++ b/test/integration/scheduler/preemption/deferred_resize_preemption_test.go @@ -42,7 +42,6 @@ import ( func TestDeferredResizePodPreemption(t *testing.T) { // Setup API server with feature gates enabled featuregatetesting.SetFeatureGatesDuringTest(t, utilfeature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{ - features.InPlacePodVerticalScaling: true, features.InPlacePodVerticalScalingSchedulerPreemption: true, }) @@ -451,7 +450,6 @@ func setUpPreemptionTestWithContext(t *testing.T, testCtx *testutils.TestContext func TestDeferredResizeQueueingHints(t *testing.T) { featuregatetesting.SetFeatureGatesDuringTest(t, utilfeature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{ - features.InPlacePodVerticalScaling: true, features.InPlacePodVerticalScalingSchedulerPreemption: true, }) @@ -616,7 +614,6 @@ func TestDeferredResizeQueueingHints(t *testing.T) { func TestDeferredResizeNodePreemptionPolicy(t *testing.T) { featuregatetesting.SetFeatureGatesDuringTest(t, utilfeature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{ - features.InPlacePodVerticalScaling: true, features.InPlacePodVerticalScalingSchedulerPreemption: true, }) @@ -743,7 +740,6 @@ func TestDeferredResizeNodePreemptionPolicy(t *testing.T) { func TestDeferredResizeQueueingHandlers(t *testing.T) { t.Run("AddPod handler enqueues existing deferred pod on scheduler startup", func(t *testing.T) { featuregatetesting.SetFeatureGatesDuringTest(t, utilfeature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{ - features.InPlacePodVerticalScaling: true, features.InPlacePodVerticalScalingSchedulerPreemption: true, }) @@ -833,7 +829,6 @@ func TestDeferredResizeQueueingHandlers(t *testing.T) { t.Run("UpdatePod handler enqueues pod when it transitions to deferred resize", func(t *testing.T) { featuregatetesting.SetFeatureGatesDuringTest(t, utilfeature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{ - features.InPlacePodVerticalScaling: true, features.InPlacePodVerticalScalingSchedulerPreemption: true, }) @@ -940,7 +935,6 @@ func TestDeferredResizeQueueingHandlers(t *testing.T) { t.Run("UpdatePod handler removes pod from queue when deferred condition is cleared", func(t *testing.T) { featuregatetesting.SetFeatureGatesDuringTest(t, utilfeature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{ - features.InPlacePodVerticalScaling: true, features.InPlacePodVerticalScalingSchedulerPreemption: true, }) @@ -1035,7 +1029,6 @@ func TestDeferredResizeQueueingHandlers(t *testing.T) { t.Run("DeletePod handler removes pod from both cache and scheduling queue when deleted", func(t *testing.T) { featuregatetesting.SetFeatureGatesDuringTest(t, utilfeature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{ - features.InPlacePodVerticalScaling: true, features.InPlacePodVerticalScalingSchedulerPreemption: true, }) diff --git a/test/integration/scheduler/queueing/queue.go b/test/integration/scheduler/queueing/queue.go index 1be6bc9c1b9..c7e86dcad00 100644 --- a/test/integration/scheduler/queueing/queue.go +++ b/test/integration/scheduler/queueing/queue.go @@ -2579,7 +2579,6 @@ var CoreResourceEnqueueTestCases = []*CoreResourceEnqueueTestCase{ // moved properly upon their registered events. func RunTestCoreResourceEnqueue(t *testing.T, tt *CoreResourceEnqueueTestCase) { //nolint:forbidigo // calls ndftesting.NewMockFeature/ktesting.NewTestContext, which require *testing.T t.Helper() - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScaling, true) if tt.EnableDRAExtendedResource { featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.DRAExtendedResource, true) } diff --git a/test/integration/scheduler_perf/event_handling/performance-config.yaml b/test/integration/scheduler_perf/event_handling/performance-config.yaml index 3bdd7feaf8c..201284417c7 100644 --- a/test/integration/scheduler_perf/event_handling/performance-config.yaml +++ b/test/integration/scheduler_perf/event_handling/performance-config.yaml @@ -144,8 +144,6 @@ # that through QHints make the pods schedulable. # Plugins covered: InterPodAffinity, NodeResources, NodeUnschedulable, PodTopologySpread, SchedulingGates and TaintToleration. - name: EventHandlingPodUpdate - featureGates: - InPlacePodVerticalScaling: true workloadTemplate: # Collect metrics from all createPods ops that initially create unschedulable pods (type: unsched). - opcode: startCollectingMetrics