diff --git a/cluster-autoscaler/main.go b/cluster-autoscaler/main.go index 948a10ec94c0..d09ef0d23eab 100644 --- a/cluster-autoscaler/main.go +++ b/cluster-autoscaler/main.go @@ -55,6 +55,7 @@ import ( "k8s.io/autoscaler/cluster-autoscaler/simulator/clustersnapshot" "k8s.io/autoscaler/cluster-autoscaler/utils/errors" kube_util "k8s.io/autoscaler/cluster-autoscaler/utils/kubernetes" + scheduler_util "k8s.io/autoscaler/cluster-autoscaler/utils/scheduler" "k8s.io/autoscaler/cluster-autoscaler/utils/units" "k8s.io/autoscaler/cluster-autoscaler/version" kube_client "k8s.io/client-go/kubernetes" @@ -67,9 +68,6 @@ import ( "k8s.io/component-base/config/options" "k8s.io/component-base/metrics/legacyregistry" "k8s.io/klog/v2" - schedconfig "k8s.io/kubernetes/pkg/scheduler/apis/config" - schedscheme "k8s.io/kubernetes/pkg/scheduler/apis/config/scheme" - schedvalidation "k8s.io/kubernetes/pkg/scheduler/apis/config/validation" ) // MultiStringFlag is a flag for passing multiple parameters using same flag @@ -256,7 +254,10 @@ func createAutoscalingOptions() config.AutoscalingOptions { klog.Fatalf("Invalid configuration, could not use --max-drain-parallelism > 1 if --parallel-drain is false") } - parsedSchedConfig := getSchedulerConfig(*schedulerConfig) + parsedSchedConfig, err := scheduler_util.GetSchedulerConfig(*schedulerConfig) + if err != nil { + klog.Fatalf("Failed to get scheduler config: %v", err) + } return config.AutoscalingOptions{ NodeGroupDefaults: config.NodeGroupAutoscalingOptions{ @@ -376,36 +377,6 @@ func getKubeConfig() *rest.Config { return kubeConfig } -func getSchedulerConfig(path string) *schedconfig.KubeSchedulerConfiguration { - data, err := os.ReadFile(path) - - defaultFallback := "(falling back to default scheduler config)" - - if err != nil { - klog.Errorf("couldn't load scheduler config %s: %v", defaultFallback, err) - return &schedconfig.KubeSchedulerConfiguration{} - } - - obj, gvk, err := schedscheme.Codecs.UniversalDecoder().Decode(data, nil, nil) - if err != nil { - klog.Errorf("couldn't decode scheduler config %s: %v", defaultFallback, err) - return &schedconfig.KubeSchedulerConfiguration{} - } - - cfgObj, ok := obj.(*schedconfig.KubeSchedulerConfiguration) - if !ok { - klog.Errorf("couldn't decode as KubeSchedulerConfiguration, got %s %s", defaultFallback, gvk) - return &schedconfig.KubeSchedulerConfiguration{} - } - - if err := schedvalidation.ValidateKubeSchedulerConfiguration(cfgObj); err != nil { - klog.Errorf("invalid KubeSchedulerConfiguration %s: %v", defaultFallback, err) - return &schedconfig.KubeSchedulerConfiguration{} - } - - return cfgObj -} - func createKubeClient(kubeConfig *rest.Config) kube_client.Interface { return kube_client.NewForConfigOrDie(kubeConfig) } diff --git a/cluster-autoscaler/utils/scheduler/scheduler.go b/cluster-autoscaler/utils/scheduler/scheduler.go index 1b9e61259e2d..efc340e81f68 100644 --- a/cluster-autoscaler/utils/scheduler/scheduler.go +++ b/cluster-autoscaler/utils/scheduler/scheduler.go @@ -18,11 +18,17 @@ package scheduler import ( "fmt" + "os" "strings" apiv1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/util/uuid" + "k8s.io/klog/v2" + schedconfig "k8s.io/kubernetes/pkg/scheduler/apis/config" + schedconfiglatest "k8s.io/kubernetes/pkg/scheduler/apis/config/latest" + schedscheme "k8s.io/kubernetes/pkg/scheduler/apis/config/scheme" + schedvalidation "k8s.io/kubernetes/pkg/scheduler/apis/config/validation" schedulerframework "k8s.io/kubernetes/pkg/scheduler/framework" ) @@ -106,3 +112,38 @@ func ResourceToResourceList(r *schedulerframework.Resource) apiv1.ResourceList { } return result } + +// GetSchedulerConfig loads scheduler config from a path +// (falls back to default config in case of error) +func GetSchedulerConfig(path string) (*schedconfig.KubeSchedulerConfiguration, error) { + defaultFallbackMsg := "(falling back to default scheduler config)" + defaultFallback, err := schedconfiglatest.Default() + if err != nil { + return nil, fmt.Errorf("couldn't create scheduler config: %v", err) + } + + data, err := os.ReadFile(path) + if err != nil { + klog.Errorf("couldn't load scheduler config %s: %v", defaultFallbackMsg, err) + return defaultFallback, nil + } + + obj, gvk, err := schedscheme.Codecs.UniversalDecoder().Decode(data, nil, nil) + if err != nil { + klog.Errorf("couldn't decode scheduler config %s: %v", defaultFallbackMsg, err) + return defaultFallback, nil + } + + cfgObj, ok := obj.(*schedconfig.KubeSchedulerConfiguration) + if !ok { + klog.Errorf("couldn't decode as KubeSchedulerConfiguration, got %s %s", defaultFallbackMsg, gvk) + return defaultFallback, nil + } + + if err := schedvalidation.ValidateKubeSchedulerConfiguration(cfgObj); err != nil { + klog.Errorf("invalid KubeSchedulerConfiguration %s: %v", defaultFallbackMsg, err) + return defaultFallback, nil + } + + return cfgObj, nil +}