Merge pull request #88087 from alculquicondor/mutiprofiles-api

Add Schedulings Profiles to kubescheduler.config.k8s.io/v1alpha2
This commit is contained in:
Kubernetes Prow Robot 2020-02-24 14:43:35 -08:00 committed by GitHub
commit f6525dbc81
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 721 additions and 234 deletions

View File

@ -38,6 +38,7 @@ type DeprecatedOptions struct {
UseLegacyPolicyConfig bool UseLegacyPolicyConfig bool
AlgorithmProvider string AlgorithmProvider string
HardPodAffinitySymmetricWeight int32 HardPodAffinitySymmetricWeight int32
SchedulerName string
} }
// AddFlags adds flags for the deprecated options. // AddFlags adds flags for the deprecated options.
@ -59,14 +60,14 @@ func (o *DeprecatedOptions) AddFlags(fs *pflag.FlagSet, cfg *kubeschedulerconfig
fs.StringVar(&cfg.ClientConnection.ContentType, "kube-api-content-type", cfg.ClientConnection.ContentType, "DEPRECATED: content type of requests sent to apiserver.") fs.StringVar(&cfg.ClientConnection.ContentType, "kube-api-content-type", cfg.ClientConnection.ContentType, "DEPRECATED: content type of requests sent to apiserver.")
fs.Float32Var(&cfg.ClientConnection.QPS, "kube-api-qps", cfg.ClientConnection.QPS, "DEPRECATED: QPS to use while talking with kubernetes apiserver") fs.Float32Var(&cfg.ClientConnection.QPS, "kube-api-qps", cfg.ClientConnection.QPS, "DEPRECATED: QPS to use while talking with kubernetes apiserver")
fs.Int32Var(&cfg.ClientConnection.Burst, "kube-api-burst", cfg.ClientConnection.Burst, "DEPRECATED: burst to use while talking with kubernetes apiserver") fs.Int32Var(&cfg.ClientConnection.Burst, "kube-api-burst", cfg.ClientConnection.Burst, "DEPRECATED: burst to use while talking with kubernetes apiserver")
fs.StringVar(&cfg.SchedulerName, "scheduler-name", cfg.SchedulerName, "DEPRECATED: name of the scheduler, used to select which pods will be processed by this scheduler, based on pod's \"spec.schedulerName\".")
fs.StringVar(&cfg.LeaderElection.ResourceNamespace, "lock-object-namespace", cfg.LeaderElection.ResourceNamespace, "DEPRECATED: define the namespace of the lock object. Will be removed in favor of leader-elect-resource-namespace.") fs.StringVar(&cfg.LeaderElection.ResourceNamespace, "lock-object-namespace", cfg.LeaderElection.ResourceNamespace, "DEPRECATED: define the namespace of the lock object. Will be removed in favor of leader-elect-resource-namespace.")
fs.StringVar(&cfg.LeaderElection.ResourceName, "lock-object-name", cfg.LeaderElection.ResourceName, "DEPRECATED: define the name of the lock object. Will be removed in favor of leader-elect-resource-name") fs.StringVar(&cfg.LeaderElection.ResourceName, "lock-object-name", cfg.LeaderElection.ResourceName, "DEPRECATED: define the name of the lock object. Will be removed in favor of leader-elect-resource-name")
fs.Int32Var(&o.HardPodAffinitySymmetricWeight, "hard-pod-affinity-symmetric-weight", interpodaffinity.DefaultHardPodAffinityWeight, fs.Int32Var(&o.HardPodAffinitySymmetricWeight, "hard-pod-affinity-symmetric-weight", o.HardPodAffinitySymmetricWeight,
"DEPRECATED: RequiredDuringScheduling affinity is not symmetric, but there is an implicit PreferredDuringScheduling affinity rule corresponding "+ "DEPRECATED: RequiredDuringScheduling affinity is not symmetric, but there is an implicit PreferredDuringScheduling affinity rule corresponding "+
"to every RequiredDuringScheduling affinity rule. --hard-pod-affinity-symmetric-weight represents the weight of implicit PreferredDuringScheduling affinity rule. Must be in the range 0-100."+ "to every RequiredDuringScheduling affinity rule. --hard-pod-affinity-symmetric-weight represents the weight of implicit PreferredDuringScheduling affinity rule. Must be in the range 0-100."+
"This option was moved to the policy configuration file") "This option was moved to the policy configuration file")
fs.StringVar(&o.SchedulerName, "scheduler-name", o.SchedulerName, "DEPRECATED: name of the scheduler, used to select which pods will be processed by this scheduler, based on pod's \"spec.schedulerName\".")
// MarkDeprecated hides the flag from the help. We don't want that: // MarkDeprecated hides the flag from the help. We don't want that:
// fs.MarkDeprecated("hard-pod-affinity-symmetric-weight", "This option was moved to the policy configuration file") // fs.MarkDeprecated("hard-pod-affinity-symmetric-weight", "This option was moved to the policy configuration file")
} }
@ -120,11 +121,17 @@ func (o *DeprecatedOptions) ApplyTo(cfg *kubeschedulerconfig.KubeSchedulerConfig
} }
} }
// The following deprecated options affect the only existing profile that is
// added by default.
profile := &cfg.Profiles[0]
if len(o.SchedulerName) > 0 {
profile.SchedulerName = o.SchedulerName
}
if o.HardPodAffinitySymmetricWeight != interpodaffinity.DefaultHardPodAffinityWeight { if o.HardPodAffinitySymmetricWeight != interpodaffinity.DefaultHardPodAffinityWeight {
args := interpodaffinity.Args{ args := interpodaffinity.Args{
HardPodAffinityWeight: &o.HardPodAffinitySymmetricWeight, HardPodAffinityWeight: &o.HardPodAffinitySymmetricWeight,
} }
cfg.PluginConfig = append(cfg.PluginConfig, plugins.NewPluginConfig(interpodaffinity.Name, args)) profile.PluginConfig = append(profile.PluginConfig, plugins.NewPluginConfig(interpodaffinity.Name, args))
} }
return nil return nil

View File

@ -48,6 +48,7 @@ import (
kubeschedulerconfig "k8s.io/kubernetes/pkg/scheduler/apis/config" kubeschedulerconfig "k8s.io/kubernetes/pkg/scheduler/apis/config"
kubeschedulerscheme "k8s.io/kubernetes/pkg/scheduler/apis/config/scheme" kubeschedulerscheme "k8s.io/kubernetes/pkg/scheduler/apis/config/scheme"
"k8s.io/kubernetes/pkg/scheduler/apis/config/validation" "k8s.io/kubernetes/pkg/scheduler/apis/config/validation"
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/interpodaffinity"
) )
// Options has all the params needed to run a Scheduler // Options has all the params needed to run a Scheduler
@ -98,8 +99,10 @@ func NewOptions() (*Options, error) {
Authentication: apiserveroptions.NewDelegatingAuthenticationOptions(), Authentication: apiserveroptions.NewDelegatingAuthenticationOptions(),
Authorization: apiserveroptions.NewDelegatingAuthorizationOptions(), Authorization: apiserveroptions.NewDelegatingAuthorizationOptions(),
Deprecated: &DeprecatedOptions{ Deprecated: &DeprecatedOptions{
UseLegacyPolicyConfig: false, UseLegacyPolicyConfig: false,
PolicyConfigMapNamespace: metav1.NamespaceSystem, PolicyConfigMapNamespace: metav1.NamespaceSystem,
SchedulerName: corev1.DefaultSchedulerName,
HardPodAffinitySymmetricWeight: interpodaffinity.DefaultHardPodAffinityWeight,
}, },
} }
@ -239,11 +242,12 @@ func (o *Options) Config() (*schedulerappconfig.Config, error) {
} }
coreBroadcaster := record.NewBroadcaster() coreBroadcaster := record.NewBroadcaster()
coreRecorder := coreBroadcaster.NewRecorder(scheme.Scheme, corev1.EventSource{Component: c.ComponentConfig.SchedulerName})
// Set up leader election if enabled. // Set up leader election if enabled.
var leaderElectionConfig *leaderelection.LeaderElectionConfig var leaderElectionConfig *leaderelection.LeaderElectionConfig
if c.ComponentConfig.LeaderElection.LeaderElect { if c.ComponentConfig.LeaderElection.LeaderElect {
// Use the scheduler name in the first profile to record leader election.
coreRecorder := coreBroadcaster.NewRecorder(scheme.Scheme, corev1.EventSource{Component: c.ComponentConfig.Profiles[0].SchedulerName})
leaderElectionConfig, err = makeLeaderElectionConfig(c.ComponentConfig.LeaderElection, leaderElectionClient, coreRecorder) leaderElectionConfig, err = makeLeaderElectionConfig(c.ComponentConfig.LeaderElection, leaderElectionClient, coreRecorder)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -138,6 +138,7 @@ leaderElection:
if err := ioutil.WriteFile(v1alpha1Config, []byte(fmt.Sprintf(` if err := ioutil.WriteFile(v1alpha1Config, []byte(fmt.Sprintf(`
apiVersion: kubescheduler.config.k8s.io/v1alpha1 apiVersion: kubescheduler.config.k8s.io/v1alpha1
kind: KubeSchedulerConfiguration kind: KubeSchedulerConfiguration
schedulerName: "my-old-scheduler"
clientConnection: clientConnection:
kubeconfig: "%s" kubeconfig: "%s"
leaderElection: leaderElection:
@ -225,20 +226,21 @@ apiVersion: kubescheduler.config.k8s.io/v1alpha2
kind: KubeSchedulerConfiguration kind: KubeSchedulerConfiguration
clientConnection: clientConnection:
kubeconfig: "%s" kubeconfig: "%s"
plugins: profiles:
reserve: - plugins:
enabled: reserve:
- name: foo enabled:
- name: bar - name: foo
disabled: - name: bar
- name: baz disabled:
preBind: - name: baz
enabled: preBind:
- name: foo enabled:
disabled: - name: foo
- name: baz disabled:
pluginConfig: - name: baz
- name: foo pluginConfig:
- name: foo
`, configKubeconfig)), os.FileMode(0600)); err != nil { `, configKubeconfig)), os.FileMode(0600)); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -319,7 +321,6 @@ plugins:
}, },
expectedUsername: "config", expectedUsername: "config",
expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{ expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{
SchedulerName: "default-scheduler",
AlgorithmSource: kubeschedulerconfig.SchedulerAlgorithmSource{Provider: &defaultSource}, AlgorithmSource: kubeschedulerconfig.SchedulerAlgorithmSource{Provider: &defaultSource},
HealthzBindAddress: "0.0.0.0:10251", HealthzBindAddress: "0.0.0.0:10251",
MetricsBindAddress: "0.0.0.0:10251", MetricsBindAddress: "0.0.0.0:10251",
@ -348,7 +349,9 @@ plugins:
BindTimeoutSeconds: defaultBindTimeoutSeconds, BindTimeoutSeconds: defaultBindTimeoutSeconds,
PodInitialBackoffSeconds: defaultPodInitialBackoffSeconds, PodInitialBackoffSeconds: defaultPodInitialBackoffSeconds,
PodMaxBackoffSeconds: defaultPodMaxBackoffSeconds, PodMaxBackoffSeconds: defaultPodMaxBackoffSeconds,
Plugins: nil, Profiles: []kubeschedulerconfig.KubeSchedulerProfile{
{SchedulerName: "default-scheduler"},
},
}, },
}, },
{ {
@ -410,7 +413,6 @@ plugins:
}, },
expectedUsername: "flag", expectedUsername: "flag",
expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{ expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{
SchedulerName: "default-scheduler",
AlgorithmSource: kubeschedulerconfig.SchedulerAlgorithmSource{Provider: &defaultSource}, AlgorithmSource: kubeschedulerconfig.SchedulerAlgorithmSource{Provider: &defaultSource},
HealthzBindAddress: "", // defaults empty when not running from config file HealthzBindAddress: "", // defaults empty when not running from config file
MetricsBindAddress: "", // defaults empty when not running from config file MetricsBindAddress: "", // defaults empty when not running from config file
@ -439,6 +441,9 @@ plugins:
BindTimeoutSeconds: defaultBindTimeoutSeconds, BindTimeoutSeconds: defaultBindTimeoutSeconds,
PodInitialBackoffSeconds: defaultPodInitialBackoffSeconds, PodInitialBackoffSeconds: defaultPodInitialBackoffSeconds,
PodMaxBackoffSeconds: defaultPodMaxBackoffSeconds, PodMaxBackoffSeconds: defaultPodMaxBackoffSeconds,
Profiles: []kubeschedulerconfig.KubeSchedulerProfile{
{SchedulerName: "default-scheduler"},
},
}, },
}, },
{ {
@ -474,7 +479,6 @@ plugins:
}, },
}, },
expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{ expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{
SchedulerName: "default-scheduler",
AlgorithmSource: kubeschedulerconfig.SchedulerAlgorithmSource{Provider: &defaultSource}, AlgorithmSource: kubeschedulerconfig.SchedulerAlgorithmSource{Provider: &defaultSource},
HealthzBindAddress: "", // defaults empty when not running from config file HealthzBindAddress: "", // defaults empty when not running from config file
MetricsBindAddress: "", // defaults empty when not running from config file MetricsBindAddress: "", // defaults empty when not running from config file
@ -503,6 +507,9 @@ plugins:
BindTimeoutSeconds: defaultBindTimeoutSeconds, BindTimeoutSeconds: defaultBindTimeoutSeconds,
PodInitialBackoffSeconds: defaultPodInitialBackoffSeconds, PodInitialBackoffSeconds: defaultPodInitialBackoffSeconds,
PodMaxBackoffSeconds: defaultPodMaxBackoffSeconds, PodMaxBackoffSeconds: defaultPodMaxBackoffSeconds,
Profiles: []kubeschedulerconfig.KubeSchedulerProfile{
{SchedulerName: "default-scheduler"},
},
}, },
expectedUsername: "none, http", expectedUsername: "none, http",
}, },
@ -513,7 +520,6 @@ plugins:
}, },
expectedUsername: "config", expectedUsername: "config",
expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{ expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{
SchedulerName: "default-scheduler",
AlgorithmSource: kubeschedulerconfig.SchedulerAlgorithmSource{Provider: &defaultSource}, AlgorithmSource: kubeschedulerconfig.SchedulerAlgorithmSource{Provider: &defaultSource},
HealthzBindAddress: "0.0.0.0:10251", HealthzBindAddress: "0.0.0.0:10251",
MetricsBindAddress: "0.0.0.0:10251", MetricsBindAddress: "0.0.0.0:10251",
@ -542,39 +548,44 @@ plugins:
BindTimeoutSeconds: defaultBindTimeoutSeconds, BindTimeoutSeconds: defaultBindTimeoutSeconds,
PodInitialBackoffSeconds: defaultPodInitialBackoffSeconds, PodInitialBackoffSeconds: defaultPodInitialBackoffSeconds,
PodMaxBackoffSeconds: defaultPodMaxBackoffSeconds, PodMaxBackoffSeconds: defaultPodMaxBackoffSeconds,
Plugins: &kubeschedulerconfig.Plugins{ Profiles: []kubeschedulerconfig.KubeSchedulerProfile{
Reserve: &kubeschedulerconfig.PluginSet{
Enabled: []kubeschedulerconfig.Plugin{
{
Name: "foo",
},
{
Name: "bar",
},
},
Disabled: []kubeschedulerconfig.Plugin{
{
Name: "baz",
},
},
},
PreBind: &kubeschedulerconfig.PluginSet{
Enabled: []kubeschedulerconfig.Plugin{
{
Name: "foo",
},
},
Disabled: []kubeschedulerconfig.Plugin{
{
Name: "baz",
},
},
},
},
PluginConfig: []kubeschedulerconfig.PluginConfig{
{ {
Name: "foo", SchedulerName: "default-scheduler",
Args: runtime.Unknown{}, Plugins: &kubeschedulerconfig.Plugins{
Reserve: &kubeschedulerconfig.PluginSet{
Enabled: []kubeschedulerconfig.Plugin{
{
Name: "foo",
},
{
Name: "bar",
},
},
Disabled: []kubeschedulerconfig.Plugin{
{
Name: "baz",
},
},
},
PreBind: &kubeschedulerconfig.PluginSet{
Enabled: []kubeschedulerconfig.Plugin{
{
Name: "foo",
},
},
Disabled: []kubeschedulerconfig.Plugin{
{
Name: "baz",
},
},
},
},
PluginConfig: []kubeschedulerconfig.PluginConfig{
{
Name: "foo",
Args: runtime.Unknown{},
},
},
}, },
}, },
}, },
@ -586,7 +597,6 @@ plugins:
}, },
expectedUsername: "config", expectedUsername: "config",
expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{ expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{
SchedulerName: "default-scheduler",
AlgorithmSource: kubeschedulerconfig.SchedulerAlgorithmSource{Provider: &defaultSource}, AlgorithmSource: kubeschedulerconfig.SchedulerAlgorithmSource{Provider: &defaultSource},
HealthzBindAddress: "0.0.0.0:10251", HealthzBindAddress: "0.0.0.0:10251",
MetricsBindAddress: "0.0.0.0:10251", MetricsBindAddress: "0.0.0.0:10251",
@ -615,19 +625,24 @@ plugins:
BindTimeoutSeconds: defaultBindTimeoutSeconds, BindTimeoutSeconds: defaultBindTimeoutSeconds,
PodInitialBackoffSeconds: defaultPodInitialBackoffSeconds, PodInitialBackoffSeconds: defaultPodInitialBackoffSeconds,
PodMaxBackoffSeconds: defaultPodMaxBackoffSeconds, PodMaxBackoffSeconds: defaultPodMaxBackoffSeconds,
Plugins: &kubeschedulerconfig.Plugins{ Profiles: []kubeschedulerconfig.KubeSchedulerProfile{
PreScore: &kubeschedulerconfig.PluginSet{ {
Enabled: []kubeschedulerconfig.Plugin{ SchedulerName: "default-scheduler",
{ Plugins: &kubeschedulerconfig.Plugins{
Name: "foo", PreScore: &kubeschedulerconfig.PluginSet{
}, Enabled: []kubeschedulerconfig.Plugin{
{ {
Name: "bar", Name: "foo",
}, },
}, {
Disabled: []kubeschedulerconfig.Plugin{ Name: "bar",
{ },
Name: "baz", },
Disabled: []kubeschedulerconfig.Plugin{
{
Name: "baz",
},
},
}, },
}, },
}, },
@ -653,7 +668,6 @@ plugins:
}, },
expectedUsername: "flag", expectedUsername: "flag",
expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{ expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{
SchedulerName: "default-scheduler",
AlgorithmSource: kubeschedulerconfig.SchedulerAlgorithmSource{Provider: &defaultSource}, AlgorithmSource: kubeschedulerconfig.SchedulerAlgorithmSource{Provider: &defaultSource},
DebuggingConfiguration: componentbaseconfig.DebuggingConfiguration{ DebuggingConfiguration: componentbaseconfig.DebuggingConfiguration{
EnableProfiling: true, EnableProfiling: true,
@ -680,24 +694,74 @@ plugins:
BindTimeoutSeconds: defaultBindTimeoutSeconds, BindTimeoutSeconds: defaultBindTimeoutSeconds,
PodInitialBackoffSeconds: defaultPodInitialBackoffSeconds, PodInitialBackoffSeconds: defaultPodInitialBackoffSeconds,
PodMaxBackoffSeconds: defaultPodMaxBackoffSeconds, PodMaxBackoffSeconds: defaultPodMaxBackoffSeconds,
PluginConfig: []kubeschedulerconfig.PluginConfig{ Profiles: []kubeschedulerconfig.KubeSchedulerProfile{
{ {
Name: "InterPodAffinity", SchedulerName: "default-scheduler",
Args: runtime.Unknown{ PluginConfig: []kubeschedulerconfig.PluginConfig{
Raw: []byte(`{"hardPodAffinityWeight":5}`), {
Name: "InterPodAffinity",
Args: runtime.Unknown{
Raw: []byte(`{"hardPodAffinityWeight":5}`),
},
},
}, },
}, },
}, },
}, },
}, },
{ {
name: "v1alpha1 config with HardPodAffinitySymmetricWeight", name: "Deprecated SchedulerName flag",
options: &Options{
ComponentConfig: func() kubeschedulerconfig.KubeSchedulerConfiguration {
cfg, _ := newDefaultComponentConfig()
cfg.ClientConnection.Kubeconfig = flagKubeconfig
return *cfg
}(),
Deprecated: &DeprecatedOptions{
SchedulerName: "my-nice-scheduler",
HardPodAffinitySymmetricWeight: 1,
},
},
expectedUsername: "flag",
expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{
AlgorithmSource: kubeschedulerconfig.SchedulerAlgorithmSource{Provider: &defaultSource},
DebuggingConfiguration: componentbaseconfig.DebuggingConfiguration{
EnableProfiling: true,
EnableContentionProfiling: true,
},
LeaderElection: kubeschedulerconfig.KubeSchedulerLeaderElectionConfiguration{
LeaderElectionConfiguration: componentbaseconfig.LeaderElectionConfiguration{
LeaderElect: true,
LeaseDuration: metav1.Duration{Duration: 15 * time.Second},
RenewDeadline: metav1.Duration{Duration: 10 * time.Second},
RetryPeriod: metav1.Duration{Duration: 2 * time.Second},
ResourceLock: "endpointsleases",
ResourceNamespace: "kube-system",
ResourceName: "kube-scheduler",
},
},
ClientConnection: componentbaseconfig.ClientConnectionConfiguration{
Kubeconfig: flagKubeconfig,
QPS: 50,
Burst: 100,
ContentType: "application/vnd.kubernetes.protobuf",
},
PercentageOfNodesToScore: defaultPercentageOfNodesToScore,
BindTimeoutSeconds: defaultBindTimeoutSeconds,
PodInitialBackoffSeconds: defaultPodInitialBackoffSeconds,
PodMaxBackoffSeconds: defaultPodMaxBackoffSeconds,
Profiles: []kubeschedulerconfig.KubeSchedulerProfile{
{SchedulerName: "my-nice-scheduler"},
},
},
},
{
name: "v1alpha1 config with SchedulerName and HardPodAffinitySymmetricWeight",
options: &Options{ options: &Options{
ConfigFile: v1alpha1Config, ConfigFile: v1alpha1Config,
}, },
expectedUsername: "config", expectedUsername: "config",
expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{ expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{
SchedulerName: "default-scheduler",
AlgorithmSource: kubeschedulerconfig.SchedulerAlgorithmSource{Provider: &defaultSource}, AlgorithmSource: kubeschedulerconfig.SchedulerAlgorithmSource{Provider: &defaultSource},
HealthzBindAddress: "0.0.0.0:10251", HealthzBindAddress: "0.0.0.0:10251",
MetricsBindAddress: "0.0.0.0:10251", MetricsBindAddress: "0.0.0.0:10251",
@ -726,11 +790,16 @@ plugins:
BindTimeoutSeconds: defaultBindTimeoutSeconds, BindTimeoutSeconds: defaultBindTimeoutSeconds,
PodInitialBackoffSeconds: defaultPodInitialBackoffSeconds, PodInitialBackoffSeconds: defaultPodInitialBackoffSeconds,
PodMaxBackoffSeconds: defaultPodMaxBackoffSeconds, PodMaxBackoffSeconds: defaultPodMaxBackoffSeconds,
PluginConfig: []kubeschedulerconfig.PluginConfig{ Profiles: []kubeschedulerconfig.KubeSchedulerProfile{
{ {
Name: "InterPodAffinity", SchedulerName: "my-old-scheduler",
Args: runtime.Unknown{ PluginConfig: []kubeschedulerconfig.PluginConfig{
Raw: []byte(`{"hardPodAffinityWeight":3}`), {
Name: "InterPodAffinity",
Args: runtime.Unknown{
Raw: []byte(`{"hardPodAffinityWeight":3}`),
},
},
}, },
}, },
}, },
@ -743,7 +812,6 @@ plugins:
}, },
expectedUsername: "config", expectedUsername: "config",
expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{ expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{
SchedulerName: "default-scheduler",
AlgorithmSource: kubeschedulerconfig.SchedulerAlgorithmSource{Provider: &defaultSource}, AlgorithmSource: kubeschedulerconfig.SchedulerAlgorithmSource{Provider: &defaultSource},
HealthzBindAddress: "0.0.0.0:10251", HealthzBindAddress: "0.0.0.0:10251",
MetricsBindAddress: "0.0.0.0:10251", MetricsBindAddress: "0.0.0.0:10251",
@ -772,7 +840,9 @@ plugins:
BindTimeoutSeconds: defaultBindTimeoutSeconds, BindTimeoutSeconds: defaultBindTimeoutSeconds,
PodInitialBackoffSeconds: defaultPodInitialBackoffSeconds, PodInitialBackoffSeconds: defaultPodInitialBackoffSeconds,
PodMaxBackoffSeconds: defaultPodMaxBackoffSeconds, PodMaxBackoffSeconds: defaultPodMaxBackoffSeconds,
Plugins: nil, Profiles: []kubeschedulerconfig.KubeSchedulerProfile{
{SchedulerName: "default-scheduler"},
},
}, },
}, },
{ {
@ -790,7 +860,6 @@ plugins:
}, },
expectedUsername: "config", expectedUsername: "config",
expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{ expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{
SchedulerName: "default-scheduler",
AlgorithmSource: kubeschedulerconfig.SchedulerAlgorithmSource{Provider: &defaultSource}, AlgorithmSource: kubeschedulerconfig.SchedulerAlgorithmSource{Provider: &defaultSource},
HealthzBindAddress: "0.0.0.0:10251", HealthzBindAddress: "0.0.0.0:10251",
MetricsBindAddress: "0.0.0.0:10251", MetricsBindAddress: "0.0.0.0:10251",
@ -819,7 +888,9 @@ plugins:
BindTimeoutSeconds: defaultBindTimeoutSeconds, BindTimeoutSeconds: defaultBindTimeoutSeconds,
PodInitialBackoffSeconds: defaultPodInitialBackoffSeconds, PodInitialBackoffSeconds: defaultPodInitialBackoffSeconds,
PodMaxBackoffSeconds: defaultPodMaxBackoffSeconds, PodMaxBackoffSeconds: defaultPodMaxBackoffSeconds,
Plugins: nil, Profiles: []kubeschedulerconfig.KubeSchedulerProfile{
{SchedulerName: "default-scheduler"},
},
}, },
}, },
{ {

View File

@ -19,6 +19,7 @@ package app
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
@ -171,12 +172,17 @@ func Run(ctx context.Context, cc schedulerserverconfig.CompletedConfig, outOfTre
} }
} }
if len(cc.ComponentConfig.Profiles) != 1 {
// TODO(#85737): Support more than one profile.
return errors.New("multiple scheduling profiles are unsupported")
}
profile := cc.ComponentConfig.Profiles[0]
// Prepare event clients. // Prepare event clients.
if _, err := cc.Client.Discovery().ServerResourcesForGroupVersion(eventsv1beta1.SchemeGroupVersion.String()); err == nil { if _, err := cc.Client.Discovery().ServerResourcesForGroupVersion(eventsv1beta1.SchemeGroupVersion.String()); err == nil {
cc.Broadcaster = events.NewBroadcaster(&events.EventSinkImpl{Interface: cc.EventClient.Events("")}) cc.Broadcaster = events.NewBroadcaster(&events.EventSinkImpl{Interface: cc.EventClient.Events("")})
cc.Recorder = cc.Broadcaster.NewRecorder(scheme.Scheme, cc.ComponentConfig.SchedulerName) cc.Recorder = cc.Broadcaster.NewRecorder(scheme.Scheme, profile.SchedulerName)
} else { } else {
recorder := cc.CoreBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: cc.ComponentConfig.SchedulerName}) recorder := cc.CoreBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: profile.SchedulerName})
cc.Recorder = record.NewEventRecorderAdapter(recorder) cc.Recorder = record.NewEventRecorderAdapter(recorder)
} }
@ -186,14 +192,14 @@ func Run(ctx context.Context, cc schedulerserverconfig.CompletedConfig, outOfTre
cc.PodInformer, cc.PodInformer,
cc.Recorder, cc.Recorder,
ctx.Done(), ctx.Done(),
scheduler.WithName(cc.ComponentConfig.SchedulerName), scheduler.WithName(profile.SchedulerName),
scheduler.WithAlgorithmSource(cc.ComponentConfig.AlgorithmSource), scheduler.WithAlgorithmSource(cc.ComponentConfig.AlgorithmSource),
scheduler.WithPreemptionDisabled(cc.ComponentConfig.DisablePreemption), scheduler.WithPreemptionDisabled(cc.ComponentConfig.DisablePreemption),
scheduler.WithPercentageOfNodesToScore(cc.ComponentConfig.PercentageOfNodesToScore), scheduler.WithPercentageOfNodesToScore(cc.ComponentConfig.PercentageOfNodesToScore),
scheduler.WithBindTimeoutSeconds(cc.ComponentConfig.BindTimeoutSeconds), scheduler.WithBindTimeoutSeconds(cc.ComponentConfig.BindTimeoutSeconds),
scheduler.WithFrameworkOutOfTreeRegistry(outOfTreeRegistry), scheduler.WithFrameworkOutOfTreeRegistry(outOfTreeRegistry),
scheduler.WithFrameworkPlugins(cc.ComponentConfig.Plugins), scheduler.WithFrameworkPlugins(profile.Plugins),
scheduler.WithFrameworkPluginConfig(cc.ComponentConfig.PluginConfig), scheduler.WithFrameworkPluginConfig(profile.PluginConfig),
scheduler.WithPodMaxBackoffSeconds(cc.ComponentConfig.PodMaxBackoffSeconds), scheduler.WithPodMaxBackoffSeconds(cc.ComponentConfig.PodMaxBackoffSeconds),
scheduler.WithPodInitialBackoffSeconds(cc.ComponentConfig.PodInitialBackoffSeconds), scheduler.WithPodInitialBackoffSeconds(cc.ComponentConfig.PodInitialBackoffSeconds),
) )

View File

@ -46,9 +46,6 @@ const (
type KubeSchedulerConfiguration struct { type KubeSchedulerConfiguration struct {
metav1.TypeMeta metav1.TypeMeta
// SchedulerName is name of the scheduler, used to select which pods
// will be processed by this scheduler, based on pod's "spec.SchedulerName".
SchedulerName string
// AlgorithmSource specifies the scheduler algorithm source. // AlgorithmSource specifies the scheduler algorithm source.
AlgorithmSource SchedulerAlgorithmSource AlgorithmSource SchedulerAlgorithmSource
@ -97,15 +94,33 @@ type KubeSchedulerConfiguration struct {
// the default value (10s) will be used. // the default value (10s) will be used.
PodMaxBackoffSeconds int64 PodMaxBackoffSeconds int64
// Plugins specify the set of plugins that should be enabled or disabled. Enabled plugins are the // Profiles are scheduling profiles that kube-scheduler supports. Pods can
// ones that should be enabled in addition to the default plugins. Disabled plugins are any of the // choose to be scheduled under a particular profile by setting its associated
// default plugins that should be disabled. // scheduler name. Pods that don't specify any scheduler name are scheduled
// When no enabled or disabled plugin is specified for an extension point, default plugins for // with the "default-scheduler" profile, if present here.
// that extension point will be used if there is any. Profiles []KubeSchedulerProfile
}
// KubeSchedulerProfile is a scheduling profile.
type KubeSchedulerProfile struct {
// SchedulerName is the name of the scheduler associated to this profile.
// If SchedulerName matches with the pod's "spec.schedulerName", then the pod
// is scheduled with this profile.
SchedulerName string
// Plugins specify the set of plugins that should be enabled or disabled.
// Enabled plugins are the ones that should be enabled in addition to the
// default plugins. Disabled plugins are any of the default plugins that
// should be disabled.
// When no enabled or disabled plugin is specified for an extension point,
// default plugins for that extension point will be used if there is any.
// If a QueueSort plugin is specified, the same QueueSort Plugin and
// PluginConfig must be specified for all profiles.
Plugins *Plugins Plugins *Plugins
// PluginConfig is an optional set of custom plugin arguments for each plugin. // PluginConfig is an optional set of custom plugin arguments for each plugin.
// Omitting config args for a plugin is equivalent to using the default config for that plugin. // Omitting config args for a plugin is equivalent to using the default config
// for that plugin.
PluginConfig []PluginConfig PluginConfig []PluginConfig
} }

View File

@ -19,6 +19,7 @@ package v1alpha1
import ( import (
"fmt" "fmt"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/conversion" "k8s.io/apimachinery/pkg/conversion"
"k8s.io/kube-scheduler/config/v1alpha1" "k8s.io/kube-scheduler/config/v1alpha1"
"k8s.io/kubernetes/pkg/scheduler/apis/config" "k8s.io/kubernetes/pkg/scheduler/apis/config"
@ -31,14 +32,40 @@ func Convert_v1alpha1_KubeSchedulerConfiguration_To_config_KubeSchedulerConfigur
if err := autoConvert_v1alpha1_KubeSchedulerConfiguration_To_config_KubeSchedulerConfiguration(in, out, s); err != nil { if err := autoConvert_v1alpha1_KubeSchedulerConfiguration_To_config_KubeSchedulerConfiguration(in, out, s); err != nil {
return err return err
} }
var profile config.KubeSchedulerProfile
if err := metav1.Convert_Pointer_string_To_string(&in.SchedulerName, &profile.SchedulerName, s); err != nil {
return err
}
if in.Plugins != nil {
profile.Plugins = &config.Plugins{}
if err := Convert_v1alpha1_Plugins_To_config_Plugins(in.Plugins, profile.Plugins, s); err != nil {
return err
}
} else {
profile.Plugins = nil
}
if in.PluginConfig != nil {
profile.PluginConfig = make([]config.PluginConfig, len(in.PluginConfig))
for i := range in.PluginConfig {
if err := Convert_v1alpha1_PluginConfig_To_config_PluginConfig(&in.PluginConfig[i], &profile.PluginConfig[i], s); err != nil {
return err
}
}
}
if in.HardPodAffinitySymmetricWeight != nil { if in.HardPodAffinitySymmetricWeight != nil {
args := interpodaffinity.Args{HardPodAffinityWeight: in.HardPodAffinitySymmetricWeight} args := interpodaffinity.Args{HardPodAffinityWeight: in.HardPodAffinitySymmetricWeight}
plCfg := plugins.NewPluginConfig(interpodaffinity.Name, args) plCfg := plugins.NewPluginConfig(interpodaffinity.Name, args)
out.PluginConfig = append(out.PluginConfig, plCfg) profile.PluginConfig = append(profile.PluginConfig, plCfg)
} }
out.Profiles = []config.KubeSchedulerProfile{profile}
return nil return nil
} }
func Convert_config_KubeSchedulerConfiguration_To_v1alpha1_KubeSchedulerConfiguration(in *config.KubeSchedulerConfiguration, out *v1alpha1.KubeSchedulerConfiguration, s conversion.Scope) error {
// Conversion from internal to v1alpha1 is not relevant for kube-scheduler.
return autoConvert_config_KubeSchedulerConfiguration_To_v1alpha1_KubeSchedulerConfiguration(in, out, s)
}
// Convert_v1alpha1_KubeSchedulerLeaderElectionConfiguration_To_config_KubeSchedulerLeaderElectionConfiguration handles deprecated parameters for leader election. // Convert_v1alpha1_KubeSchedulerLeaderElectionConfiguration_To_config_KubeSchedulerLeaderElectionConfiguration handles deprecated parameters for leader election.
func Convert_v1alpha1_KubeSchedulerLeaderElectionConfiguration_To_config_KubeSchedulerLeaderElectionConfiguration(in *v1alpha1.KubeSchedulerLeaderElectionConfiguration, out *config.KubeSchedulerLeaderElectionConfiguration, s conversion.Scope) error { func Convert_v1alpha1_KubeSchedulerLeaderElectionConfiguration_To_config_KubeSchedulerLeaderElectionConfiguration(in *v1alpha1.KubeSchedulerLeaderElectionConfiguration, out *config.KubeSchedulerLeaderElectionConfiguration, s conversion.Scope) error {
if err := autoConvert_v1alpha1_KubeSchedulerLeaderElectionConfiguration_To_config_KubeSchedulerLeaderElectionConfiguration(in, out, s); err != nil { if err := autoConvert_v1alpha1_KubeSchedulerLeaderElectionConfiguration_To_config_KubeSchedulerLeaderElectionConfiguration(in, out, s); err != nil {

View File

@ -30,33 +30,76 @@ import (
"k8s.io/utils/pointer" "k8s.io/utils/pointer"
) )
func TestConvertHardPodAffinitySymmetricWeight(t *testing.T) { func TestConvertKubeSchedulerConfiguration(t *testing.T) {
cases := []struct { cases := []struct {
name string name string
cfg v1alpha1.KubeSchedulerConfiguration cfg v1alpha1.KubeSchedulerConfiguration
want config.KubeSchedulerConfiguration want config.KubeSchedulerConfiguration
}{ }{
{ {
name: "no weight", name: "scheduler name",
},
{
name: "custom weight",
cfg: v1alpha1.KubeSchedulerConfiguration{ cfg: v1alpha1.KubeSchedulerConfiguration{
HardPodAffinitySymmetricWeight: pointer.Int32Ptr(3), SchedulerName: pointer.StringPtr("custom-name"),
}, },
want: config.KubeSchedulerConfiguration{ want: config.KubeSchedulerConfiguration{
PluginConfig: []config.PluginConfig{ Profiles: []config.KubeSchedulerProfile{
{SchedulerName: "custom-name"},
},
},
},
{
name: "plugins and plugin config",
cfg: v1alpha1.KubeSchedulerConfiguration{
Plugins: &v1alpha1.Plugins{
QueueSort: &v1alpha1.PluginSet{
Enabled: []v1alpha1.Plugin{
{Name: "FooPlugin"},
},
},
},
PluginConfig: []v1alpha1.PluginConfig{
{Name: "FooPlugin"},
},
},
want: config.KubeSchedulerConfiguration{
Profiles: []config.KubeSchedulerProfile{
{ {
Name: "InterPodAffinity", Plugins: &config.Plugins{
Args: runtime.Unknown{ QueueSort: &config.PluginSet{
Raw: []byte(`{"hardPodAffinityWeight":3}`), Enabled: []config.Plugin{
{Name: "FooPlugin"},
},
},
},
PluginConfig: []config.PluginConfig{
{Name: "FooPlugin"},
}, },
}, },
}, },
}, },
}, },
{ {
name: "custom weight and existing PluginConfig", name: "custom hard pod affinity weight",
cfg: v1alpha1.KubeSchedulerConfiguration{
HardPodAffinitySymmetricWeight: pointer.Int32Ptr(3),
},
want: config.KubeSchedulerConfiguration{
Profiles: []config.KubeSchedulerProfile{
{
PluginConfig: []config.PluginConfig{
{
Name: "InterPodAffinity",
Args: runtime.Unknown{
Raw: []byte(`{"hardPodAffinityWeight":3}`),
},
},
},
},
},
},
},
{
name: "custom hard pod affinity weight and existing PluginConfig",
cfg: v1alpha1.KubeSchedulerConfiguration{ cfg: v1alpha1.KubeSchedulerConfiguration{
HardPodAffinitySymmetricWeight: pointer.Int32Ptr(3), HardPodAffinitySymmetricWeight: pointer.Int32Ptr(3),
PluginConfig: []v1alpha1.PluginConfig{ PluginConfig: []v1alpha1.PluginConfig{
@ -69,17 +112,21 @@ func TestConvertHardPodAffinitySymmetricWeight(t *testing.T) {
}, },
}, },
want: config.KubeSchedulerConfiguration{ want: config.KubeSchedulerConfiguration{
PluginConfig: []config.PluginConfig{ Profiles: []config.KubeSchedulerProfile{
{ {
Name: "InterPodAffinity", PluginConfig: []config.PluginConfig{
Args: runtime.Unknown{ {
Raw: []byte(`{"hardPodAffinityWeight":5}`), Name: "InterPodAffinity",
}, Args: runtime.Unknown{
}, Raw: []byte(`{"hardPodAffinityWeight":5}`),
{ },
Name: "InterPodAffinity", },
Args: runtime.Unknown{ {
Raw: []byte(`{"hardPodAffinityWeight":3}`), Name: "InterPodAffinity",
Args: runtime.Unknown{
Raw: []byte(`{"hardPodAffinityWeight":3}`),
},
},
}, },
}, },
}, },

View File

@ -38,11 +38,6 @@ func init() {
// RegisterConversions adds conversion functions to the given scheme. // RegisterConversions adds conversion functions to the given scheme.
// Public to allow building arbitrary schemes. // Public to allow building arbitrary schemes.
func RegisterConversions(s *runtime.Scheme) error { func RegisterConversions(s *runtime.Scheme) error {
if err := s.AddGeneratedConversionFunc((*config.KubeSchedulerConfiguration)(nil), (*v1alpha1.KubeSchedulerConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_config_KubeSchedulerConfiguration_To_v1alpha1_KubeSchedulerConfiguration(a.(*config.KubeSchedulerConfiguration), b.(*v1alpha1.KubeSchedulerConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*v1alpha1.Plugin)(nil), (*config.Plugin)(nil), func(a, b interface{}, scope conversion.Scope) error { if err := s.AddGeneratedConversionFunc((*v1alpha1.Plugin)(nil), (*config.Plugin)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_Plugin_To_config_Plugin(a.(*v1alpha1.Plugin), b.(*config.Plugin), scope) return Convert_v1alpha1_Plugin_To_config_Plugin(a.(*v1alpha1.Plugin), b.(*config.Plugin), scope)
}); err != nil { }); err != nil {
@ -113,6 +108,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil { }); err != nil {
return err return err
} }
if err := s.AddConversionFunc((*config.KubeSchedulerConfiguration)(nil), (*v1alpha1.KubeSchedulerConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_config_KubeSchedulerConfiguration_To_v1alpha1_KubeSchedulerConfiguration(a.(*config.KubeSchedulerConfiguration), b.(*v1alpha1.KubeSchedulerConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddConversionFunc((*config.KubeSchedulerLeaderElectionConfiguration)(nil), (*v1alpha1.KubeSchedulerLeaderElectionConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error { if err := s.AddConversionFunc((*config.KubeSchedulerLeaderElectionConfiguration)(nil), (*v1alpha1.KubeSchedulerLeaderElectionConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_config_KubeSchedulerLeaderElectionConfiguration_To_v1alpha1_KubeSchedulerLeaderElectionConfiguration(a.(*config.KubeSchedulerLeaderElectionConfiguration), b.(*v1alpha1.KubeSchedulerLeaderElectionConfiguration), scope) return Convert_config_KubeSchedulerLeaderElectionConfiguration_To_v1alpha1_KubeSchedulerLeaderElectionConfiguration(a.(*config.KubeSchedulerLeaderElectionConfiguration), b.(*v1alpha1.KubeSchedulerLeaderElectionConfiguration), scope)
}); err != nil { }); err != nil {
@ -142,9 +142,7 @@ func RegisterConversions(s *runtime.Scheme) error {
} }
func autoConvert_v1alpha1_KubeSchedulerConfiguration_To_config_KubeSchedulerConfiguration(in *v1alpha1.KubeSchedulerConfiguration, out *config.KubeSchedulerConfiguration, s conversion.Scope) error { func autoConvert_v1alpha1_KubeSchedulerConfiguration_To_config_KubeSchedulerConfiguration(in *v1alpha1.KubeSchedulerConfiguration, out *config.KubeSchedulerConfiguration, s conversion.Scope) error {
if err := v1.Convert_Pointer_string_To_string(&in.SchedulerName, &out.SchedulerName, s); err != nil { // WARNING: in.SchedulerName requires manual conversion: does not exist in peer-type
return err
}
if err := Convert_v1alpha1_SchedulerAlgorithmSource_To_config_SchedulerAlgorithmSource(&in.AlgorithmSource, &out.AlgorithmSource, s); err != nil { if err := Convert_v1alpha1_SchedulerAlgorithmSource_To_config_SchedulerAlgorithmSource(&in.AlgorithmSource, &out.AlgorithmSource, s); err != nil {
return err return err
} }
@ -179,23 +177,12 @@ func autoConvert_v1alpha1_KubeSchedulerConfiguration_To_config_KubeSchedulerConf
if err := v1.Convert_Pointer_int64_To_int64(&in.PodMaxBackoffSeconds, &out.PodMaxBackoffSeconds, s); err != nil { if err := v1.Convert_Pointer_int64_To_int64(&in.PodMaxBackoffSeconds, &out.PodMaxBackoffSeconds, s); err != nil {
return err return err
} }
if in.Plugins != nil { // WARNING: in.Plugins requires manual conversion: does not exist in peer-type
in, out := &in.Plugins, &out.Plugins // WARNING: in.PluginConfig requires manual conversion: does not exist in peer-type
*out = new(config.Plugins)
if err := Convert_v1alpha1_Plugins_To_config_Plugins(*in, *out, s); err != nil {
return err
}
} else {
out.Plugins = nil
}
out.PluginConfig = *(*[]config.PluginConfig)(unsafe.Pointer(&in.PluginConfig))
return nil return nil
} }
func autoConvert_config_KubeSchedulerConfiguration_To_v1alpha1_KubeSchedulerConfiguration(in *config.KubeSchedulerConfiguration, out *v1alpha1.KubeSchedulerConfiguration, s conversion.Scope) error { func autoConvert_config_KubeSchedulerConfiguration_To_v1alpha1_KubeSchedulerConfiguration(in *config.KubeSchedulerConfiguration, out *v1alpha1.KubeSchedulerConfiguration, s conversion.Scope) error {
if err := v1.Convert_string_To_Pointer_string(&in.SchedulerName, &out.SchedulerName, s); err != nil {
return err
}
if err := Convert_config_SchedulerAlgorithmSource_To_v1alpha1_SchedulerAlgorithmSource(&in.AlgorithmSource, &out.AlgorithmSource, s); err != nil { if err := Convert_config_SchedulerAlgorithmSource_To_v1alpha1_SchedulerAlgorithmSource(&in.AlgorithmSource, &out.AlgorithmSource, s); err != nil {
return err return err
} }
@ -229,24 +216,10 @@ func autoConvert_config_KubeSchedulerConfiguration_To_v1alpha1_KubeSchedulerConf
if err := v1.Convert_int64_To_Pointer_int64(&in.PodMaxBackoffSeconds, &out.PodMaxBackoffSeconds, s); err != nil { if err := v1.Convert_int64_To_Pointer_int64(&in.PodMaxBackoffSeconds, &out.PodMaxBackoffSeconds, s); err != nil {
return err return err
} }
if in.Plugins != nil { // WARNING: in.Profiles requires manual conversion: does not exist in peer-type
in, out := &in.Plugins, &out.Plugins
*out = new(v1alpha1.Plugins)
if err := Convert_config_Plugins_To_v1alpha1_Plugins(*in, *out, s); err != nil {
return err
}
} else {
out.Plugins = nil
}
out.PluginConfig = *(*[]v1alpha1.PluginConfig)(unsafe.Pointer(&in.PluginConfig))
return nil return nil
} }
// Convert_config_KubeSchedulerConfiguration_To_v1alpha1_KubeSchedulerConfiguration is an autogenerated conversion function.
func Convert_config_KubeSchedulerConfiguration_To_v1alpha1_KubeSchedulerConfiguration(in *config.KubeSchedulerConfiguration, out *v1alpha1.KubeSchedulerConfiguration, s conversion.Scope) error {
return autoConvert_config_KubeSchedulerConfiguration_To_v1alpha1_KubeSchedulerConfiguration(in, out, s)
}
func autoConvert_v1alpha1_KubeSchedulerLeaderElectionConfiguration_To_config_KubeSchedulerLeaderElectionConfiguration(in *v1alpha1.KubeSchedulerLeaderElectionConfiguration, out *config.KubeSchedulerLeaderElectionConfiguration, s conversion.Scope) error { func autoConvert_v1alpha1_KubeSchedulerLeaderElectionConfiguration_To_config_KubeSchedulerLeaderElectionConfiguration(in *v1alpha1.KubeSchedulerLeaderElectionConfiguration, out *config.KubeSchedulerLeaderElectionConfiguration, s conversion.Scope) error {
if err := componentbaseconfigv1alpha1.Convert_v1alpha1_LeaderElectionConfiguration_To_config_LeaderElectionConfiguration(&in.LeaderElectionConfiguration, &out.LeaderElectionConfiguration, s); err != nil { if err := componentbaseconfigv1alpha1.Convert_v1alpha1_LeaderElectionConfiguration_To_config_LeaderElectionConfiguration(&in.LeaderElectionConfiguration, &out.LeaderElectionConfiguration, s); err != nil {
return err return err

View File

@ -21,6 +21,7 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/component-base/config/v1alpha1:go_default_library", "//staging/src/k8s.io/component-base/config/v1alpha1:go_default_library",
"//staging/src/k8s.io/kube-scheduler/config/v1alpha2:go_default_library", "//staging/src/k8s.io/kube-scheduler/config/v1alpha2:go_default_library",
"//vendor/k8s.io/utils/pointer:go_default_library",
], ],
) )
@ -32,6 +33,7 @@ go_test(
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/component-base/config/v1alpha1:go_default_library", "//staging/src/k8s.io/component-base/config/v1alpha1:go_default_library",
"//staging/src/k8s.io/kube-scheduler/config/v1alpha2:go_default_library", "//staging/src/k8s.io/kube-scheduler/config/v1alpha2:go_default_library",
"//vendor/github.com/google/go-cmp/cmp:go_default_library",
"//vendor/k8s.io/utils/pointer:go_default_library", "//vendor/k8s.io/utils/pointer:go_default_library",
], ],
) )

View File

@ -24,6 +24,7 @@ import (
componentbaseconfigv1alpha1 "k8s.io/component-base/config/v1alpha1" componentbaseconfigv1alpha1 "k8s.io/component-base/config/v1alpha1"
"k8s.io/kube-scheduler/config/v1alpha2" "k8s.io/kube-scheduler/config/v1alpha2"
"k8s.io/kubernetes/pkg/scheduler/apis/config" "k8s.io/kubernetes/pkg/scheduler/apis/config"
"k8s.io/utils/pointer"
// this package shouldn't really depend on other k8s.io/kubernetes code // this package shouldn't really depend on other k8s.io/kubernetes code
api "k8s.io/kubernetes/pkg/apis/core" api "k8s.io/kubernetes/pkg/apis/core"
@ -36,9 +37,13 @@ func addDefaultingFuncs(scheme *runtime.Scheme) error {
// SetDefaults_KubeSchedulerConfiguration sets additional defaults // SetDefaults_KubeSchedulerConfiguration sets additional defaults
func SetDefaults_KubeSchedulerConfiguration(obj *v1alpha2.KubeSchedulerConfiguration) { func SetDefaults_KubeSchedulerConfiguration(obj *v1alpha2.KubeSchedulerConfiguration) {
if obj.SchedulerName == nil { if len(obj.Profiles) == 0 {
val := api.DefaultSchedulerName obj.Profiles = append(obj.Profiles, v1alpha2.KubeSchedulerProfile{})
obj.SchedulerName = &val }
// Only apply a default scheduler name when there is a single profile.
// Validation will ensure that every profile has a non-empty unique name.
if len(obj.Profiles) == 1 && obj.Profiles[0].SchedulerName == nil {
obj.Profiles[0].SchedulerName = pointer.StringPtr(api.DefaultSchedulerName)
} }
if obj.AlgorithmSource.Policy == nil && if obj.AlgorithmSource.Policy == nil &&

View File

@ -17,10 +17,10 @@ limitations under the License.
package v1alpha2 package v1alpha2
import ( import (
"reflect"
"testing" "testing"
"time" "time"
"github.com/google/go-cmp/cmp"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
componentbaseconfig "k8s.io/component-base/config/v1alpha1" componentbaseconfig "k8s.io/component-base/config/v1alpha1"
"k8s.io/kube-scheduler/config/v1alpha2" "k8s.io/kube-scheduler/config/v1alpha2"
@ -38,7 +38,6 @@ func TestSchedulerDefaults(t *testing.T) {
name: "empty config", name: "empty config",
config: &v1alpha2.KubeSchedulerConfiguration{}, config: &v1alpha2.KubeSchedulerConfiguration{},
expected: &v1alpha2.KubeSchedulerConfiguration{ expected: &v1alpha2.KubeSchedulerConfiguration{
SchedulerName: pointer.StringPtr("default-scheduler"),
AlgorithmSource: v1alpha2.SchedulerAlgorithmSource{Provider: pointer.StringPtr("DefaultProvider")}, AlgorithmSource: v1alpha2.SchedulerAlgorithmSource{Provider: pointer.StringPtr("DefaultProvider")},
HealthzBindAddress: pointer.StringPtr("0.0.0.0:10251"), HealthzBindAddress: pointer.StringPtr("0.0.0.0:10251"),
MetricsBindAddress: pointer.StringPtr("0.0.0.0:10251"), MetricsBindAddress: pointer.StringPtr("0.0.0.0:10251"),
@ -67,7 +66,128 @@ func TestSchedulerDefaults(t *testing.T) {
BindTimeoutSeconds: pointer.Int64Ptr(600), BindTimeoutSeconds: pointer.Int64Ptr(600),
PodInitialBackoffSeconds: pointer.Int64Ptr(1), PodInitialBackoffSeconds: pointer.Int64Ptr(1),
PodMaxBackoffSeconds: pointer.Int64Ptr(10), PodMaxBackoffSeconds: pointer.Int64Ptr(10),
Plugins: nil, Profiles: []v1alpha2.KubeSchedulerProfile{
{SchedulerName: pointer.StringPtr("default-scheduler")},
},
},
},
{
name: "no scheduler name",
config: &v1alpha2.KubeSchedulerConfiguration{
Profiles: []v1alpha2.KubeSchedulerProfile{
{
PluginConfig: []v1alpha2.PluginConfig{
{Name: "FooPlugin"},
},
},
},
},
expected: &v1alpha2.KubeSchedulerConfiguration{
AlgorithmSource: v1alpha2.SchedulerAlgorithmSource{Provider: pointer.StringPtr("DefaultProvider")},
HealthzBindAddress: pointer.StringPtr("0.0.0.0:10251"),
MetricsBindAddress: pointer.StringPtr("0.0.0.0:10251"),
DebuggingConfiguration: componentbaseconfig.DebuggingConfiguration{
EnableProfiling: &enable,
EnableContentionProfiling: &enable,
},
LeaderElection: v1alpha2.KubeSchedulerLeaderElectionConfiguration{
LeaderElectionConfiguration: componentbaseconfig.LeaderElectionConfiguration{
LeaderElect: pointer.BoolPtr(true),
LeaseDuration: metav1.Duration{Duration: 15 * time.Second},
RenewDeadline: metav1.Duration{Duration: 10 * time.Second},
RetryPeriod: metav1.Duration{Duration: 2 * time.Second},
ResourceLock: "endpointsleases",
ResourceNamespace: "kube-system",
ResourceName: "kube-scheduler",
},
},
ClientConnection: componentbaseconfig.ClientConnectionConfiguration{
QPS: 50,
Burst: 100,
ContentType: "application/vnd.kubernetes.protobuf",
},
DisablePreemption: pointer.BoolPtr(false),
PercentageOfNodesToScore: pointer.Int32Ptr(0),
BindTimeoutSeconds: pointer.Int64Ptr(600),
PodInitialBackoffSeconds: pointer.Int64Ptr(1),
PodMaxBackoffSeconds: pointer.Int64Ptr(10),
Profiles: []v1alpha2.KubeSchedulerProfile{
{
SchedulerName: pointer.StringPtr("default-scheduler"),
PluginConfig: []v1alpha2.PluginConfig{
{Name: "FooPlugin"},
},
},
},
},
},
{
name: "two profiles",
config: &v1alpha2.KubeSchedulerConfiguration{
Profiles: []v1alpha2.KubeSchedulerProfile{
{
PluginConfig: []v1alpha2.PluginConfig{
{Name: "FooPlugin"},
},
},
{
SchedulerName: pointer.StringPtr("custom-scheduler"),
Plugins: &v1alpha2.Plugins{
Bind: &v1alpha2.PluginSet{
Enabled: []v1alpha2.Plugin{
{Name: "BarPlugin"},
},
},
},
},
},
},
expected: &v1alpha2.KubeSchedulerConfiguration{
AlgorithmSource: v1alpha2.SchedulerAlgorithmSource{Provider: pointer.StringPtr("DefaultProvider")},
HealthzBindAddress: pointer.StringPtr("0.0.0.0:10251"),
MetricsBindAddress: pointer.StringPtr("0.0.0.0:10251"),
DebuggingConfiguration: componentbaseconfig.DebuggingConfiguration{
EnableProfiling: &enable,
EnableContentionProfiling: &enable,
},
LeaderElection: v1alpha2.KubeSchedulerLeaderElectionConfiguration{
LeaderElectionConfiguration: componentbaseconfig.LeaderElectionConfiguration{
LeaderElect: pointer.BoolPtr(true),
LeaseDuration: metav1.Duration{Duration: 15 * time.Second},
RenewDeadline: metav1.Duration{Duration: 10 * time.Second},
RetryPeriod: metav1.Duration{Duration: 2 * time.Second},
ResourceLock: "endpointsleases",
ResourceNamespace: "kube-system",
ResourceName: "kube-scheduler",
},
},
ClientConnection: componentbaseconfig.ClientConnectionConfiguration{
QPS: 50,
Burst: 100,
ContentType: "application/vnd.kubernetes.protobuf",
},
DisablePreemption: pointer.BoolPtr(false),
PercentageOfNodesToScore: pointer.Int32Ptr(0),
BindTimeoutSeconds: pointer.Int64Ptr(600),
PodInitialBackoffSeconds: pointer.Int64Ptr(1),
PodMaxBackoffSeconds: pointer.Int64Ptr(10),
Profiles: []v1alpha2.KubeSchedulerProfile{
{
PluginConfig: []v1alpha2.PluginConfig{
{Name: "FooPlugin"},
},
},
{
SchedulerName: pointer.StringPtr("custom-scheduler"),
Plugins: &v1alpha2.Plugins{
Bind: &v1alpha2.PluginSet{
Enabled: []v1alpha2.Plugin{
{Name: "BarPlugin"},
},
},
},
},
},
}, },
}, },
{ {
@ -77,7 +197,6 @@ func TestSchedulerDefaults(t *testing.T) {
HealthzBindAddress: pointer.StringPtr("1.2.3.4"), HealthzBindAddress: pointer.StringPtr("1.2.3.4"),
}, },
expected: &v1alpha2.KubeSchedulerConfiguration{ expected: &v1alpha2.KubeSchedulerConfiguration{
SchedulerName: pointer.StringPtr("default-scheduler"),
AlgorithmSource: v1alpha2.SchedulerAlgorithmSource{Provider: pointer.StringPtr("DefaultProvider")}, AlgorithmSource: v1alpha2.SchedulerAlgorithmSource{Provider: pointer.StringPtr("DefaultProvider")},
HealthzBindAddress: pointer.StringPtr("1.2.3.4:10251"), HealthzBindAddress: pointer.StringPtr("1.2.3.4:10251"),
MetricsBindAddress: pointer.StringPtr("1.2.3.4:10251"), MetricsBindAddress: pointer.StringPtr("1.2.3.4:10251"),
@ -106,7 +225,9 @@ func TestSchedulerDefaults(t *testing.T) {
BindTimeoutSeconds: pointer.Int64Ptr(600), BindTimeoutSeconds: pointer.Int64Ptr(600),
PodInitialBackoffSeconds: pointer.Int64Ptr(1), PodInitialBackoffSeconds: pointer.Int64Ptr(1),
PodMaxBackoffSeconds: pointer.Int64Ptr(10), PodMaxBackoffSeconds: pointer.Int64Ptr(10),
Plugins: nil, Profiles: []v1alpha2.KubeSchedulerProfile{
{SchedulerName: pointer.StringPtr("default-scheduler")},
},
}, },
}, },
{ {
@ -116,7 +237,6 @@ func TestSchedulerDefaults(t *testing.T) {
HealthzBindAddress: pointer.StringPtr(":12345"), HealthzBindAddress: pointer.StringPtr(":12345"),
}, },
expected: &v1alpha2.KubeSchedulerConfiguration{ expected: &v1alpha2.KubeSchedulerConfiguration{
SchedulerName: pointer.StringPtr("default-scheduler"),
AlgorithmSource: v1alpha2.SchedulerAlgorithmSource{Provider: pointer.StringPtr("DefaultProvider")}, AlgorithmSource: v1alpha2.SchedulerAlgorithmSource{Provider: pointer.StringPtr("DefaultProvider")},
HealthzBindAddress: pointer.StringPtr("0.0.0.0:12345"), HealthzBindAddress: pointer.StringPtr("0.0.0.0:12345"),
MetricsBindAddress: pointer.StringPtr("0.0.0.0:12345"), MetricsBindAddress: pointer.StringPtr("0.0.0.0:12345"),
@ -145,15 +265,17 @@ func TestSchedulerDefaults(t *testing.T) {
BindTimeoutSeconds: pointer.Int64Ptr(600), BindTimeoutSeconds: pointer.Int64Ptr(600),
PodInitialBackoffSeconds: pointer.Int64Ptr(1), PodInitialBackoffSeconds: pointer.Int64Ptr(1),
PodMaxBackoffSeconds: pointer.Int64Ptr(10), PodMaxBackoffSeconds: pointer.Int64Ptr(10),
Plugins: nil, Profiles: []v1alpha2.KubeSchedulerProfile{
{SchedulerName: pointer.StringPtr("default-scheduler")},
},
}, },
}, },
} }
for _, tc := range tests { for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
SetDefaults_KubeSchedulerConfiguration(tc.config) SetDefaults_KubeSchedulerConfiguration(tc.config)
if !reflect.DeepEqual(tc.expected, tc.config) { if diff := cmp.Diff(tc.expected, tc.config); diff != "" {
t.Errorf("Expected:\n%#v\n\nGot:\n%#v", tc.expected, tc.config) t.Errorf("Got unexpected defaults (-want, +got):\n%s", diff)
} }
}) })
} }

View File

@ -58,6 +58,16 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil { }); err != nil {
return err return err
} }
if err := s.AddGeneratedConversionFunc((*v1alpha2.KubeSchedulerProfile)(nil), (*config.KubeSchedulerProfile)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha2_KubeSchedulerProfile_To_config_KubeSchedulerProfile(a.(*v1alpha2.KubeSchedulerProfile), b.(*config.KubeSchedulerProfile), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*config.KubeSchedulerProfile)(nil), (*v1alpha2.KubeSchedulerProfile)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_config_KubeSchedulerProfile_To_v1alpha2_KubeSchedulerProfile(a.(*config.KubeSchedulerProfile), b.(*v1alpha2.KubeSchedulerProfile), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*v1alpha2.Plugin)(nil), (*config.Plugin)(nil), func(a, b interface{}, scope conversion.Scope) error { if err := s.AddGeneratedConversionFunc((*v1alpha2.Plugin)(nil), (*config.Plugin)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha2_Plugin_To_config_Plugin(a.(*v1alpha2.Plugin), b.(*config.Plugin), scope) return Convert_v1alpha2_Plugin_To_config_Plugin(a.(*v1alpha2.Plugin), b.(*config.Plugin), scope)
}); err != nil { }); err != nil {
@ -142,9 +152,6 @@ func RegisterConversions(s *runtime.Scheme) error {
} }
func autoConvert_v1alpha2_KubeSchedulerConfiguration_To_config_KubeSchedulerConfiguration(in *v1alpha2.KubeSchedulerConfiguration, out *config.KubeSchedulerConfiguration, s conversion.Scope) error { func autoConvert_v1alpha2_KubeSchedulerConfiguration_To_config_KubeSchedulerConfiguration(in *v1alpha2.KubeSchedulerConfiguration, out *config.KubeSchedulerConfiguration, s conversion.Scope) error {
if err := v1.Convert_Pointer_string_To_string(&in.SchedulerName, &out.SchedulerName, s); err != nil {
return err
}
if err := Convert_v1alpha2_SchedulerAlgorithmSource_To_config_SchedulerAlgorithmSource(&in.AlgorithmSource, &out.AlgorithmSource, s); err != nil { if err := Convert_v1alpha2_SchedulerAlgorithmSource_To_config_SchedulerAlgorithmSource(&in.AlgorithmSource, &out.AlgorithmSource, s); err != nil {
return err return err
} }
@ -178,16 +185,17 @@ func autoConvert_v1alpha2_KubeSchedulerConfiguration_To_config_KubeSchedulerConf
if err := v1.Convert_Pointer_int64_To_int64(&in.PodMaxBackoffSeconds, &out.PodMaxBackoffSeconds, s); err != nil { if err := v1.Convert_Pointer_int64_To_int64(&in.PodMaxBackoffSeconds, &out.PodMaxBackoffSeconds, s); err != nil {
return err return err
} }
if in.Plugins != nil { if in.Profiles != nil {
in, out := &in.Plugins, &out.Plugins in, out := &in.Profiles, &out.Profiles
*out = new(config.Plugins) *out = make([]config.KubeSchedulerProfile, len(*in))
if err := Convert_v1alpha2_Plugins_To_config_Plugins(*in, *out, s); err != nil { for i := range *in {
return err if err := Convert_v1alpha2_KubeSchedulerProfile_To_config_KubeSchedulerProfile(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
} }
} else { } else {
out.Plugins = nil out.Profiles = nil
} }
out.PluginConfig = *(*[]config.PluginConfig)(unsafe.Pointer(&in.PluginConfig))
return nil return nil
} }
@ -197,9 +205,6 @@ func Convert_v1alpha2_KubeSchedulerConfiguration_To_config_KubeSchedulerConfigur
} }
func autoConvert_config_KubeSchedulerConfiguration_To_v1alpha2_KubeSchedulerConfiguration(in *config.KubeSchedulerConfiguration, out *v1alpha2.KubeSchedulerConfiguration, s conversion.Scope) error { func autoConvert_config_KubeSchedulerConfiguration_To_v1alpha2_KubeSchedulerConfiguration(in *config.KubeSchedulerConfiguration, out *v1alpha2.KubeSchedulerConfiguration, s conversion.Scope) error {
if err := v1.Convert_string_To_Pointer_string(&in.SchedulerName, &out.SchedulerName, s); err != nil {
return err
}
if err := Convert_config_SchedulerAlgorithmSource_To_v1alpha2_SchedulerAlgorithmSource(&in.AlgorithmSource, &out.AlgorithmSource, s); err != nil { if err := Convert_config_SchedulerAlgorithmSource_To_v1alpha2_SchedulerAlgorithmSource(&in.AlgorithmSource, &out.AlgorithmSource, s); err != nil {
return err return err
} }
@ -233,16 +238,17 @@ func autoConvert_config_KubeSchedulerConfiguration_To_v1alpha2_KubeSchedulerConf
if err := v1.Convert_int64_To_Pointer_int64(&in.PodMaxBackoffSeconds, &out.PodMaxBackoffSeconds, s); err != nil { if err := v1.Convert_int64_To_Pointer_int64(&in.PodMaxBackoffSeconds, &out.PodMaxBackoffSeconds, s); err != nil {
return err return err
} }
if in.Plugins != nil { if in.Profiles != nil {
in, out := &in.Plugins, &out.Plugins in, out := &in.Profiles, &out.Profiles
*out = new(v1alpha2.Plugins) *out = make([]v1alpha2.KubeSchedulerProfile, len(*in))
if err := Convert_config_Plugins_To_v1alpha2_Plugins(*in, *out, s); err != nil { for i := range *in {
return err if err := Convert_config_KubeSchedulerProfile_To_v1alpha2_KubeSchedulerProfile(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
} }
} else { } else {
out.Plugins = nil out.Profiles = nil
} }
out.PluginConfig = *(*[]v1alpha2.PluginConfig)(unsafe.Pointer(&in.PluginConfig))
return nil return nil
} }
@ -275,6 +281,50 @@ func Convert_config_KubeSchedulerLeaderElectionConfiguration_To_v1alpha2_KubeSch
return autoConvert_config_KubeSchedulerLeaderElectionConfiguration_To_v1alpha2_KubeSchedulerLeaderElectionConfiguration(in, out, s) return autoConvert_config_KubeSchedulerLeaderElectionConfiguration_To_v1alpha2_KubeSchedulerLeaderElectionConfiguration(in, out, s)
} }
func autoConvert_v1alpha2_KubeSchedulerProfile_To_config_KubeSchedulerProfile(in *v1alpha2.KubeSchedulerProfile, out *config.KubeSchedulerProfile, s conversion.Scope) error {
if err := v1.Convert_Pointer_string_To_string(&in.SchedulerName, &out.SchedulerName, s); err != nil {
return err
}
if in.Plugins != nil {
in, out := &in.Plugins, &out.Plugins
*out = new(config.Plugins)
if err := Convert_v1alpha2_Plugins_To_config_Plugins(*in, *out, s); err != nil {
return err
}
} else {
out.Plugins = nil
}
out.PluginConfig = *(*[]config.PluginConfig)(unsafe.Pointer(&in.PluginConfig))
return nil
}
// Convert_v1alpha2_KubeSchedulerProfile_To_config_KubeSchedulerProfile is an autogenerated conversion function.
func Convert_v1alpha2_KubeSchedulerProfile_To_config_KubeSchedulerProfile(in *v1alpha2.KubeSchedulerProfile, out *config.KubeSchedulerProfile, s conversion.Scope) error {
return autoConvert_v1alpha2_KubeSchedulerProfile_To_config_KubeSchedulerProfile(in, out, s)
}
func autoConvert_config_KubeSchedulerProfile_To_v1alpha2_KubeSchedulerProfile(in *config.KubeSchedulerProfile, out *v1alpha2.KubeSchedulerProfile, s conversion.Scope) error {
if err := v1.Convert_string_To_Pointer_string(&in.SchedulerName, &out.SchedulerName, s); err != nil {
return err
}
if in.Plugins != nil {
in, out := &in.Plugins, &out.Plugins
*out = new(v1alpha2.Plugins)
if err := Convert_config_Plugins_To_v1alpha2_Plugins(*in, *out, s); err != nil {
return err
}
} else {
out.Plugins = nil
}
out.PluginConfig = *(*[]v1alpha2.PluginConfig)(unsafe.Pointer(&in.PluginConfig))
return nil
}
// Convert_config_KubeSchedulerProfile_To_v1alpha2_KubeSchedulerProfile is an autogenerated conversion function.
func Convert_config_KubeSchedulerProfile_To_v1alpha2_KubeSchedulerProfile(in *config.KubeSchedulerProfile, out *v1alpha2.KubeSchedulerProfile, s conversion.Scope) error {
return autoConvert_config_KubeSchedulerProfile_To_v1alpha2_KubeSchedulerProfile(in, out, s)
}
func autoConvert_v1alpha2_Plugin_To_config_Plugin(in *v1alpha2.Plugin, out *config.Plugin, s conversion.Scope) error { func autoConvert_v1alpha2_Plugin_To_config_Plugin(in *v1alpha2.Plugin, out *config.Plugin, s conversion.Scope) error {
out.Name = in.Name out.Name = in.Name
if err := v1.Convert_Pointer_int32_To_int32(&in.Weight, &out.Weight, s); err != nil { if err := v1.Convert_Pointer_int32_To_int32(&in.Weight, &out.Weight, s); err != nil {

View File

@ -14,6 +14,7 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/util/validation:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/validation:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
"//staging/src/k8s.io/component-base/config/validation:go_default_library", "//staging/src/k8s.io/component-base/config/validation:go_default_library",
"//vendor/github.com/google/go-cmp/cmp:go_default_library",
], ],
) )

View File

@ -20,6 +20,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"github.com/google/go-cmp/cmp"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
utilerrors "k8s.io/apimachinery/pkg/util/errors" utilerrors "k8s.io/apimachinery/pkg/util/errors"
"k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/sets"
@ -34,9 +35,23 @@ import (
func ValidateKubeSchedulerConfiguration(cc *config.KubeSchedulerConfiguration) field.ErrorList { func ValidateKubeSchedulerConfiguration(cc *config.KubeSchedulerConfiguration) field.ErrorList {
allErrs := field.ErrorList{} allErrs := field.ErrorList{}
allErrs = append(allErrs, componentbasevalidation.ValidateClientConnectionConfiguration(&cc.ClientConnection, field.NewPath("clientConnection"))...) allErrs = append(allErrs, componentbasevalidation.ValidateClientConnectionConfiguration(&cc.ClientConnection, field.NewPath("clientConnection"))...)
allErrs = append(allErrs, ValidateKubeSchedulerLeaderElectionConfiguration(&cc.LeaderElection, field.NewPath("leaderElection"))...) allErrs = append(allErrs, validateKubeSchedulerLeaderElectionConfiguration(field.NewPath("leaderElection"), &cc.LeaderElection)...)
if len(cc.SchedulerName) == 0 {
allErrs = append(allErrs, field.Required(field.NewPath("schedulerName"), "")) profilesPath := field.NewPath("profiles")
if len(cc.Profiles) == 0 {
allErrs = append(allErrs, field.Required(profilesPath, ""))
} else {
existingProfiles := make(map[string]int, len(cc.Profiles))
for i := range cc.Profiles {
profile := &cc.Profiles[i]
path := profilesPath.Index(i)
allErrs = append(allErrs, validateKubeSchedulerProfile(path, profile)...)
if idx, ok := existingProfiles[profile.SchedulerName]; ok {
allErrs = append(allErrs, field.Duplicate(path.Child("schedulerName"), profilesPath.Index(idx).Child("schedulerName")))
}
existingProfiles[profile.SchedulerName] = i
}
allErrs = append(allErrs, validateCommonQueueSort(profilesPath, cc.Profiles)...)
} }
for _, msg := range validation.IsValidSocketAddr(cc.HealthzBindAddress) { for _, msg := range validation.IsValidSocketAddr(cc.HealthzBindAddress) {
allErrs = append(allErrs, field.Invalid(field.NewPath("healthzBindAddress"), cc.HealthzBindAddress, msg)) allErrs = append(allErrs, field.Invalid(field.NewPath("healthzBindAddress"), cc.HealthzBindAddress, msg))
@ -59,13 +74,39 @@ func ValidateKubeSchedulerConfiguration(cc *config.KubeSchedulerConfiguration) f
return allErrs return allErrs
} }
// ValidateKubeSchedulerLeaderElectionConfiguration ensures validation of the KubeSchedulerLeaderElectionConfiguration struct func validateKubeSchedulerProfile(path *field.Path, profile *config.KubeSchedulerProfile) field.ErrorList {
func ValidateKubeSchedulerLeaderElectionConfiguration(cc *config.KubeSchedulerLeaderElectionConfiguration, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{}
if len(profile.SchedulerName) == 0 {
allErrs = append(allErrs, field.Required(path.Child("schedulerName"), ""))
}
return allErrs
}
func validateCommonQueueSort(path *field.Path, profiles []config.KubeSchedulerProfile) field.ErrorList {
allErrs := field.ErrorList{}
var canon *config.PluginSet
if profiles[0].Plugins != nil {
canon = profiles[0].Plugins.QueueSort
}
for i := 1; i < len(profiles); i++ {
var curr *config.PluginSet
if profiles[i].Plugins != nil {
curr = profiles[i].Plugins.QueueSort
}
if !cmp.Equal(canon, curr) {
allErrs = append(allErrs, field.Invalid(path.Index(i).Child("plugins", "queueSort"), curr, "has to match for all profiles"))
}
}
// TODO(#88093): Validate that all plugin configs for the queue sort extension match.
return allErrs
}
func validateKubeSchedulerLeaderElectionConfiguration(fldPath *field.Path, cc *config.KubeSchedulerLeaderElectionConfiguration) field.ErrorList {
allErrs := field.ErrorList{} allErrs := field.ErrorList{}
if !cc.LeaderElectionConfiguration.LeaderElect { if !cc.LeaderElectionConfiguration.LeaderElect {
return allErrs return allErrs
} }
allErrs = append(allErrs, componentbasevalidation.ValidateLeaderElectionConfiguration(&cc.LeaderElectionConfiguration, field.NewPath("leaderElectionConfiguration"))...) allErrs = append(allErrs, componentbasevalidation.ValidateLeaderElectionConfiguration(&cc.LeaderElectionConfiguration, fldPath)...)
return allErrs return allErrs
} }

View File

@ -32,7 +32,6 @@ func TestValidateKubeSchedulerConfiguration(t *testing.T) {
podInitialBackoffSeconds := int64(1) podInitialBackoffSeconds := int64(1)
podMaxBackoffSeconds := int64(1) podMaxBackoffSeconds := int64(1)
validConfig := &config.KubeSchedulerConfiguration{ validConfig := &config.KubeSchedulerConfiguration{
SchedulerName: "me",
HealthzBindAddress: "0.0.0.0:10254", HealthzBindAddress: "0.0.0.0:10254",
MetricsBindAddress: "0.0.0.0:10254", MetricsBindAddress: "0.0.0.0:10254",
ClientConnection: componentbaseconfig.ClientConnectionConfiguration{ ClientConnection: componentbaseconfig.ClientConnectionConfiguration{
@ -64,6 +63,30 @@ func TestValidateKubeSchedulerConfiguration(t *testing.T) {
PodMaxBackoffSeconds: podMaxBackoffSeconds, PodMaxBackoffSeconds: podMaxBackoffSeconds,
BindTimeoutSeconds: testTimeout, BindTimeoutSeconds: testTimeout,
PercentageOfNodesToScore: 35, PercentageOfNodesToScore: 35,
Profiles: []config.KubeSchedulerProfile{
{
SchedulerName: "me",
Plugins: &config.Plugins{
QueueSort: &config.PluginSet{
Enabled: []config.Plugin{{Name: "CustomSort"}},
},
Score: &config.PluginSet{
Disabled: []config.Plugin{{Name: "*"}},
},
},
},
{
SchedulerName: "other",
Plugins: &config.Plugins{
QueueSort: &config.PluginSet{
Enabled: []config.Plugin{{Name: "CustomSort"}},
},
Bind: &config.PluginSet{
Enabled: []config.Plugin{{Name: "CustomBind"}},
},
},
},
},
} }
resourceNameNotSet := validConfig.DeepCopy() resourceNameNotSet := validConfig.DeepCopy()
@ -91,6 +114,18 @@ func TestValidateKubeSchedulerConfiguration(t *testing.T) {
percentageOfNodesToScore101 := validConfig.DeepCopy() percentageOfNodesToScore101 := validConfig.DeepCopy()
percentageOfNodesToScore101.PercentageOfNodesToScore = int32(101) percentageOfNodesToScore101.PercentageOfNodesToScore = int32(101)
schedulerNameNotSet := validConfig.DeepCopy()
schedulerNameNotSet.Profiles[1].SchedulerName = ""
repeatedSchedulerName := validConfig.DeepCopy()
repeatedSchedulerName.Profiles[0].SchedulerName = "other"
differentQueueSort := validConfig.DeepCopy()
differentQueueSort.Profiles[1].Plugins.QueueSort.Enabled[0].Name = "AnotherSort"
oneEmptyQueueSort := validConfig.DeepCopy()
oneEmptyQueueSort.Profiles[0].Plugins = nil
scenarios := map[string]struct { scenarios := map[string]struct {
expectedToFail bool expectedToFail bool
config *config.KubeSchedulerConfiguration config *config.KubeSchedulerConfiguration
@ -127,16 +162,34 @@ func TestValidateKubeSchedulerConfiguration(t *testing.T) {
expectedToFail: true, expectedToFail: true,
config: percentageOfNodesToScore101, config: percentageOfNodesToScore101,
}, },
"scheduler-name-not-set": {
expectedToFail: true,
config: schedulerNameNotSet,
},
"repeated-scheduler-name": {
expectedToFail: true,
config: repeatedSchedulerName,
},
"different-queue-sort": {
expectedToFail: true,
config: differentQueueSort,
},
"one-empty-queue-sort": {
expectedToFail: true,
config: oneEmptyQueueSort,
},
} }
for name, scenario := range scenarios { for name, scenario := range scenarios {
errs := ValidateKubeSchedulerConfiguration(scenario.config) t.Run(name, func(t *testing.T) {
if len(errs) == 0 && scenario.expectedToFail { errs := ValidateKubeSchedulerConfiguration(scenario.config)
t.Errorf("Unexpected success for scenario: %s", name) if len(errs) == 0 && scenario.expectedToFail {
} t.Error("Unexpected success")
if len(errs) > 0 && !scenario.expectedToFail { }
t.Errorf("Unexpected failure for scenario: %s - %+v", name, errs) if len(errs) > 0 && !scenario.expectedToFail {
} t.Errorf("Unexpected failure: %+v", errs)
}
})
} }
} }

View File

@ -105,14 +105,9 @@ func (in *KubeSchedulerConfiguration) DeepCopyInto(out *KubeSchedulerConfigurati
out.LeaderElection = in.LeaderElection out.LeaderElection = in.LeaderElection
out.ClientConnection = in.ClientConnection out.ClientConnection = in.ClientConnection
out.DebuggingConfiguration = in.DebuggingConfiguration out.DebuggingConfiguration = in.DebuggingConfiguration
if in.Plugins != nil { if in.Profiles != nil {
in, out := &in.Plugins, &out.Plugins in, out := &in.Profiles, &out.Profiles
*out = new(Plugins) *out = make([]KubeSchedulerProfile, len(*in))
(*in).DeepCopyInto(*out)
}
if in.PluginConfig != nil {
in, out := &in.PluginConfig, &out.PluginConfig
*out = make([]PluginConfig, len(*in))
for i := range *in { for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i]) (*in)[i].DeepCopyInto(&(*out)[i])
} }
@ -155,6 +150,34 @@ func (in *KubeSchedulerLeaderElectionConfiguration) DeepCopy() *KubeSchedulerLea
return out return out
} }
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *KubeSchedulerProfile) DeepCopyInto(out *KubeSchedulerProfile) {
*out = *in
if in.Plugins != nil {
in, out := &in.Plugins, &out.Plugins
*out = new(Plugins)
(*in).DeepCopyInto(*out)
}
if in.PluginConfig != nil {
in, out := &in.PluginConfig, &out.PluginConfig
*out = make([]PluginConfig, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeSchedulerProfile.
func (in *KubeSchedulerProfile) DeepCopy() *KubeSchedulerProfile {
if in == nil {
return nil
}
out := new(KubeSchedulerProfile)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *LabelPreference) DeepCopyInto(out *LabelPreference) { func (in *LabelPreference) DeepCopyInto(out *LabelPreference) {
*out = *in *out = *in

View File

@ -39,9 +39,6 @@ const (
type KubeSchedulerConfiguration struct { type KubeSchedulerConfiguration struct {
metav1.TypeMeta `json:",inline"` metav1.TypeMeta `json:",inline"`
// SchedulerName is name of the scheduler, used to select which pods
// will be processed by this scheduler, based on pod's "spec.SchedulerName".
SchedulerName *string `json:"schedulerName,omitempty"`
// AlgorithmSource specifies the scheduler algorithm source. // AlgorithmSource specifies the scheduler algorithm source.
AlgorithmSource SchedulerAlgorithmSource `json:"algorithmSource"` AlgorithmSource SchedulerAlgorithmSource `json:"algorithmSource"`
@ -90,15 +87,35 @@ type KubeSchedulerConfiguration struct {
// the default value (10s) will be used. // the default value (10s) will be used.
PodMaxBackoffSeconds *int64 `json:"podMaxBackoffSeconds"` PodMaxBackoffSeconds *int64 `json:"podMaxBackoffSeconds"`
// Plugins specify the set of plugins that should be enabled or disabled. Enabled plugins are the // Profiles are scheduling profiles that kube-scheduler supports. Pods can
// ones that should be enabled in addition to the default plugins. Disabled plugins are any of the // choose to be scheduled under a particular profile by setting its associated
// default plugins that should be disabled. // scheduler name. Pods that don't specify any scheduler name are scheduled
// When no enabled or disabled plugin is specified for an extension point, default plugins for // with the "default-scheduler" profile, if present here.
// that extension point will be used if there is any. // +listType=map
// +listMapKey=schedulerName
Profiles []KubeSchedulerProfile `json:"profiles"`
}
// KubeSchedulerProfile is a scheduling profile.
type KubeSchedulerProfile struct {
// SchedulerName is the name of the scheduler associated to this profile.
// If SchedulerName matches with the pod's "spec.schedulerName", then the pod
// is scheduled with this profile.
SchedulerName *string `json:"schedulerName,omitempty"`
// Plugins specify the set of plugins that should be enabled or disabled.
// Enabled plugins are the ones that should be enabled in addition to the
// default plugins. Disabled plugins are any of the default plugins that
// should be disabled.
// When no enabled or disabled plugin is specified for an extension point,
// default plugins for that extension point will be used if there is any.
// If a QueueSort plugin is specified, the same QueueSort Plugin and
// PluginConfig must be specified for all profiles.
Plugins *Plugins `json:"plugins,omitempty"` Plugins *Plugins `json:"plugins,omitempty"`
// PluginConfig is an optional set of custom plugin arguments for each plugin. // PluginConfig is an optional set of custom plugin arguments for each plugin.
// Omitting config args for a plugin is equivalent to using the default config for that plugin. // Omitting config args for a plugin is equivalent to using the default config
// for that plugin.
// +listType=map // +listType=map
// +listMapKey=name // +listMapKey=name
PluginConfig []PluginConfig `json:"pluginConfig,omitempty"` PluginConfig []PluginConfig `json:"pluginConfig,omitempty"`

View File

@ -28,11 +28,6 @@ import (
func (in *KubeSchedulerConfiguration) DeepCopyInto(out *KubeSchedulerConfiguration) { func (in *KubeSchedulerConfiguration) DeepCopyInto(out *KubeSchedulerConfiguration) {
*out = *in *out = *in
out.TypeMeta = in.TypeMeta out.TypeMeta = in.TypeMeta
if in.SchedulerName != nil {
in, out := &in.SchedulerName, &out.SchedulerName
*out = new(string)
**out = **in
}
in.AlgorithmSource.DeepCopyInto(&out.AlgorithmSource) in.AlgorithmSource.DeepCopyInto(&out.AlgorithmSource)
in.LeaderElection.DeepCopyInto(&out.LeaderElection) in.LeaderElection.DeepCopyInto(&out.LeaderElection)
out.ClientConnection = in.ClientConnection out.ClientConnection = in.ClientConnection
@ -72,14 +67,9 @@ func (in *KubeSchedulerConfiguration) DeepCopyInto(out *KubeSchedulerConfigurati
*out = new(int64) *out = new(int64)
**out = **in **out = **in
} }
if in.Plugins != nil { if in.Profiles != nil {
in, out := &in.Plugins, &out.Plugins in, out := &in.Profiles, &out.Profiles
*out = new(Plugins) *out = make([]KubeSchedulerProfile, len(*in))
(*in).DeepCopyInto(*out)
}
if in.PluginConfig != nil {
in, out := &in.PluginConfig, &out.PluginConfig
*out = make([]PluginConfig, len(*in))
for i := range *in { for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i]) (*in)[i].DeepCopyInto(&(*out)[i])
} }
@ -122,6 +112,39 @@ func (in *KubeSchedulerLeaderElectionConfiguration) DeepCopy() *KubeSchedulerLea
return out return out
} }
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *KubeSchedulerProfile) DeepCopyInto(out *KubeSchedulerProfile) {
*out = *in
if in.SchedulerName != nil {
in, out := &in.SchedulerName, &out.SchedulerName
*out = new(string)
**out = **in
}
if in.Plugins != nil {
in, out := &in.Plugins, &out.Plugins
*out = new(Plugins)
(*in).DeepCopyInto(*out)
}
if in.PluginConfig != nil {
in, out := &in.PluginConfig, &out.PluginConfig
*out = make([]PluginConfig, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeSchedulerProfile.
func (in *KubeSchedulerProfile) DeepCopy() *KubeSchedulerProfile {
if in == nil {
return nil
}
out := new(KubeSchedulerProfile)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Plugin) DeepCopyInto(out *Plugin) { func (in *Plugin) DeepCopyInto(out *Plugin) {
*out = *in *out = *in