diff --git a/pkg/kubelet/apis/config/validation/validation.go b/pkg/kubelet/apis/config/validation/validation.go index 7d9b452b4fd..dd46a477cfd 100644 --- a/pkg/kubelet/apis/config/validation/validation.go +++ b/pkg/kubelet/apis/config/validation/validation.go @@ -83,6 +83,15 @@ func ValidateKubeletConfiguration(kc *kubeletconfig.KubeletConfiguration, featur if kc.ImageGCLowThresholdPercent >= kc.ImageGCHighThresholdPercent { allErrors = append(allErrors, fmt.Errorf("invalid configuration: imageGCLowThresholdPercent (--image-gc-low-threshold) %v must be less than imageGCHighThresholdPercent (--image-gc-high-threshold) %v", kc.ImageGCLowThresholdPercent, kc.ImageGCHighThresholdPercent)) } + if kc.ImageMaximumGCAge.Duration != 0 && !localFeatureGate.Enabled(features.ImageMaximumGCAge) { + allErrors = append(allErrors, fmt.Errorf("invalid configuration: ImageMaximumGCAge feature gate is required for Kubelet configuration option ImageMaximumGCAge")) + } + if kc.ImageMaximumGCAge.Duration < 0 { + allErrors = append(allErrors, fmt.Errorf("invalid configuration: imageMaximumGCAge %v must not be negative", kc.ImageMaximumGCAge.Duration)) + } + if kc.ImageMaximumGCAge.Duration > 0 && kc.ImageMaximumGCAge.Duration <= kc.ImageMinimumGCAge.Duration { + allErrors = append(allErrors, fmt.Errorf("invalid configuration: imageMaximumGCAge %v must be greater than imageMinimumGCAge %v", kc.ImageMaximumGCAge.Duration, kc.ImageMinimumGCAge.Duration)) + } if utilvalidation.IsInRange(int(kc.IPTablesDropBit), 0, 31) != nil { allErrors = append(allErrors, fmt.Errorf("invalid configuration: iptablesDropBit (--iptables-drop-bit) %v must be between 0 and 31, inclusive", kc.IPTablesDropBit)) } diff --git a/pkg/kubelet/apis/config/validation/validation_test.go b/pkg/kubelet/apis/config/validation/validation_test.go index 776a7597372..913c5dc3bdf 100644 --- a/pkg/kubelet/apis/config/validation/validation_test.go +++ b/pkg/kubelet/apis/config/validation/validation_test.go @@ -521,6 +521,30 @@ func TestValidateKubeletConfiguration(t *testing.T) { return conf }, errMsg: "invalid configuration: enableSystemLogHandler is required for enableSystemLogQuery", + }, { + name: "imageMaximumGCAge should not be specified without feature gate", + configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration { + conf.ImageMaximumGCAge = metav1.Duration{Duration: 1} + return conf + }, + errMsg: "invalid configuration: ImageMaximumGCAge feature gate is required for Kubelet configuration option ImageMaximumGCAge", + }, { + name: "imageMaximumGCAge should not be negative", + configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration { + conf.FeatureGates = map[string]bool{"ImageMaximumGCAge": true} + conf.ImageMaximumGCAge = metav1.Duration{Duration: -1} + return conf + }, + errMsg: "invalid configuration: imageMaximumGCAge -1ns must not be negative", + }, { + name: "imageMaximumGCAge should not be less than imageMinimumGCAge", + configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration { + conf.FeatureGates = map[string]bool{"ImageMaximumGCAge": true} + conf.ImageMaximumGCAge = metav1.Duration{Duration: 1} + conf.ImageMinimumGCAge = metav1.Duration{Duration: 2} + return conf + }, + errMsg: "invalid configuration: imageMaximumGCAge 1ns must be greater than imageMinimumGCAge 2ns", }} for _, tc := range cases {