-
Notifications
You must be signed in to change notification settings - Fork 41.3k
Log defaulted kube-scheduler component config at startup #96426
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
Log defaulted kube-scheduler component config at startup #96426
Conversation
/cc @ahg-g @alculquicondor @ingvagabund |
// WriteConfigFile writes the config into the given file name as YAML. | ||
func WriteConfigFile(fileName string, cfg *kubeschedulerconfig.KubeSchedulerConfiguration) error { | ||
// LogAndWriteConfigFile writes the config into the given file name as YAML. | ||
func LogAndWriteConfigFile(fileName string, cfg *kubeschedulerconfig.KubeSchedulerConfiguration) error { |
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.
Not sure who would use a filename (probably just us k8s-devs), but why not "LogOrWrite"
return err | ||
} | ||
configString := string(bytes) | ||
klog.V(2).Infof("Starting scheduler with component config:\n%+v\n", configString) |
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.
klog.V(2).Infof("Starting scheduler with component config:\n%+v\n", configString) | |
klog.V(2).Infof("Using component config:\n%+v\n", configString) |
const mediaType = runtime.ContentTypeYAML | ||
info, ok := runtime.SerializerInfoForMediaType(kubeschedulerscheme.Codecs.SupportedMediaTypes(), mediaType) | ||
if !ok { | ||
return fmt.Errorf("unable to locate encoder -- %q is not a supported media type", mediaType) | ||
} | ||
|
||
encoder := kubeschedulerscheme.Codecs.EncoderForVersion(info.Serializer, kubeschedulerconfigv1beta1.SchemeGroupVersion) | ||
|
||
configFile, err := os.Create(fileName) | ||
bytes, err := runtime.Encode(encoder, cfg) |
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.
nit: Only encode if klog.V(2)
pkg/scheduler/factory.go
Outdated
} | ||
|
||
// create a scheduler from a set of registered plugins. | ||
func (c *Configurator) create() (*Scheduler, error) { | ||
c.componentConfig.Profiles = make([]schedulerapi.KubeSchedulerProfile, 0) |
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.
c.componentConfig
could be nil
cmd/kube-scheduler/app/server.go
Outdated
@@ -323,10 +319,14 @@ func Setup(ctx context.Context, opts *options.Options, outOfTreeRegistryOptions | |||
scheduler.WithPodInitialBackoffSeconds(cc.ComponentConfig.PodInitialBackoffSeconds), | |||
scheduler.WithExtenders(cc.ComponentConfig.Extenders...), | |||
scheduler.WithParallelism(cc.ComponentConfig.Parallelism), | |||
scheduler.WithComponentConfig(&cc.ComponentConfig), |
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.
All options are about configuring the scheduler, but this one is actually about capturing the output.
So, I would rather call it WithComponentConfigOutput
. But also we only care about profiles, so could be limited to cc.ComponentConfig.Profiles.
Or you could do WithCaptureProfiles(func ([]config.KubeSchedulerProfile))
so that the caller is free to do with it whatever they want.
We actually have something like the above that we use for tests https://github.com/kubernetes/kubernetes/blob/master/pkg/scheduler/scheduler.go#L168
It would be cool to unify that. Tests check the expected output, whereas prod scheduler uses it for logs.
@@ -199,6 +200,12 @@ func WithExtenders(extenders []framework.Extender) Option { | |||
} | |||
} | |||
|
|||
func WithComponentConfig(cc *config.KubeSchedulerConfiguration) Option { |
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.
Similarly to the ideas above, this could be:
WithProfileCapturer(func (*config.KubeSchedulerProfile))
and the code in scheduler.go is in charge of the aggregation.
/milestone v1.20 |
possible github issue, please link if you run into this on other PR's kubernetes/test-infra#19910 |
Some plugin configs are not produced until the framework is instantiated. Add a callback to capture them inside the framework constructor. Change-Id: Id3f709b6461ccd0eafec7d21412cda093d9c4645
@@ -247,6 +254,8 @@ func NewFramework(r Registry, plugins *config.Plugins, args []config.PluginConfi | |||
return f, nil | |||
} | |||
|
|||
profile := config.KubeSchedulerProfile{SchedulerName: f.ProfileName(), Plugins: plugins, PluginConfig: make([]config.PluginConfig, 0)} |
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.
If the goal is to print the final config, we missed a little thing, at line 296, the weight changed to 1 if it is 0. Not sure it is worth it or not. Actually, I also point it out at d6ef6d6#r521218103, at least it is fine for the test.
56da280
to
a41b8dd
Compare
f922512
to
a5064bb
Compare
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.
@alculquicondor I rebased this onto the changes from your PR (#96438) and just re-used your WithBuildFrameworkCapturer
option to append the profiles. You can see just my changes in a5064bb. ptal!
@@ -323,10 +319,19 @@ func Setup(ctx context.Context, opts *options.Options, outOfTreeRegistryOptions | |||
scheduler.WithPodInitialBackoffSeconds(cc.ComponentConfig.PodInitialBackoffSeconds), | |||
scheduler.WithExtenders(cc.ComponentConfig.Extenders...), | |||
scheduler.WithParallelism(cc.ComponentConfig.Parallelism), | |||
scheduler.WithBuildFrameworkCapturer(func(profile kubeschedulerconfig.KubeSchedulerProfile) { |
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.
Add a comment to clarify why is this done.
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.
That's a "what", not a "why" 😉
I would say something like: "Profiles are processed during Framework instantiation to set default plugins and configurations. Capturing them for logging".
@@ -129,10 +129,6 @@ func runCommand(cmd *cobra.Command, opts *options.Options, registryOptions ...Op | |||
} | |||
|
|||
if len(opts.WriteConfigTo) > 0 { | |||
if err := options.WriteConfigFile(opts.WriteConfigTo, &cc.ComponentConfig); err != nil { |
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.
Add a comment to say where this parameter was handled.... but maybe we can do os.Exit(0)
in LogOrWriteConfig
?
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.
Added an os.Exit(0)
to LogOrWriteConfig
cmd/kube-scheduler/app/server.go
Outdated
@@ -323,10 +319,19 @@ func Setup(ctx context.Context, opts *options.Options, outOfTreeRegistryOptions | |||
scheduler.WithPodInitialBackoffSeconds(cc.ComponentConfig.PodInitialBackoffSeconds), | |||
scheduler.WithExtenders(cc.ComponentConfig.Extenders...), | |||
scheduler.WithParallelism(cc.ComponentConfig.Parallelism), | |||
scheduler.WithBuildFrameworkCapturer(func(profile kubeschedulerconfig.KubeSchedulerProfile) { | |||
if cc.ComponentConfig.Profiles == nil { | |||
cc.ComponentConfig.Profiles = make([]kubeschedulerconfig.KubeSchedulerProfile, 0) |
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.
shouldn't we always make a new slice?
a5064bb
to
edfa12d
Compare
edfa12d
to
005cbe6
Compare
@@ -48,24 +49,40 @@ func loadConfig(data []byte) (*kubeschedulerconfig.KubeSchedulerConfiguration, e | |||
return nil, fmt.Errorf("couldn't decode as KubeSchedulerConfiguration, got %s: ", gvk) | |||
} | |||
|
|||
// WriteConfigFile writes the config into the given file name as YAML. | |||
func WriteConfigFile(fileName string, cfg *kubeschedulerconfig.KubeSchedulerConfiguration) error { | |||
// LogOrWriteConfig writes the config into the given file name as YAML. |
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.
Update the comment to match the new logic
@@ -323,10 +319,19 @@ func Setup(ctx context.Context, opts *options.Options, outOfTreeRegistryOptions | |||
scheduler.WithPodInitialBackoffSeconds(cc.ComponentConfig.PodInitialBackoffSeconds), | |||
scheduler.WithExtenders(cc.ComponentConfig.Extenders...), | |||
scheduler.WithParallelism(cc.ComponentConfig.Parallelism), | |||
scheduler.WithBuildFrameworkCapturer(func(profile kubeschedulerconfig.KubeSchedulerProfile) { |
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.
That's a "what", not a "why" 😉
I would say something like: "Profiles are processed during Framework instantiation to set default plugins and configurations. Capturing them for logging".
) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
if err := options.LogOrWriteConfig(opts.WriteConfigTo, &cc.ComponentConfig, completedProfiles); err != nil { |
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.
why not just override the completed profiles at this point?
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.
We could, but since it's only necessary if we're logging/writing the config I figured I'd keep that logic in the function
005cbe6
to
aec327c
Compare
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.
/approve
/lgtm
/priority important-soon
I don't really mind if this PR merges and the parent doesn't :)
/triage accepted |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: alculquicondor, damemi The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
/retest
but adding the defaultpreemption args causes it to fail locally for me:
|
aec327c
to
37b3d47
Compare
/lgtm |
37b3d47
to
14fa76d
Compare
/lgtm |
What type of PR is this?
/kind cleanup
What this PR does / why we need it:
This PR passes the initialized ComponentConfig for kube-scheduler through the framework initialization functions, allowing the default plugin registry (and PluginArgs) to be presented to the user after plugin instantiation is filled out by API defaulting.
Which issue(s) this PR fixes:
Fixes #93718
Special notes for your reviewer:
Does this PR introduce a user-facing change?:
Additional documentation e.g., KEPs (Kubernetes Enhancement Proposals), usage docs, etc.:
The output from a default scheduler with these changes looks like this:
/sig scheduling