-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: support custom scheduler config (without extenders) #5708
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,6 +19,10 @@ package config | |
import "time" | ||
|
||
const ( | ||
// SchedulerConfigFileFlag is the name of the flag | ||
// for passing in custom scheduler config for in-tree scheduelr plugins | ||
SchedulerConfigFileFlag = "scheduler-config-file" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the reason for putting this here instead of inline with the existing flags? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So that it is easier to refer again here. |
||
|
||
// DefaultMaxClusterCores is the default maximum number of cores in the cluster. | ||
DefaultMaxClusterCores = 5000 * 64 | ||
// DefaultMaxClusterMemory is the default maximum number of gigabytes of memory in cluster. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
/* | ||
Copyright 2023 The Kubernetes Authors. | ||
|
||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
|
||
http://www.apache.org/licenses/LICENSE-2.0 | ||
|
||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package test | ||
|
||
const ( | ||
// Custom scheduler configs for testing | ||
|
||
// SchedulerConfigNodeResourcesFitDisabled is scheduler config | ||
// with `NodeResourcesFit` plugin disabled | ||
SchedulerConfigNodeResourcesFitDisabled = ` | ||
apiVersion: kubescheduler.config.k8s.io/v1 | ||
kind: KubeSchedulerConfiguration | ||
profiles: | ||
- pluginConfig: | ||
plugins: | ||
multiPoint: | ||
disabled: | ||
- name: NodeResourcesFit | ||
weight: 1 | ||
schedulerName: custom-scheduler` | ||
|
||
// SchedulerConfigTaintTolerationDisabled is scheduler config | ||
// with `TaintToleration` plugin disabled | ||
SchedulerConfigTaintTolerationDisabled = ` | ||
apiVersion: kubescheduler.config.k8s.io/v1 | ||
kind: KubeSchedulerConfiguration | ||
profiles: | ||
- pluginConfig: | ||
plugins: | ||
multiPoint: | ||
disabled: | ||
- name: TaintToleration | ||
weight: 1 | ||
schedulerName: custom-scheduler` | ||
|
||
// SchedulerConfigMinimalCorrect is the minimal | ||
// correct scheduler config | ||
SchedulerConfigMinimalCorrect = ` | ||
apiVersion: kubescheduler.config.k8s.io/v1 | ||
kind: KubeSchedulerConfiguration` | ||
|
||
// SchedulerConfigDecodeErr is the scheduler config | ||
// which throws decoding error when we try to load it | ||
SchedulerConfigDecodeErr = ` | ||
kind: KubeSchedulerConfiguration` | ||
|
||
// SchedulerConfigInvalid is invalid scheduler config | ||
// because we specify percentageOfNodesToScore > 100 | ||
SchedulerConfigInvalid = ` | ||
apiVersion: kubescheduler.config.k8s.io/v1 | ||
kind: KubeSchedulerConfiguration | ||
# percentageOfNodesToScore has to be between 0 and 100 | ||
percentageOfNodesToScore: 130` | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -56,6 +56,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" | ||
|
@@ -68,6 +69,7 @@ import ( | |
"k8s.io/component-base/config/options" | ||
"k8s.io/component-base/metrics/legacyregistry" | ||
"k8s.io/klog/v2" | ||
scheduler_config "k8s.io/kubernetes/pkg/scheduler/apis/config" | ||
) | ||
|
||
// MultiStringFlag is a flag for passing multiple parameters using same flag | ||
|
@@ -133,6 +135,7 @@ var ( | |
"for scale down when some candidates from previous iteration are no longer valid."+ | ||
"When calculating the pool size for additional candidates we take"+ | ||
"max(#nodes * scale-down-candidates-pool-ratio, scale-down-candidates-pool-min-count).") | ||
schedulerConfigFile = flag.String(config.SchedulerConfigFileFlag, "", "scheduler-config allows changing configuration of in-tree scheduler plugins acting on PreFilter and Filter extension points") | ||
nodeDeletionDelayTimeout = flag.Duration("node-deletion-delay-timeout", 2*time.Minute, "Maximum time CA waits for removing delay-deletion.cluster-autoscaler.kubernetes.io/ annotations before deleting the node.") | ||
nodeDeletionBatcherInterval = flag.Duration("node-deletion-batcher-interval", 0*time.Second, "How long CA ScaleDown gather nodes to delete them in batch.") | ||
scanInterval = flag.Duration("scan-interval", 10*time.Second, "How often cluster is reevaluated for scale up or down") | ||
|
@@ -274,6 +277,15 @@ func createAutoscalingOptions() config.AutoscalingOptions { | |
*maxEmptyBulkDeleteFlag = *maxScaleDownParallelismFlag | ||
} | ||
|
||
var parsedSchedConfig *scheduler_config.KubeSchedulerConfiguration | ||
// if scheduler config flag was set by the user | ||
if pflag.CommandLine.Changed(config.SchedulerConfigFileFlag) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is so that if the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is it better than just comparing with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think there are two lines of thought here:
Falling back to default in case of 2 doesn't seem as valuable to me because if the user wants to use the default config, they can just skip the flag altogether because the flag specifies path to a config file (and not scheduler config itself) and if they have set it to A counter-argument could be, if the user sets only one or two fields in the custom scheduler config we anyway fill rest of the required fields by default (in this PR). It can be argued that 2 is inline with this behavior. I think failing here makes more sense than using default config but I am open to change it if you think there's a strong reason for not doing so. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was thinking about someone templating the manifest and using empty string to mean "default", but I guess such templating can also just skip the flag in such cases, so maybe it is fine to just leave as is. |
||
parsedSchedConfig, err = scheduler_util.ConfigFromPath(*schedulerConfigFile) | ||
} | ||
if err != nil { | ||
klog.Fatalf("Failed to get scheduler config: %v", err) | ||
} | ||
|
||
return config.AutoscalingOptions{ | ||
NodeGroupDefaults: config.NodeGroupAutoscalingOptions{ | ||
ScaleDownUtilizationThreshold: *scaleDownUtilizationThreshold, | ||
|
@@ -316,6 +328,7 @@ func createAutoscalingOptions() config.AutoscalingOptions { | |
ScaleDownNonEmptyCandidatesCount: *scaleDownNonEmptyCandidatesCount, | ||
ScaleDownCandidatesPoolRatio: *scaleDownCandidatesPoolRatio, | ||
ScaleDownCandidatesPoolMinCount: *scaleDownCandidatesPoolMinCount, | ||
SchedulerConfig: parsedSchedConfig, | ||
WriteStatusConfigMap: *writeStatusConfigMapFlag, | ||
StatusConfigMapName: *statusConfigMapName, | ||
BalanceSimilarNodeGroups: *balanceSimilarNodeGroupsFlag, | ||
|
@@ -422,7 +435,8 @@ func buildAutoscaler(debuggingSnapshotter debuggingsnapshot.DebuggingSnapshotter | |
|
||
eventsKubeClient := createKubeClient(getKubeConfig()) | ||
|
||
predicateChecker, err := predicatechecker.NewSchedulerBasedPredicateChecker(kubeClient, make(chan struct{})) | ||
predicateChecker, err := predicatechecker.NewSchedulerBasedPredicateChecker(kubeClient, | ||
autoscalingOptions.SchedulerConfig, make(chan struct{})) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think
SchedulerConfig
belongs in options.SchedulerConfigPath
probably would, though - the types here should stay simple (ints/strings/time.Durations).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me think about this 🙏
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess the reason we want to keep it simple is because these are
AutoscalingOptions
and they should represent options instead of result of options.