From a49760bfcec5cd1a59327ab1c412ecfe52f50ed0 Mon Sep 17 00:00:00 2001 From: Karan Goel Date: Thu, 10 Sep 2020 09:34:16 -0700 Subject: [PATCH] Non-zero cfs quota period duration requires feature flag --- pkg/kubelet/apis/config/validation/BUILD | 1 + .../apis/config/validation/validation.go | 8 ++++++++ .../apis/config/validation/validation_test.go | 17 +++++++++++++---- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/pkg/kubelet/apis/config/validation/BUILD b/pkg/kubelet/apis/config/validation/BUILD index 447b9d3b1a5..25ad727a0a0 100644 --- a/pkg/kubelet/apis/config/validation/BUILD +++ b/pkg/kubelet/apis/config/validation/BUILD @@ -19,6 +19,7 @@ go_library( "//pkg/kubelet/apis/config:go_default_library", "//pkg/kubelet/cm/cpuset:go_default_library", "//pkg/kubelet/types:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/errors:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/validation:go_default_library", "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", diff --git a/pkg/kubelet/apis/config/validation/validation.go b/pkg/kubelet/apis/config/validation/validation.go index 9afa64205e0..c42885d970b 100644 --- a/pkg/kubelet/apis/config/validation/validation.go +++ b/pkg/kubelet/apis/config/validation/validation.go @@ -20,6 +20,7 @@ import ( "fmt" "time" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" utilerrors "k8s.io/apimachinery/pkg/util/errors" utilvalidation "k8s.io/apimachinery/pkg/util/validation" utilfeature "k8s.io/apiserver/pkg/util/feature" @@ -31,6 +32,10 @@ import ( kubetypes "k8s.io/kubernetes/pkg/kubelet/types" ) +var ( + defaultCFSQuota = metav1.Duration{Duration: 100 * time.Millisecond} +) + // ValidateKubeletConfiguration validates `kc` and returns an error if it is invalid func ValidateKubeletConfiguration(kc *kubeletconfig.KubeletConfiguration) error { allErrors := []error{} @@ -60,6 +65,9 @@ func ValidateKubeletConfiguration(kc *kubeletconfig.KubeletConfiguration) error if kc.HealthzPort != 0 && utilvalidation.IsValidPortNum(int(kc.HealthzPort)) != nil { allErrors = append(allErrors, fmt.Errorf("invalid configuration: HealthzPort (--healthz-port) %v must be between 1 and 65535, inclusive", kc.HealthzPort)) } + if !localFeatureGate.Enabled(features.CPUCFSQuotaPeriod) && kc.CPUCFSQuotaPeriod != defaultCFSQuota { + allErrors = append(allErrors, fmt.Errorf("invalid configuration: CPUCFSQuotaPeriod %v requires feature gate CustomCPUCFSQuotaPeriod", kc.CPUCFSQuotaPeriod)) + } if localFeatureGate.Enabled(features.CPUCFSQuotaPeriod) && utilvalidation.IsInRange(int(kc.CPUCFSQuotaPeriod.Duration), int(1*time.Microsecond), int(time.Second)) != nil { allErrors = append(allErrors, fmt.Errorf("invalid configuration: CPUCFSQuotaPeriod (--cpu-cfs-quota-period) %v must be between 1usec and 1sec, inclusive", kc.CPUCFSQuotaPeriod)) } diff --git a/pkg/kubelet/apis/config/validation/validation_test.go b/pkg/kubelet/apis/config/validation/validation_test.go index 00ed0aaf268..31ab03b7015 100644 --- a/pkg/kubelet/apis/config/validation/validation_test.go +++ b/pkg/kubelet/apis/config/validation/validation_test.go @@ -52,7 +52,10 @@ func TestValidateKubeletConfiguration(t *testing.T) { RegistryPullQPS: 5, HairpinMode: kubeletconfig.PromiscuousBridge, NodeLeaseDurationSeconds: 1, - CPUCFSQuotaPeriod: metav1.Duration{Duration: 100 * time.Millisecond}, + CPUCFSQuotaPeriod: metav1.Duration{Duration: 25 * time.Millisecond}, + FeatureGates: map[string]bool{ + "CustomCPUCFSQuotaPeriod": true, + }, } if allErrors := ValidateKubeletConfiguration(successCase1); allErrors != nil { t.Errorf("expect no errors, got %v", allErrors) @@ -84,8 +87,11 @@ func TestValidateKubeletConfiguration(t *testing.T) { RegistryPullQPS: 5, HairpinMode: kubeletconfig.PromiscuousBridge, NodeLeaseDurationSeconds: 1, - CPUCFSQuotaPeriod: metav1.Duration{Duration: 100 * time.Millisecond}, + CPUCFSQuotaPeriod: metav1.Duration{Duration: 50 * time.Millisecond}, ReservedSystemCPUs: "0-3", + FeatureGates: map[string]bool{ + "CustomCPUCFSQuotaPeriod": true, + }, } if allErrors := ValidateKubeletConfiguration(successCase2); allErrors != nil { t.Errorf("expect no errors, got %v", allErrors) @@ -115,7 +121,7 @@ func TestValidateKubeletConfiguration(t *testing.T) { RegistryPullQPS: -10, HairpinMode: "foo", NodeLeaseDurationSeconds: -1, - CPUCFSQuotaPeriod: metav1.Duration{Duration: 0}, + CPUCFSQuotaPeriod: metav1.Duration{Duration: 100 * time.Millisecond}, } const numErrsErrorCase1 = 25 if allErrors := ValidateKubeletConfiguration(errorCase1); len(allErrors.(utilerrors.Aggregate).Errors()) != numErrsErrorCase1 { @@ -148,8 +154,11 @@ func TestValidateKubeletConfiguration(t *testing.T) { RegistryPullQPS: 5, HairpinMode: kubeletconfig.PromiscuousBridge, NodeLeaseDurationSeconds: 1, - CPUCFSQuotaPeriod: metav1.Duration{Duration: 100 * time.Millisecond}, + CPUCFSQuotaPeriod: metav1.Duration{Duration: 50 * time.Millisecond}, ReservedSystemCPUs: "0-3", + FeatureGates: map[string]bool{ + "CustomCPUCFSQuotaPeriod": true, + }, } const numErrsErrorCase2 = 1 if allErrors := ValidateKubeletConfiguration(errorCase2); len(allErrors.(utilerrors.Aggregate).Errors()) != numErrsErrorCase2 {