From 96edaa43d2eabeaef6961dd4e17fab1fda461da1 Mon Sep 17 00:00:00 2001 From: Hank Freund Date: Sun, 2 Nov 2025 13:15:52 +0000 Subject: [PATCH] Set KubeletCrashLoopBackOffMax feature gate to default enabled for beta. --- pkg/features/kube_features.go | 5 ++- pkg/kubelet/apis/config/fuzzer/fuzzer.go | 3 ++ .../KubeletConfiguration/after/v1beta1.yaml | 3 +- .../roundtrip/default/v1beta1.yaml | 3 +- .../apis/config/v1beta1/defaults_test.go | 30 +++++++++----- pkg/kubelet/kubelet_test.go | 41 +++++++------------ .../reference/versioned_feature_list.yaml | 4 ++ 7 files changed, 48 insertions(+), 41 deletions(-) diff --git a/pkg/features/kube_features.go b/pkg/features/kube_features.go index 5870b3a4cfa..d7f8ddcfac9 100644 --- a/pkg/features/kube_features.go +++ b/pkg/features/kube_features.go @@ -435,8 +435,8 @@ const ( // fallback to using it's cgroupDriver option. KubeletCgroupDriverFromCRI featuregate.Feature = "KubeletCgroupDriverFromCRI" - // owner: @lauralorenz - // kep: https://kep.k8s.io/4603 + // owner: @lauralorenz @hankfreund + // kep: https://kep.k8s.io/5593 // // Enables support for configurable per-node backoff maximums for restarting // containers (aka containers in CrashLoopBackOff) @@ -1328,6 +1328,7 @@ var defaultVersionedKubernetesFeatureGates = map[featuregate.Feature]featuregate KubeletCrashLoopBackOffMax: { {Version: version.MustParse("1.32"), Default: false, PreRelease: featuregate.Alpha}, + {Version: version.MustParse("1.35"), Default: true, PreRelease: featuregate.Beta}, }, KubeletEnsureSecretPulledImages: { diff --git a/pkg/kubelet/apis/config/fuzzer/fuzzer.go b/pkg/kubelet/apis/config/fuzzer/fuzzer.go index 16f7c223860..b1643f1b950 100644 --- a/pkg/kubelet/apis/config/fuzzer/fuzzer.go +++ b/pkg/kubelet/apis/config/fuzzer/fuzzer.go @@ -126,6 +126,9 @@ func Funcs(codecs runtimeserializer.CodecFactory) []interface{} { "AllAlpha": false, "AllBeta": true, } + obj.CrashLoopBackOff = kubeletconfig.CrashLoopBackOffConfig{ + MaxContainerRestartPeriod: &metav1.Duration{Duration: 5 * time.Minute}, + } }, // tokenAttributes field is only supported in v1 CredentialProvider diff --git a/pkg/kubelet/apis/config/scheme/testdata/KubeletConfiguration/after/v1beta1.yaml b/pkg/kubelet/apis/config/scheme/testdata/KubeletConfiguration/after/v1beta1.yaml index 515a995b572..5a1fea35e2c 100644 --- a/pkg/kubelet/apis/config/scheme/testdata/KubeletConfiguration/after/v1beta1.yaml +++ b/pkg/kubelet/apis/config/scheme/testdata/KubeletConfiguration/after/v1beta1.yaml @@ -25,7 +25,8 @@ cpuCFSQuota: true cpuCFSQuotaPeriod: 100ms cpuManagerPolicy: none cpuManagerReconcilePeriod: 10s -crashLoopBackOff: {} +crashLoopBackOff: + maxContainerRestartPeriod: 5m0s enableControllerAttachDetach: true enableDebugFlagsHandler: true enableDebuggingHandlers: true diff --git a/pkg/kubelet/apis/config/scheme/testdata/KubeletConfiguration/roundtrip/default/v1beta1.yaml b/pkg/kubelet/apis/config/scheme/testdata/KubeletConfiguration/roundtrip/default/v1beta1.yaml index 8d065e6447c..9bf8c939610 100644 --- a/pkg/kubelet/apis/config/scheme/testdata/KubeletConfiguration/roundtrip/default/v1beta1.yaml +++ b/pkg/kubelet/apis/config/scheme/testdata/KubeletConfiguration/roundtrip/default/v1beta1.yaml @@ -25,7 +25,8 @@ cpuCFSQuota: true cpuCFSQuotaPeriod: 100ms cpuManagerPolicy: none cpuManagerReconcilePeriod: 10s -crashLoopBackOff: {} +crashLoopBackOff: + maxContainerRestartPeriod: 5m0s enableControllerAttachDetach: true enableDebugFlagsHandler: true enableDebuggingHandlers: true diff --git a/pkg/kubelet/apis/config/v1beta1/defaults_test.go b/pkg/kubelet/apis/config/v1beta1/defaults_test.go index d6cedf9a1af..42e20535a65 100644 --- a/pkg/kubelet/apis/config/v1beta1/defaults_test.go +++ b/pkg/kubelet/apis/config/v1beta1/defaults_test.go @@ -132,7 +132,9 @@ func TestSetDefaultsKubeletConfiguration(t *testing.T) { LocalStorageCapacityIsolation: ptr.To(true), PodLogsDir: DefaultPodLogsDir, SingleProcessOOMKill: nil, - CrashLoopBackOff: v1beta1.CrashLoopBackOffConfig{}, + CrashLoopBackOff: v1beta1.CrashLoopBackOffConfig{ + MaxContainerRestartPeriod: &metav1.Duration{Duration: MaxContainerBackOff}, + }, }, }, { @@ -372,7 +374,9 @@ func TestSetDefaultsKubeletConfiguration(t *testing.T) { LocalStorageCapacityIsolation: ptr.To(false), PodLogsDir: DefaultPodLogsDir, SingleProcessOOMKill: ptr.To(false), - CrashLoopBackOff: v1beta1.CrashLoopBackOffConfig{}, + CrashLoopBackOff: v1beta1.CrashLoopBackOffConfig{ + MaxContainerRestartPeriod: &metav1.Duration{Duration: MaxContainerBackOff}, + }, }, }, { @@ -785,7 +789,9 @@ func TestSetDefaultsKubeletConfiguration(t *testing.T) { LocalStorageCapacityIsolation: ptr.To(true), PodLogsDir: DefaultPodLogsDir, SingleProcessOOMKill: nil, - CrashLoopBackOff: v1beta1.CrashLoopBackOffConfig{}, + CrashLoopBackOff: v1beta1.CrashLoopBackOffConfig{ + MaxContainerRestartPeriod: &metav1.Duration{Duration: MaxContainerBackOff}, + }, }, }, { @@ -881,7 +887,9 @@ func TestSetDefaultsKubeletConfiguration(t *testing.T) { LocalStorageCapacityIsolation: ptr.To(true), PodLogsDir: DefaultPodLogsDir, SingleProcessOOMKill: nil, - CrashLoopBackOff: v1beta1.CrashLoopBackOffConfig{}, + CrashLoopBackOff: v1beta1.CrashLoopBackOffConfig{ + MaxContainerRestartPeriod: &metav1.Duration{Duration: MaxContainerBackOff}, + }, }, }, { @@ -976,16 +984,18 @@ func TestSetDefaultsKubeletConfiguration(t *testing.T) { RegisterNode: ptr.To(true), LocalStorageCapacityIsolation: ptr.To(true), PodLogsDir: DefaultPodLogsDir, - CrashLoopBackOff: v1beta1.CrashLoopBackOffConfig{}, + CrashLoopBackOff: v1beta1.CrashLoopBackOffConfig{ + MaxContainerRestartPeriod: &metav1.Duration{Duration: MaxContainerBackOff}, + }, }, }, { - "CrashLoopBackOff.MaxContainerRestartPeriod defaults to internal default when feature gate enabled", + "CrashLoopBackOff defaults empty when feature gate disabled", &v1beta1.KubeletConfiguration{ - FeatureGates: map[string]bool{"KubeletCrashLoopBackOffMax": true}, + FeatureGates: map[string]bool{"KubeletCrashLoopBackOffMax": false}, }, &v1beta1.KubeletConfiguration{ - FeatureGates: map[string]bool{"KubeletCrashLoopBackOffMax": true}, + FeatureGates: map[string]bool{"KubeletCrashLoopBackOffMax": false}, EnableServer: ptr.To(true), SyncFrequency: metav1.Duration{Duration: 1 * time.Minute}, FileCheckFrequency: metav1.Duration{Duration: 20 * time.Second}, @@ -1073,9 +1083,7 @@ func TestSetDefaultsKubeletConfiguration(t *testing.T) { LocalStorageCapacityIsolation: ptr.To(true), PodLogsDir: DefaultPodLogsDir, SingleProcessOOMKill: nil, - CrashLoopBackOff: v1beta1.CrashLoopBackOffConfig{ - MaxContainerRestartPeriod: &metav1.Duration{Duration: MaxContainerBackOff}, - }, + CrashLoopBackOff: v1beta1.CrashLoopBackOffConfig{}, }, }, } diff --git a/pkg/kubelet/kubelet_test.go b/pkg/kubelet/kubelet_test.go index 4fb0fc0a811..cbaa3d6be00 100644 --- a/pkg/kubelet/kubelet_test.go +++ b/pkg/kubelet/kubelet_test.go @@ -3264,6 +3264,9 @@ func TestNewMainKubeletStandAlone(t *testing.T) { ContainerLogMaxSize: "10Mi", ContainerLogMaxFiles: 5, MemoryThrottlingFactor: ptr.To[float64](0), + CrashLoopBackOff: kubeletconfiginternal.CrashLoopBackOffConfig{ + MaxContainerRestartPeriod: &metav1.Duration{Duration: 5 * time.Minute}, + }, } var prober volume.DynamicPluginProber tp := noopoteltrace.NewTracerProvider() @@ -3729,60 +3732,46 @@ func TestCrashLoopBackOffConfiguration(t *testing.T) { testCases := []struct { name string featureGates []featuregate.Feature - nodeDecay metav1.Duration + configuredMax metav1.Duration expectedInitial time.Duration expectedMax time.Duration }{ - { - name: "Prior behavior", - expectedMax: time.Duration(300 * time.Second), - expectedInitial: time.Duration(10 * time.Second), - }, - { - name: "New default only", - featureGates: []featuregate.Feature{features.ReduceDefaultCrashLoopBackOffDecay}, - expectedMax: time.Duration(60 * time.Second), - expectedInitial: time.Duration(1 * time.Second), - }, { name: "Faster per node config; only node config configured", - featureGates: []featuregate.Feature{features.KubeletCrashLoopBackOffMax}, - nodeDecay: metav1.Duration{Duration: 2 * time.Second}, + configuredMax: metav1.Duration{Duration: 2 * time.Second}, expectedMax: time.Duration(2 * time.Second), expectedInitial: time.Duration(2 * time.Second), }, { name: "Faster per node config; new default and node config configured", - featureGates: []featuregate.Feature{features.KubeletCrashLoopBackOffMax, features.ReduceDefaultCrashLoopBackOffDecay}, - nodeDecay: metav1.Duration{Duration: 2 * time.Second}, + featureGates: []featuregate.Feature{features.ReduceDefaultCrashLoopBackOffDecay}, + configuredMax: metav1.Duration{Duration: 2 * time.Second}, expectedMax: time.Duration(2 * time.Second), expectedInitial: time.Duration(1 * time.Second), }, { name: "Slower per node config; new default and node config configured, set A", - featureGates: []featuregate.Feature{features.KubeletCrashLoopBackOffMax, features.ReduceDefaultCrashLoopBackOffDecay}, - nodeDecay: metav1.Duration{Duration: 10 * time.Second}, + featureGates: []featuregate.Feature{features.ReduceDefaultCrashLoopBackOffDecay}, + configuredMax: metav1.Duration{Duration: 10 * time.Second}, expectedMax: time.Duration(10 * time.Second), expectedInitial: time.Duration(1 * time.Second), }, { name: "Slower per node config; new default and node config configured, set B", - featureGates: []featuregate.Feature{features.KubeletCrashLoopBackOffMax, features.ReduceDefaultCrashLoopBackOffDecay}, - nodeDecay: metav1.Duration{Duration: 300 * time.Second}, + featureGates: []featuregate.Feature{features.ReduceDefaultCrashLoopBackOffDecay}, + configuredMax: metav1.Duration{Duration: 300 * time.Second}, expectedMax: time.Duration(300 * time.Second), expectedInitial: time.Duration(1 * time.Second), }, { name: "Slower per node config; only node config configured, set A", - featureGates: []featuregate.Feature{features.KubeletCrashLoopBackOffMax}, - nodeDecay: metav1.Duration{Duration: 11 * time.Second}, + configuredMax: metav1.Duration{Duration: 11 * time.Second}, expectedMax: time.Duration(11 * time.Second), expectedInitial: time.Duration(10 * time.Second), }, { name: "Slower per node config; only node config configured, set B", - featureGates: []featuregate.Feature{features.KubeletCrashLoopBackOffMax}, - nodeDecay: metav1.Duration{Duration: 300 * time.Second}, + configuredMax: metav1.Duration{Duration: 300 * time.Second}, expectedMax: time.Duration(300 * time.Second), expectedInitial: time.Duration(10 * time.Second), }, @@ -3795,8 +3784,8 @@ func TestCrashLoopBackOffConfiguration(t *testing.T) { for _, f := range tc.featureGates { featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, f, true) } - if tc.nodeDecay.Duration > 0 { - kubeCfg.CrashLoopBackOff.MaxContainerRestartPeriod = &tc.nodeDecay + if tc.configuredMax.Duration > 0 { + kubeCfg.CrashLoopBackOff.MaxContainerRestartPeriod = &tc.configuredMax } resultMax, resultInitial := newCrashLoopBackOff(kubeCfg) diff --git a/test/compatibility_lifecycle/reference/versioned_feature_list.yaml b/test/compatibility_lifecycle/reference/versioned_feature_list.yaml index c361100ef21..e7369799c99 100644 --- a/test/compatibility_lifecycle/reference/versioned_feature_list.yaml +++ b/test/compatibility_lifecycle/reference/versioned_feature_list.yaml @@ -787,6 +787,10 @@ lockToDefault: false preRelease: Alpha version: "1.32" + - default: true + lockToDefault: false + preRelease: Beta + version: "1.35" - name: KubeletEnsureSecretPulledImages versionedSpecs: - default: false