diff --git a/cmd/kubelet/app/server.go b/cmd/kubelet/app/server.go index aaaa2b8ccf3..6d4bf492038 100644 --- a/cmd/kubelet/app/server.go +++ b/cmd/kubelet/app/server.go @@ -443,6 +443,12 @@ func loadConfigFile(name string) (*kubeletconfiginternal.KubeletConfiguration, e // See: https://github.com/kubernetes/kubernetes/pull/110263 if kc.EvictionHard == nil { kc.EvictionHard = eviction.DefaultEvictionHard + } else if kc.MergeDefaultEvictionSettings { + for k, v := range eviction.DefaultEvictionHard { + if _, exists := kc.EvictionHard[k]; !exists { + kc.EvictionHard[k] = v + } + } } return kc, err } diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index e6a393429aa..f7d0abc5d72 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -64977,6 +64977,13 @@ func schema_k8sio_kubelet_config_v1beta1_KubeletConfiguration(ref common.Referen }, }, }, + "mergeDefaultEvictionSettings": { + SchemaProps: spec.SchemaProps{ + Description: "mergeDefaultEvictionSettings indicates that defaults for the evictionHard, evictionSoft, evictionSoftGracePeriod, and evictionMinimumReclaim fields should be merged into values specified for those fields in this configuration. Signals specified in this configuration take precedence. Signals not specified in this configuration inherit their defaults. If false, and if any signal is specified in this configuration then other signals that are not specified in this configuration will be set to 0. It applies to merging the fields for which the default exists, and currently only evictionHard has default values. Default: false", + Type: []string{"boolean"}, + Format: "", + }, + }, "podsPerCore": { SchemaProps: spec.SchemaProps{ Description: "podsPerCore is the maximum number of pods per core. Cannot exceed maxPods. The value must be a non-negative integer. If 0, there is no limit on the number of Pods. Default: 0", diff --git a/pkg/kubelet/apis/config/fuzzer/fuzzer.go b/pkg/kubelet/apis/config/fuzzer/fuzzer.go index 474d6db2ef0..70d6d485c6c 100644 --- a/pkg/kubelet/apis/config/fuzzer/fuzzer.go +++ b/pkg/kubelet/apis/config/fuzzer/fuzzer.go @@ -98,6 +98,7 @@ func Funcs(codecs runtimeserializer.CodecFactory) []interface{} { obj.HairpinMode = v1beta1.PromiscuousBridge obj.EvictionHard = eviction.DefaultEvictionHard obj.EvictionPressureTransitionPeriod = metav1.Duration{Duration: 5 * time.Minute} + obj.MergeDefaultEvictionSettings = false obj.MakeIPTablesUtilChains = true obj.IPTablesMasqueradeBit = kubeletconfigv1beta1.DefaultIPTablesMasqueradeBit obj.IPTablesDropBit = kubeletconfigv1beta1.DefaultIPTablesDropBit diff --git a/pkg/kubelet/apis/config/helpers_test.go b/pkg/kubelet/apis/config/helpers_test.go index 3be9d8a392e..568b0be20df 100644 --- a/pkg/kubelet/apis/config/helpers_test.go +++ b/pkg/kubelet/apis/config/helpers_test.go @@ -258,6 +258,7 @@ var ( "MaxPods", "MemoryManagerPolicy", "MemorySwap.SwapBehavior", + "MergeDefaultEvictionSettings", "NodeLeaseDurationSeconds", "NodeStatusMaxImages", "NodeStatusUpdateFrequency.Duration", 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 09b9e4ff839..1acdd87f50f 100644 --- a/pkg/kubelet/apis/config/scheme/testdata/KubeletConfiguration/after/v1beta1.yaml +++ b/pkg/kubelet/apis/config/scheme/testdata/KubeletConfiguration/after/v1beta1.yaml @@ -70,6 +70,7 @@ maxPods: 110 memoryManagerPolicy: None memorySwap: {} memoryThrottlingFactor: 0.9 +mergeDefaultEvictionSettings: false nodeLeaseDurationSeconds: 40 nodeStatusMaxImages: 50 nodeStatusReportFrequency: 5m0s 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 99ff9671f8b..33c9777a94a 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 @@ -70,6 +70,7 @@ maxPods: 110 memoryManagerPolicy: None memorySwap: {} memoryThrottlingFactor: 0.9 +mergeDefaultEvictionSettings: false nodeLeaseDurationSeconds: 40 nodeStatusMaxImages: 50 nodeStatusReportFrequency: 5m0s diff --git a/pkg/kubelet/apis/config/types.go b/pkg/kubelet/apis/config/types.go index 132cc3f1094..caf4472af3b 100644 --- a/pkg/kubelet/apis/config/types.go +++ b/pkg/kubelet/apis/config/types.go @@ -322,6 +322,14 @@ type KubeletConfiguration struct { // amount of a given resource the kubelet will reclaim when performing a pod eviction while // that resource is under pressure. For example: {"imagefs.available": "2Gi"} EvictionMinimumReclaim map[string]string + // mergeDefaultEvictionSettings indicates that defaults for the evictionHard, evictionSoft, evictionSoftGracePeriod, and evictionMinimumReclaim + // fields should be merged into values specified for those fields in this configuration. + // Signals specified in this configuration take precedence. + // Signals not specified in this configuration inherit their defaults. + // If false, and if any signal is specified in this configuration then other signals that + // are not specified in this configuration will be set to 0. + // It applies to merging the fields for which the default exists, and currently only evictionHard has default values. + MergeDefaultEvictionSettings bool // podsPerCore is the maximum number of pods per core. Cannot exceed MaxPods. // If 0, this field is ignored. PodsPerCore int32 diff --git a/pkg/kubelet/apis/config/v1beta1/defaults.go b/pkg/kubelet/apis/config/v1beta1/defaults.go index 960b1489d30..6a7ea7fd468 100644 --- a/pkg/kubelet/apis/config/v1beta1/defaults.go +++ b/pkg/kubelet/apis/config/v1beta1/defaults.go @@ -236,6 +236,9 @@ func SetDefaults_KubeletConfiguration(obj *kubeletconfigv1beta1.KubeletConfigura if obj.EvictionPressureTransitionPeriod == zeroDuration { obj.EvictionPressureTransitionPeriod = metav1.Duration{Duration: 5 * time.Minute} } + if obj.MergeDefaultEvictionSettings == nil { + obj.MergeDefaultEvictionSettings = ptr.To(false) + } if obj.EnableControllerAttachDetach == nil { obj.EnableControllerAttachDetach = ptr.To(true) } diff --git a/pkg/kubelet/apis/config/v1beta1/defaults_test.go b/pkg/kubelet/apis/config/v1beta1/defaults_test.go index c33c5c730ef..391bdbe0b9d 100644 --- a/pkg/kubelet/apis/config/v1beta1/defaults_test.go +++ b/pkg/kubelet/apis/config/v1beta1/defaults_test.go @@ -104,6 +104,7 @@ func TestSetDefaultsKubeletConfiguration(t *testing.T) { MaxParallelImagePulls: nil, EvictionHard: nil, EvictionPressureTransitionPeriod: metav1.Duration{Duration: 5 * time.Minute}, + MergeDefaultEvictionSettings: ptr.To(false), EnableControllerAttachDetach: ptr.To(true), MakeIPTablesUtilChains: ptr.To(true), IPTablesMasqueradeBit: ptr.To[int32](DefaultIPTablesMasqueradeBit), @@ -221,6 +222,7 @@ func TestSetDefaultsKubeletConfiguration(t *testing.T) { EvictionPressureTransitionPeriod: zeroDuration, EvictionMaxPodGracePeriod: 0, EvictionMinimumReclaim: map[string]string{}, + MergeDefaultEvictionSettings: ptr.To(false), PodsPerCore: 0, EnableControllerAttachDetach: ptr.To(false), ProtectKernelDefaults: false, @@ -334,6 +336,7 @@ func TestSetDefaultsKubeletConfiguration(t *testing.T) { EvictionSoftGracePeriod: map[string]string{}, EvictionPressureTransitionPeriod: metav1.Duration{Duration: 5 * time.Minute}, EvictionMinimumReclaim: map[string]string{}, + MergeDefaultEvictionSettings: ptr.To(false), EnableControllerAttachDetach: ptr.To(false), MakeIPTablesUtilChains: ptr.To(false), IPTablesMasqueradeBit: ptr.To[int32](0), @@ -472,6 +475,7 @@ func TestSetDefaultsKubeletConfiguration(t *testing.T) { EvictionMinimumReclaim: map[string]string{ "imagefs.available": "1Gi", }, + MergeDefaultEvictionSettings: ptr.To(true), PodsPerCore: 1, EnableControllerAttachDetach: ptr.To(true), ProtectKernelDefaults: true, @@ -630,6 +634,7 @@ func TestSetDefaultsKubeletConfiguration(t *testing.T) { PodsPerCore: 1, EnableControllerAttachDetach: ptr.To(true), ProtectKernelDefaults: true, + MergeDefaultEvictionSettings: ptr.To(true), MakeIPTablesUtilChains: ptr.To(true), IPTablesMasqueradeBit: ptr.To[int32](1), IPTablesDropBit: ptr.To[int32](1), @@ -748,6 +753,7 @@ func TestSetDefaultsKubeletConfiguration(t *testing.T) { MaxParallelImagePulls: nil, EvictionHard: nil, EvictionPressureTransitionPeriod: metav1.Duration{Duration: 5 * time.Minute}, + MergeDefaultEvictionSettings: ptr.To(false), EnableControllerAttachDetach: ptr.To(true), MakeIPTablesUtilChains: ptr.To(true), IPTablesMasqueradeBit: ptr.To[int32](DefaultIPTablesMasqueradeBit), @@ -843,6 +849,7 @@ func TestSetDefaultsKubeletConfiguration(t *testing.T) { MaxParallelImagePulls: ptr.To[int32](5), EvictionHard: nil, EvictionPressureTransitionPeriod: metav1.Duration{Duration: 5 * time.Minute}, + MergeDefaultEvictionSettings: ptr.To(false), EnableControllerAttachDetach: ptr.To(true), MakeIPTablesUtilChains: ptr.To(true), IPTablesMasqueradeBit: ptr.To[int32](DefaultIPTablesMasqueradeBit), @@ -938,6 +945,7 @@ func TestSetDefaultsKubeletConfiguration(t *testing.T) { MaxParallelImagePulls: ptr.To[int32](1), EvictionHard: nil, EvictionPressureTransitionPeriod: metav1.Duration{Duration: 5 * time.Minute}, + MergeDefaultEvictionSettings: ptr.To(false), EnableControllerAttachDetach: ptr.To(true), MakeIPTablesUtilChains: ptr.To(true), IPTablesMasqueradeBit: ptr.To[int32](DefaultIPTablesMasqueradeBit), @@ -1033,6 +1041,7 @@ func TestSetDefaultsKubeletConfiguration(t *testing.T) { MaxParallelImagePulls: nil, EvictionHard: nil, EvictionPressureTransitionPeriod: metav1.Duration{Duration: 5 * time.Minute}, + MergeDefaultEvictionSettings: ptr.To(false), EnableControllerAttachDetach: ptr.To(true), MakeIPTablesUtilChains: ptr.To(true), IPTablesMasqueradeBit: ptr.To[int32](DefaultIPTablesMasqueradeBit), diff --git a/pkg/kubelet/apis/config/v1beta1/zz_generated.conversion.go b/pkg/kubelet/apis/config/v1beta1/zz_generated.conversion.go index 347a3d54dec..6c0bffa63a3 100644 --- a/pkg/kubelet/apis/config/v1beta1/zz_generated.conversion.go +++ b/pkg/kubelet/apis/config/v1beta1/zz_generated.conversion.go @@ -483,6 +483,9 @@ func autoConvert_v1beta1_KubeletConfiguration_To_config_KubeletConfiguration(in out.EvictionPressureTransitionPeriod = in.EvictionPressureTransitionPeriod out.EvictionMaxPodGracePeriod = in.EvictionMaxPodGracePeriod out.EvictionMinimumReclaim = *(*map[string]string)(unsafe.Pointer(&in.EvictionMinimumReclaim)) + if err := v1.Convert_Pointer_bool_To_bool(&in.MergeDefaultEvictionSettings, &out.MergeDefaultEvictionSettings, s); err != nil { + return err + } out.PodsPerCore = in.PodsPerCore if err := v1.Convert_Pointer_bool_To_bool(&in.EnableControllerAttachDetach, &out.EnableControllerAttachDetach, s); err != nil { return err @@ -685,6 +688,9 @@ func autoConvert_config_KubeletConfiguration_To_v1beta1_KubeletConfiguration(in out.EvictionPressureTransitionPeriod = in.EvictionPressureTransitionPeriod out.EvictionMaxPodGracePeriod = in.EvictionMaxPodGracePeriod out.EvictionMinimumReclaim = *(*map[string]string)(unsafe.Pointer(&in.EvictionMinimumReclaim)) + if err := v1.Convert_bool_To_Pointer_bool(&in.MergeDefaultEvictionSettings, &out.MergeDefaultEvictionSettings, s); err != nil { + return err + } out.PodsPerCore = in.PodsPerCore if err := v1.Convert_bool_To_Pointer_bool(&in.EnableControllerAttachDetach, &out.EnableControllerAttachDetach, s); err != nil { return err diff --git a/staging/src/k8s.io/kubelet/config/v1beta1/types.go b/staging/src/k8s.io/kubelet/config/v1beta1/types.go index ce2d3121373..edbee00b45f 100644 --- a/staging/src/k8s.io/kubelet/config/v1beta1/types.go +++ b/staging/src/k8s.io/kubelet/config/v1beta1/types.go @@ -547,6 +547,16 @@ type KubeletConfiguration struct { // Default: nil // +optional EvictionMinimumReclaim map[string]string `json:"evictionMinimumReclaim,omitempty"` + // mergeDefaultEvictionSettings indicates that defaults for the evictionHard, evictionSoft, evictionSoftGracePeriod, and evictionMinimumReclaim + // fields should be merged into values specified for those fields in this configuration. + // Signals specified in this configuration take precedence. + // Signals not specified in this configuration inherit their defaults. + // If false, and if any signal is specified in this configuration then other signals that + // are not specified in this configuration will be set to 0. + // It applies to merging the fields for which the default exists, and currently only evictionHard has default values. + // Default: false + // +optional + MergeDefaultEvictionSettings *bool `json:"mergeDefaultEvictionSettings,omitempty"` // podsPerCore is the maximum number of pods per core. Cannot exceed maxPods. // The value must be a non-negative integer. // If 0, there is no limit on the number of Pods. diff --git a/staging/src/k8s.io/kubelet/config/v1beta1/zz_generated.deepcopy.go b/staging/src/k8s.io/kubelet/config/v1beta1/zz_generated.deepcopy.go index 89dda0dfa17..87d56899c81 100644 --- a/staging/src/k8s.io/kubelet/config/v1beta1/zz_generated.deepcopy.go +++ b/staging/src/k8s.io/kubelet/config/v1beta1/zz_generated.deepcopy.go @@ -372,6 +372,11 @@ func (in *KubeletConfiguration) DeepCopyInto(out *KubeletConfiguration) { (*out)[key] = val } } + if in.MergeDefaultEvictionSettings != nil { + in, out := &in.MergeDefaultEvictionSettings, &out.MergeDefaultEvictionSettings + *out = new(bool) + **out = **in + } if in.EnableControllerAttachDetach != nil { in, out := &in.EnableControllerAttachDetach, &out.EnableControllerAttachDetach *out = new(bool)