diff --git a/cmd/descheduler/app/options/options.go b/cmd/descheduler/app/options/options.go index 254d2720d..3821f64c3 100644 --- a/cmd/descheduler/app/options/options.go +++ b/cmd/descheduler/app/options/options.go @@ -18,6 +18,7 @@ limitations under the License. package options import ( + "strings" "time" "github.com/spf13/pflag" @@ -25,14 +26,18 @@ import ( apiserver "k8s.io/apiserver/pkg/server" apiserveroptions "k8s.io/apiserver/pkg/server/options" clientset "k8s.io/client-go/kubernetes" + restclient "k8s.io/client-go/rest" + cliflag "k8s.io/component-base/cli/flag" componentbaseconfig "k8s.io/component-base/config" componentbaseoptions "k8s.io/component-base/config/options" + "k8s.io/component-base/featuregate" "k8s.io/klog/v2" "sigs.k8s.io/descheduler/pkg/apis/componentconfig" "sigs.k8s.io/descheduler/pkg/apis/componentconfig/v1alpha1" deschedulerscheme "sigs.k8s.io/descheduler/pkg/descheduler/scheme" + "sigs.k8s.io/descheduler/pkg/features" "sigs.k8s.io/descheduler/pkg/tracing" ) @@ -50,6 +55,10 @@ type DeschedulerServer struct { SecureServingInfo *apiserver.SecureServingInfo DisableMetrics bool EnableHTTP2 bool + // FeatureGates enabled by the user + FeatureGates map[string]bool + // DefaultFeatureGates for internal accessing so unit tests can enable/disable specific features + DefaultFeatureGates featuregate.FeatureGate } // NewDeschedulerServer creates a new DeschedulerServer with default parameters @@ -107,6 +116,8 @@ func (rs *DeschedulerServer) AddFlags(fs *pflag.FlagSet) { fs.Float64Var(&rs.Tracing.SampleRate, "otel-sample-rate", 1.0, "Sample rate to collect the Traces") fs.BoolVar(&rs.Tracing.FallbackToNoOpProviderOnError, "otel-fallback-no-op-on-error", false, "Fallback to NoOp Tracer in case of error") fs.BoolVar(&rs.EnableHTTP2, "enable-http2", false, "If http/2 should be enabled for the metrics and health check") + fs.Var(cliflag.NewMapStringBool(&rs.FeatureGates), "feature-gates", "A set of key=value pairs that describe feature gates for alpha/experimental features. "+ + "Options are:\n"+strings.Join(features.DefaultMutableFeatureGate.KnownFeatures(), "\n")) componentbaseoptions.BindLeaderElectionFlags(&rs.LeaderElection, fs) @@ -114,6 +125,12 @@ func (rs *DeschedulerServer) AddFlags(fs *pflag.FlagSet) { } func (rs *DeschedulerServer) Apply() error { + err := features.DefaultMutableFeatureGate.SetFromMap(rs.FeatureGates) + if err != nil { + return err + } + rs.DefaultFeatureGates = features.DefaultMutableFeatureGate + // loopbackClientConfig is a config for a privileged loopback connection var loopbackClientConfig *restclient.Config var secureServing *apiserver.SecureServingInfo diff --git a/cmd/descheduler/app/server.go b/cmd/descheduler/app/server.go index 2bcb0e326..8b18d2f11 100644 --- a/cmd/descheduler/app/server.go +++ b/cmd/descheduler/app/server.go @@ -23,16 +23,15 @@ import ( "os/signal" "syscall" - "k8s.io/apiserver/pkg/server/healthz" + "github.com/spf13/cobra" "sigs.k8s.io/descheduler/cmd/descheduler/app/options" "sigs.k8s.io/descheduler/pkg/descheduler" "sigs.k8s.io/descheduler/pkg/tracing" - "github.com/spf13/cobra" - "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/watch" + "k8s.io/apiserver/pkg/server/healthz" "k8s.io/apiserver/pkg/server/mux" "k8s.io/component-base/featuregate" "k8s.io/component-base/logs" diff --git a/docs/cli/descheduler.md b/docs/cli/descheduler.md index 7b79b5af5..71257e918 100644 --- a/docs/cli/descheduler.md +++ b/docs/cli/descheduler.md @@ -23,6 +23,10 @@ descheduler [flags] --disable-metrics Disables metrics. The metrics are by default served through https://localhost:10258/metrics. Secure address, resp. port can be changed through --bind-address, resp. --secure-port flags. --dry-run Execute descheduler in dry run mode. --enable-http2 If http/2 should be enabled for the metrics and health check + --feature-gates mapStringBool A set of key=value pairs that describe feature gates for alpha/experimental features. Options are: + AllAlpha=true|false (ALPHA - default=false) + AllBeta=true|false (BETA - default=false) + EvictionsInBackground=true|false (ALPHA - default=false) -h, --help help for descheduler --http2-max-streams-per-connection int The limit that the server gives to clients for the maximum number of streams in an HTTP/2 connection. Zero means to use golang's default. --kubeconfig string File with kube configuration. Deprecated, use client-connection-kubeconfig instead. diff --git a/pkg/features/features.go b/pkg/features/features.go new file mode 100644 index 000000000..fe504f022 --- /dev/null +++ b/pkg/features/features.go @@ -0,0 +1,49 @@ +package features + +import ( + "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/component-base/featuregate" +) + +const ( + // Every feature gate should add method here following this template: + // + // // owner: @username + // // kep: kep link + // // alpha: v1.X + // MyFeature featuregate.Feature = "MyFeature" + // + // Feature gates should be listed in alphabetical, case-sensitive + // (upper before any lower case character) order. This reduces the risk + // of code conflicts because changes are more likely to be scattered + // across the file. + + // owner: @ingvagabund + // kep: https://github.com/kubernetes-sigs/descheduler/issues/1397 + // alpha: v1.31 + // + // Enable evictions in background so users can create their own eviction policies + // as an alternative to immediate evictions. + EvictionsInBackground featuregate.Feature = "EvictionsInBackground" +) + +func init() { + runtime.Must(DefaultMutableFeatureGate.Add(defaultDeschedulerFeatureGates)) +} + +// defaultDeschedulerFeatureGates consists of all known descheduler-specific feature keys. +// To add a new feature, define a key for it above and add it here. The features will be +// available throughout descheduler binary. +// +// Entries are separated from each other with blank lines to avoid sweeping gofmt changes +// when adding or removing one entry. +var defaultDeschedulerFeatureGates = map[featuregate.Feature]featuregate.FeatureSpec{ + EvictionsInBackground: {Default: false, PreRelease: featuregate.Alpha}, +} + +// DefaultMutableFeatureGate is a mutable version of DefaultFeatureGate. +// Only top-level commands/options setup and the k8s.io/component-base/featuregate/testing package should make use of this. +// Tests that need to modify feature gates for the duration of their test should use: +// +// defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features., )() +var DefaultMutableFeatureGate featuregate.MutableFeatureGate = featuregate.NewFeatureGate()