Merge pull request #143587 from antcybersec/remove-gate-nodeswap

pkg/features: remove GA feature gate NodeSwap
This commit is contained in:
kubernetes-prow[bot] authored and GitHub committed 2026-11-05 18:01:25 +00:00
commit a6f04b605a
12 files changed
+15 -91

No files matched your search

+7 -9
View File
@@ -911,15 +911,13 @@ func run(ctx context.Context, s *options.KubeletServer, kubeDeps *kubelet.Depend
return fmt.Errorf("topology manager policy options %v require feature gates %q enabled",
s.TopologyManagerPolicyOptions, features.TopologyManagerPolicyOptions)
}
if utilfeature.DefaultFeatureGate.Enabled(features.NodeSwap) {
if !kubeletutil.IsCgroup2UnifiedMode() && s.MemorySwap.SwapBehavior == string(kubelettypes.LimitedSwap) {
// This feature is not supported for cgroupv1 so we are failing early.
return fmt.Errorf("swap feature is enabled and LimitedSwap but it is only supported with cgroupv2")
}
if !s.FailSwapOn && s.MemorySwap.SwapBehavior == "" {
// This is just a log because we are using a default of NoSwap.
logger.Info("NoSwap is set due to memorySwapBehavior not specified", "memorySwapBehavior", s.MemorySwap.SwapBehavior, "FailSwapOn", s.FailSwapOn)
}
if !kubeletutil.IsCgroup2UnifiedMode() && s.MemorySwap.SwapBehavior == string(kubelettypes.LimitedSwap) {
// LimitedSwap is not supported for cgroupv1 so we are failing early.
return fmt.Errorf("LimitedSwap is only supported with cgroupv2")
}
if !s.FailSwapOn && s.MemorySwap.SwapBehavior == "" {
// This is just a log because we are using a default of NoSwap.
logger.Info("NoSwap is set due to memorySwapBehavior not specified", "memorySwapBehavior", s.MemorySwap.SwapBehavior, "FailSwapOn", s.FailSwapOn)
}
kubeDeps.ContainerManager, err = cm.NewContainerManager(
-15
View File
@@ -777,12 +777,6 @@ const (
// The recommendation is to enable it on a need basis for debugging purposes and disabling otherwise.
NodeLogQuery featuregate.Feature = "NodeLogQuery"
// owner: @iholder101 @kannon92
// kep: https://kep.k8s.io/2400
//
// Permits kubelet to run with swap enabled.
NodeSwap featuregate.Feature = "NodeSwap"
// owner: @sanposhiho, @wojtek-t
// kep: https://kep.k8s.io/5278
//
@@ -1775,13 +1769,6 @@ var defaultVersionedKubernetesFeatureGates = map[featuregate.Feature]featuregate
{Version: version.MustParse("1.36"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.39, locked to default in 1.36
},
NodeSwap: {
{Version: version.MustParse("1.22"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.28"), Default: false, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.30"), Default: true, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.34"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.37
},
NominatedNodeNameForExpectation: {
{Version: version.MustParse("1.34"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.35"), Default: true, PreRelease: featuregate.Beta},
@@ -2572,8 +2559,6 @@ var defaultKubernetesFeatureGateDependencies = map[featuregate.Feature][]feature
NodeLogQuery: {},
NodeSwap: {},
NominatedNodeNameForExpectation: {},
OpportunisticBatching: {},
@@ -1694,7 +1694,6 @@ func TestRetryPendingResizesWithSwap(t *testing.T) {
featuregatetesting.SetFeatureGatesDuringTest(t, utilfeature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{
features.InPlacePodVerticalScaling: true,
features.NodeSwap: true,
})
logger, tCtx := ktesting.NewTestContext(t)
noSwapContainerName, swapContainerName := "test-container-noswap", "test-container-limitedswap"
@@ -250,17 +250,12 @@ func ValidateKubeletConfiguration(kc *kubeletconfig.KubeletConfiguration, featur
allErrors = append(allErrors, fmt.Errorf("invalid configuration: Specifying shutdownGracePeriodByPodPriority requires feature gate GracefulNodeShutdownBasedOnPodPriority"))
}
}
if localFeatureGate.Enabled(features.NodeSwap) {
switch kc.MemorySwap.SwapBehavior {
case "":
case string(kubetypes.NoSwap):
case string(kubetypes.LimitedSwap):
default:
allErrors = append(allErrors, fmt.Errorf("invalid configuration: memorySwap.swapBehavior %q must be one of: \"\", %q or %q", kc.MemorySwap.SwapBehavior, kubetypes.LimitedSwap, kubetypes.NoSwap))
}
}
if !localFeatureGate.Enabled(features.NodeSwap) && kc.MemorySwap != (kubeletconfig.MemorySwapConfiguration{}) {
allErrors = append(allErrors, fmt.Errorf("invalid configuration: memorySwap.swapBehavior cannot be set when NodeSwap feature flag is disabled"))
switch kc.MemorySwap.SwapBehavior {
case "":
case string(kubetypes.NoSwap):
case string(kubetypes.LimitedSwap):
default:
allErrors = append(allErrors, fmt.Errorf("invalid configuration: memorySwap.swapBehavior %q must be one of: \"\", %q or %q", kc.MemorySwap.SwapBehavior, kubetypes.LimitedSwap, kubetypes.NoSwap))
}
if localFeatureGate.Enabled(features.KubeletCrashLoopBackOffMax) {
@@ -396,7 +396,6 @@ func TestValidateKubeletConfiguration(t *testing.T) {
}, {
name: "invalid MemorySwap.SwapBehavior",
configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
conf.FeatureGates = map[string]bool{"NodeSwap": true}
conf.MemorySwap.SwapBehavior = "invalid-behavior"
return conf
},
@@ -305,7 +305,7 @@ func (m *kubeGenericRuntimeManager) configureContainerSwapResources(ctx context.
func (m *kubeGenericRuntimeManager) GetContainerSwapBehavior(pod *v1.Pod, container *v1.Container) types.SwapBehavior {
c := types.SwapBehavior(m.memorySwapBehavior)
if c == types.LimitedSwap {
if !utilfeature.DefaultFeatureGate.Enabled(kubefeatures.NodeSwap) || !m.getSwapControllerAvailable() {
if !m.getSwapControllerAvailable() {
return types.NoSwap
}
+1 -1
View File
@@ -284,7 +284,7 @@ func MachineInfo(nodeName string,
node.Status.Capacity[v1.ResourceName(removedResource)] = *resource.NewQuantity(int64(0), resource.DecimalSI)
}
if utilfeature.DefaultFeatureGate.Enabled(features.NodeSwap) && info.SwapCapacity != 0 {
if info.SwapCapacity != 0 {
node.Status.NodeInfo.Swap = &v1.NodeSwapStatus{
Capacity: ptr.To(int64(info.SwapCapacity)),
}
-17
View File
@@ -37,12 +37,9 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/rand"
"k8s.io/apimachinery/pkg/util/uuid"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/component-base/featuregate"
"k8s.io/component-base/version"
"k8s.io/klog/v2"
"k8s.io/ktesting"
"k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/kubelet/cm"
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
kubecontainertest "k8s.io/kubernetes/pkg/kubelet/container/testing"
@@ -452,7 +449,6 @@ func TestMachineInfo(t *testing.T) {
expectNode *v1.Node
expectEvents []testEvent
disableLocalStorageCapacityIsolation bool
featureGateDependencies []featuregate.Feature
}{
{
desc: "machine identifiers, basic capacity and allocatable",
@@ -897,23 +893,10 @@ func TestMachineInfo(t *testing.T) {
},
},
},
featureGateDependencies: []featuregate.Feature{features.NodeSwap},
},
}
for _, tc := range cases {
featureGatesMissing := false
for _, featureGateDependency := range tc.featureGateDependencies {
if !utilfeature.DefaultFeatureGate.Enabled(featureGateDependency) {
featureGatesMissing = true
break
}
}
if featureGatesMissing {
continue
}
t.Run(tc.desc, func(t *testing.T) {
ctx := ktesting.Init(t)
machineInfoFunc := func() (*cadvisorapi.MachineInfo, error) {
@@ -153,7 +153,6 @@
| NodeInclusionPolicyInPodTopologySpread | :ballot_box_with_check: 1.26+ | :closed_lock_with_key: 1.33+ | 1.25 | 1.26–1.32 | 1.33– | | | [code](https://cs.k8s.io/?q=%5CbNodeInclusionPolicyInPodTopologySpread%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbNodeInclusionPolicyInPodTopologySpread%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) |
| NodeLifecycleConditions | | | 1.37– | | | | | [code](https://cs.k8s.io/?q=%5CbNodeLifecycleConditions%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbNodeLifecycleConditions%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) |
| NodeLogQuery | :ballot_box_with_check: 1.36+ | :closed_lock_with_key: 1.36+ | 1.27–1.29 | 1.30–1.35 | 1.36– | | | [code](https://cs.k8s.io/?q=%5CbNodeLogQuery%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbNodeLogQuery%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) |
| NodeSwap | :ballot_box_with_check: 1.30+ | :closed_lock_with_key: 1.34+ | 1.22–1.27 | 1.28–1.33 | 1.34– | | | [code](https://cs.k8s.io/?q=%5CbNodeSwap%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbNodeSwap%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) |
| NominatedNodeNameForExpectation | :ballot_box_with_check: 1.35+ | | 1.34 | 1.35– | | | | [code](https://cs.k8s.io/?q=%5CbNominatedNodeNameForExpectation%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbNominatedNodeNameForExpectation%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) |
| OpenAPIEnums | :ballot_box_with_check: 1.24+ | | 1.23 | 1.24– | | | | [code](https://cs.k8s.io/?q=%5CbOpenAPIEnums%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbOpenAPIEnums%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) |
| OpenAPIV2LazyBuild | :ballot_box_with_check: 1.38+ | | | 1.38– | | | | [code](https://cs.k8s.io/?q=%5CbOpenAPIV2LazyBuild%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbOpenAPIV2LazyBuild%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) |
@@ -1373,24 +1373,6 @@
lockToDefault: true
preRelease: GA
version: "1.36"
- name: NodeSwap
versionedSpecs:
- default: false
lockToDefault: false
preRelease: Alpha
version: "1.22"
- default: false
lockToDefault: false
preRelease: Beta
version: "1.28"
- default: true
lockToDefault: false
preRelease: Beta
version: "1.30"
- default: true
lockToDefault: true
preRelease: GA
version: "1.34"
- name: NominatedNodeNameForExpectation
versionedSpecs:
- default: false
-6
View File
@@ -174,12 +174,6 @@ featureGates:
}
overrides["PodAndContainerStatsFromCRI"] = false
overrides["KubeletServiceAccountTokenForCredentialProviders"] = true
// In some CI jobs, `NodeSwap` is explicitly disabled as the images are cgroupv1 based,
// so such flags should be picked up directly from the initial configuration
if _, ok := initialConfig.FeatureGates["NodeSwap"]; ok {
overrides["NodeSwap"] = initialConfig.FeatureGates["NodeSwap"]
}
initialConfig.FeatureGates = overrides
// Compare the expected config with the merged config
gomega.Expect(initialConfig).To(gomega.BeComparableTo(mergedConfig), "Merged kubelet config does not match the expected configuration.")
-10
View File
@@ -38,7 +38,6 @@ import (
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/rand"
"k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/kubelet/types"
"k8s.io/kubernetes/test/e2e/framework"
e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
@@ -62,10 +61,6 @@ var _ = SIGDescribe("Swap", "[LinuxOnly]", ginkgo.Ordered, feature.Swap, framewo
addAfterEachForCleaningUpPods(f)
f.NamespacePodSecurityLevel = admissionapi.LevelBaseline
ginkgo.BeforeEach(func() {
gomega.Expect(isSwapFeatureGateEnabled()).To(gomega.BeTrueBecause("NodeSwap feature should be on"))
})
f.Context(framework.WithNodeConformance(), func() {
ginkgo.DescribeTable("with configuration", func(qosClass v1.PodQOSClass, memoryRequestEqualLimit bool) {
@@ -459,11 +454,6 @@ func runPodAndWaitUntilScheduled(f *framework.Framework, pod *v1.Pod) *v1.Pod {
return pod
}
func isSwapFeatureGateEnabled() bool {
ginkgo.By("figuring if NodeSwap feature gate is turned on")
return e2eskipper.IsFeatureGateEnabled(features.NodeSwap)
}
func isPodCgroupV2(f *framework.Framework, pod *v1.Pod) bool {
ginkgo.By("figuring is test pod runs cgroup v2")
output := e2epod.ExecCommandInContainer(f, pod.Name, pod.Spec.Containers[0].Name, "/bin/sh", "-ec", `if test -f "/sys/fs/cgroup/cgroup.controllers"; then echo "true"; else echo "false"; fi`)