mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-22 19:31:44 +00:00
Merge pull request #88087 from alculquicondor/mutiprofiles-api
Add Schedulings Profiles to kubescheduler.config.k8s.io/v1alpha2
This commit is contained in:
commit
f6525dbc81
@ -38,6 +38,7 @@ type DeprecatedOptions struct {
|
||||
UseLegacyPolicyConfig bool
|
||||
AlgorithmProvider string
|
||||
HardPodAffinitySymmetricWeight int32
|
||||
SchedulerName string
|
||||
}
|
||||
|
||||
// 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.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.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.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 "+
|
||||
"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")
|
||||
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:
|
||||
// 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 {
|
||||
args := interpodaffinity.Args{
|
||||
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
|
||||
|
@ -48,6 +48,7 @@ import (
|
||||
kubeschedulerconfig "k8s.io/kubernetes/pkg/scheduler/apis/config"
|
||||
kubeschedulerscheme "k8s.io/kubernetes/pkg/scheduler/apis/config/scheme"
|
||||
"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
|
||||
@ -98,8 +99,10 @@ func NewOptions() (*Options, error) {
|
||||
Authentication: apiserveroptions.NewDelegatingAuthenticationOptions(),
|
||||
Authorization: apiserveroptions.NewDelegatingAuthorizationOptions(),
|
||||
Deprecated: &DeprecatedOptions{
|
||||
UseLegacyPolicyConfig: false,
|
||||
PolicyConfigMapNamespace: metav1.NamespaceSystem,
|
||||
UseLegacyPolicyConfig: false,
|
||||
PolicyConfigMapNamespace: metav1.NamespaceSystem,
|
||||
SchedulerName: corev1.DefaultSchedulerName,
|
||||
HardPodAffinitySymmetricWeight: interpodaffinity.DefaultHardPodAffinityWeight,
|
||||
},
|
||||
}
|
||||
|
||||
@ -239,11 +242,12 @@ func (o *Options) Config() (*schedulerappconfig.Config, error) {
|
||||
}
|
||||
|
||||
coreBroadcaster := record.NewBroadcaster()
|
||||
coreRecorder := coreBroadcaster.NewRecorder(scheme.Scheme, corev1.EventSource{Component: c.ComponentConfig.SchedulerName})
|
||||
|
||||
// Set up leader election if enabled.
|
||||
var leaderElectionConfig *leaderelection.LeaderElectionConfig
|
||||
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)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -138,6 +138,7 @@ leaderElection:
|
||||
if err := ioutil.WriteFile(v1alpha1Config, []byte(fmt.Sprintf(`
|
||||
apiVersion: kubescheduler.config.k8s.io/v1alpha1
|
||||
kind: KubeSchedulerConfiguration
|
||||
schedulerName: "my-old-scheduler"
|
||||
clientConnection:
|
||||
kubeconfig: "%s"
|
||||
leaderElection:
|
||||
@ -225,20 +226,21 @@ apiVersion: kubescheduler.config.k8s.io/v1alpha2
|
||||
kind: KubeSchedulerConfiguration
|
||||
clientConnection:
|
||||
kubeconfig: "%s"
|
||||
plugins:
|
||||
reserve:
|
||||
enabled:
|
||||
- name: foo
|
||||
- name: bar
|
||||
disabled:
|
||||
- name: baz
|
||||
preBind:
|
||||
enabled:
|
||||
- name: foo
|
||||
disabled:
|
||||
- name: baz
|
||||
pluginConfig:
|
||||
- name: foo
|
||||
profiles:
|
||||
- plugins:
|
||||
reserve:
|
||||
enabled:
|
||||
- name: foo
|
||||
- name: bar
|
||||
disabled:
|
||||
- name: baz
|
||||
preBind:
|
||||
enabled:
|
||||
- name: foo
|
||||
disabled:
|
||||
- name: baz
|
||||
pluginConfig:
|
||||
- name: foo
|
||||
`, configKubeconfig)), os.FileMode(0600)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -319,7 +321,6 @@ plugins:
|
||||
},
|
||||
expectedUsername: "config",
|
||||
expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{
|
||||
SchedulerName: "default-scheduler",
|
||||
AlgorithmSource: kubeschedulerconfig.SchedulerAlgorithmSource{Provider: &defaultSource},
|
||||
HealthzBindAddress: "0.0.0.0:10251",
|
||||
MetricsBindAddress: "0.0.0.0:10251",
|
||||
@ -348,7 +349,9 @@ plugins:
|
||||
BindTimeoutSeconds: defaultBindTimeoutSeconds,
|
||||
PodInitialBackoffSeconds: defaultPodInitialBackoffSeconds,
|
||||
PodMaxBackoffSeconds: defaultPodMaxBackoffSeconds,
|
||||
Plugins: nil,
|
||||
Profiles: []kubeschedulerconfig.KubeSchedulerProfile{
|
||||
{SchedulerName: "default-scheduler"},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -410,7 +413,6 @@ plugins:
|
||||
},
|
||||
expectedUsername: "flag",
|
||||
expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{
|
||||
SchedulerName: "default-scheduler",
|
||||
AlgorithmSource: kubeschedulerconfig.SchedulerAlgorithmSource{Provider: &defaultSource},
|
||||
HealthzBindAddress: "", // defaults empty when not running from config file
|
||||
MetricsBindAddress: "", // defaults empty when not running from config file
|
||||
@ -439,6 +441,9 @@ plugins:
|
||||
BindTimeoutSeconds: defaultBindTimeoutSeconds,
|
||||
PodInitialBackoffSeconds: defaultPodInitialBackoffSeconds,
|
||||
PodMaxBackoffSeconds: defaultPodMaxBackoffSeconds,
|
||||
Profiles: []kubeschedulerconfig.KubeSchedulerProfile{
|
||||
{SchedulerName: "default-scheduler"},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -474,7 +479,6 @@ plugins:
|
||||
},
|
||||
},
|
||||
expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{
|
||||
SchedulerName: "default-scheduler",
|
||||
AlgorithmSource: kubeschedulerconfig.SchedulerAlgorithmSource{Provider: &defaultSource},
|
||||
HealthzBindAddress: "", // defaults empty when not running from config file
|
||||
MetricsBindAddress: "", // defaults empty when not running from config file
|
||||
@ -503,6 +507,9 @@ plugins:
|
||||
BindTimeoutSeconds: defaultBindTimeoutSeconds,
|
||||
PodInitialBackoffSeconds: defaultPodInitialBackoffSeconds,
|
||||
PodMaxBackoffSeconds: defaultPodMaxBackoffSeconds,
|
||||
Profiles: []kubeschedulerconfig.KubeSchedulerProfile{
|
||||
{SchedulerName: "default-scheduler"},
|
||||
},
|
||||
},
|
||||
expectedUsername: "none, http",
|
||||
},
|
||||
@ -513,7 +520,6 @@ plugins:
|
||||
},
|
||||
expectedUsername: "config",
|
||||
expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{
|
||||
SchedulerName: "default-scheduler",
|
||||
AlgorithmSource: kubeschedulerconfig.SchedulerAlgorithmSource{Provider: &defaultSource},
|
||||
HealthzBindAddress: "0.0.0.0:10251",
|
||||
MetricsBindAddress: "0.0.0.0:10251",
|
||||
@ -542,39 +548,44 @@ plugins:
|
||||
BindTimeoutSeconds: defaultBindTimeoutSeconds,
|
||||
PodInitialBackoffSeconds: defaultPodInitialBackoffSeconds,
|
||||
PodMaxBackoffSeconds: defaultPodMaxBackoffSeconds,
|
||||
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{
|
||||
Profiles: []kubeschedulerconfig.KubeSchedulerProfile{
|
||||
{
|
||||
Name: "foo",
|
||||
Args: runtime.Unknown{},
|
||||
SchedulerName: "default-scheduler",
|
||||
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",
|
||||
expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{
|
||||
SchedulerName: "default-scheduler",
|
||||
AlgorithmSource: kubeschedulerconfig.SchedulerAlgorithmSource{Provider: &defaultSource},
|
||||
HealthzBindAddress: "0.0.0.0:10251",
|
||||
MetricsBindAddress: "0.0.0.0:10251",
|
||||
@ -615,19 +625,24 @@ plugins:
|
||||
BindTimeoutSeconds: defaultBindTimeoutSeconds,
|
||||
PodInitialBackoffSeconds: defaultPodInitialBackoffSeconds,
|
||||
PodMaxBackoffSeconds: defaultPodMaxBackoffSeconds,
|
||||
Plugins: &kubeschedulerconfig.Plugins{
|
||||
PreScore: &kubeschedulerconfig.PluginSet{
|
||||
Enabled: []kubeschedulerconfig.Plugin{
|
||||
{
|
||||
Name: "foo",
|
||||
},
|
||||
{
|
||||
Name: "bar",
|
||||
},
|
||||
},
|
||||
Disabled: []kubeschedulerconfig.Plugin{
|
||||
{
|
||||
Name: "baz",
|
||||
Profiles: []kubeschedulerconfig.KubeSchedulerProfile{
|
||||
{
|
||||
SchedulerName: "default-scheduler",
|
||||
Plugins: &kubeschedulerconfig.Plugins{
|
||||
PreScore: &kubeschedulerconfig.PluginSet{
|
||||
Enabled: []kubeschedulerconfig.Plugin{
|
||||
{
|
||||
Name: "foo",
|
||||
},
|
||||
{
|
||||
Name: "bar",
|
||||
},
|
||||
},
|
||||
Disabled: []kubeschedulerconfig.Plugin{
|
||||
{
|
||||
Name: "baz",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -653,7 +668,6 @@ plugins:
|
||||
},
|
||||
expectedUsername: "flag",
|
||||
expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{
|
||||
SchedulerName: "default-scheduler",
|
||||
AlgorithmSource: kubeschedulerconfig.SchedulerAlgorithmSource{Provider: &defaultSource},
|
||||
DebuggingConfiguration: componentbaseconfig.DebuggingConfiguration{
|
||||
EnableProfiling: true,
|
||||
@ -680,24 +694,74 @@ plugins:
|
||||
BindTimeoutSeconds: defaultBindTimeoutSeconds,
|
||||
PodInitialBackoffSeconds: defaultPodInitialBackoffSeconds,
|
||||
PodMaxBackoffSeconds: defaultPodMaxBackoffSeconds,
|
||||
PluginConfig: []kubeschedulerconfig.PluginConfig{
|
||||
Profiles: []kubeschedulerconfig.KubeSchedulerProfile{
|
||||
{
|
||||
Name: "InterPodAffinity",
|
||||
Args: runtime.Unknown{
|
||||
Raw: []byte(`{"hardPodAffinityWeight":5}`),
|
||||
SchedulerName: "default-scheduler",
|
||||
PluginConfig: []kubeschedulerconfig.PluginConfig{
|
||||
{
|
||||
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{
|
||||
ConfigFile: v1alpha1Config,
|
||||
},
|
||||
expectedUsername: "config",
|
||||
expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{
|
||||
SchedulerName: "default-scheduler",
|
||||
AlgorithmSource: kubeschedulerconfig.SchedulerAlgorithmSource{Provider: &defaultSource},
|
||||
HealthzBindAddress: "0.0.0.0:10251",
|
||||
MetricsBindAddress: "0.0.0.0:10251",
|
||||
@ -726,11 +790,16 @@ plugins:
|
||||
BindTimeoutSeconds: defaultBindTimeoutSeconds,
|
||||
PodInitialBackoffSeconds: defaultPodInitialBackoffSeconds,
|
||||
PodMaxBackoffSeconds: defaultPodMaxBackoffSeconds,
|
||||
PluginConfig: []kubeschedulerconfig.PluginConfig{
|
||||
Profiles: []kubeschedulerconfig.KubeSchedulerProfile{
|
||||
{
|
||||
Name: "InterPodAffinity",
|
||||
Args: runtime.Unknown{
|
||||
Raw: []byte(`{"hardPodAffinityWeight":3}`),
|
||||
SchedulerName: "my-old-scheduler",
|
||||
PluginConfig: []kubeschedulerconfig.PluginConfig{
|
||||
{
|
||||
Name: "InterPodAffinity",
|
||||
Args: runtime.Unknown{
|
||||
Raw: []byte(`{"hardPodAffinityWeight":3}`),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -743,7 +812,6 @@ plugins:
|
||||
},
|
||||
expectedUsername: "config",
|
||||
expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{
|
||||
SchedulerName: "default-scheduler",
|
||||
AlgorithmSource: kubeschedulerconfig.SchedulerAlgorithmSource{Provider: &defaultSource},
|
||||
HealthzBindAddress: "0.0.0.0:10251",
|
||||
MetricsBindAddress: "0.0.0.0:10251",
|
||||
@ -772,7 +840,9 @@ plugins:
|
||||
BindTimeoutSeconds: defaultBindTimeoutSeconds,
|
||||
PodInitialBackoffSeconds: defaultPodInitialBackoffSeconds,
|
||||
PodMaxBackoffSeconds: defaultPodMaxBackoffSeconds,
|
||||
Plugins: nil,
|
||||
Profiles: []kubeschedulerconfig.KubeSchedulerProfile{
|
||||
{SchedulerName: "default-scheduler"},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -790,7 +860,6 @@ plugins:
|
||||
},
|
||||
expectedUsername: "config",
|
||||
expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{
|
||||
SchedulerName: "default-scheduler",
|
||||
AlgorithmSource: kubeschedulerconfig.SchedulerAlgorithmSource{Provider: &defaultSource},
|
||||
HealthzBindAddress: "0.0.0.0:10251",
|
||||
MetricsBindAddress: "0.0.0.0:10251",
|
||||
@ -819,7 +888,9 @@ plugins:
|
||||
BindTimeoutSeconds: defaultBindTimeoutSeconds,
|
||||
PodInitialBackoffSeconds: defaultPodInitialBackoffSeconds,
|
||||
PodMaxBackoffSeconds: defaultPodMaxBackoffSeconds,
|
||||
Plugins: nil,
|
||||
Profiles: []kubeschedulerconfig.KubeSchedulerProfile{
|
||||
{SchedulerName: "default-scheduler"},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -19,6 +19,7 @@ package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"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.
|
||||
if _, err := cc.Client.Discovery().ServerResourcesForGroupVersion(eventsv1beta1.SchemeGroupVersion.String()); err == nil {
|
||||
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 {
|
||||
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)
|
||||
}
|
||||
|
||||
@ -186,14 +192,14 @@ func Run(ctx context.Context, cc schedulerserverconfig.CompletedConfig, outOfTre
|
||||
cc.PodInformer,
|
||||
cc.Recorder,
|
||||
ctx.Done(),
|
||||
scheduler.WithName(cc.ComponentConfig.SchedulerName),
|
||||
scheduler.WithName(profile.SchedulerName),
|
||||
scheduler.WithAlgorithmSource(cc.ComponentConfig.AlgorithmSource),
|
||||
scheduler.WithPreemptionDisabled(cc.ComponentConfig.DisablePreemption),
|
||||
scheduler.WithPercentageOfNodesToScore(cc.ComponentConfig.PercentageOfNodesToScore),
|
||||
scheduler.WithBindTimeoutSeconds(cc.ComponentConfig.BindTimeoutSeconds),
|
||||
scheduler.WithFrameworkOutOfTreeRegistry(outOfTreeRegistry),
|
||||
scheduler.WithFrameworkPlugins(cc.ComponentConfig.Plugins),
|
||||
scheduler.WithFrameworkPluginConfig(cc.ComponentConfig.PluginConfig),
|
||||
scheduler.WithFrameworkPlugins(profile.Plugins),
|
||||
scheduler.WithFrameworkPluginConfig(profile.PluginConfig),
|
||||
scheduler.WithPodMaxBackoffSeconds(cc.ComponentConfig.PodMaxBackoffSeconds),
|
||||
scheduler.WithPodInitialBackoffSeconds(cc.ComponentConfig.PodInitialBackoffSeconds),
|
||||
)
|
||||
|
@ -46,9 +46,6 @@ const (
|
||||
type KubeSchedulerConfiguration struct {
|
||||
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 SchedulerAlgorithmSource
|
||||
|
||||
@ -97,15 +94,33 @@ type KubeSchedulerConfiguration struct {
|
||||
// the default value (10s) will be used.
|
||||
PodMaxBackoffSeconds int64
|
||||
|
||||
// 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.
|
||||
// Profiles are scheduling profiles that kube-scheduler supports. Pods can
|
||||
// choose to be scheduled under a particular profile by setting its associated
|
||||
// scheduler name. Pods that don't specify any scheduler name are scheduled
|
||||
// with the "default-scheduler" profile, if present here.
|
||||
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
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@ package v1alpha1
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/conversion"
|
||||
"k8s.io/kube-scheduler/config/v1alpha1"
|
||||
"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 {
|
||||
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 {
|
||||
args := interpodaffinity.Args{HardPodAffinityWeight: in.HardPodAffinitySymmetricWeight}
|
||||
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
|
||||
}
|
||||
|
||||
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.
|
||||
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 {
|
||||
|
@ -30,33 +30,76 @@ import (
|
||||
"k8s.io/utils/pointer"
|
||||
)
|
||||
|
||||
func TestConvertHardPodAffinitySymmetricWeight(t *testing.T) {
|
||||
func TestConvertKubeSchedulerConfiguration(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
cfg v1alpha1.KubeSchedulerConfiguration
|
||||
want config.KubeSchedulerConfiguration
|
||||
}{
|
||||
{
|
||||
name: "no weight",
|
||||
},
|
||||
{
|
||||
name: "custom weight",
|
||||
name: "scheduler name",
|
||||
cfg: v1alpha1.KubeSchedulerConfiguration{
|
||||
HardPodAffinitySymmetricWeight: pointer.Int32Ptr(3),
|
||||
SchedulerName: pointer.StringPtr("custom-name"),
|
||||
},
|
||||
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",
|
||||
Args: runtime.Unknown{
|
||||
Raw: []byte(`{"hardPodAffinityWeight":3}`),
|
||||
Plugins: &config.Plugins{
|
||||
QueueSort: &config.PluginSet{
|
||||
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{
|
||||
HardPodAffinitySymmetricWeight: pointer.Int32Ptr(3),
|
||||
PluginConfig: []v1alpha1.PluginConfig{
|
||||
@ -69,17 +112,21 @@ func TestConvertHardPodAffinitySymmetricWeight(t *testing.T) {
|
||||
},
|
||||
},
|
||||
want: config.KubeSchedulerConfiguration{
|
||||
PluginConfig: []config.PluginConfig{
|
||||
Profiles: []config.KubeSchedulerProfile{
|
||||
{
|
||||
Name: "InterPodAffinity",
|
||||
Args: runtime.Unknown{
|
||||
Raw: []byte(`{"hardPodAffinityWeight":5}`),
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "InterPodAffinity",
|
||||
Args: runtime.Unknown{
|
||||
Raw: []byte(`{"hardPodAffinityWeight":3}`),
|
||||
PluginConfig: []config.PluginConfig{
|
||||
{
|
||||
Name: "InterPodAffinity",
|
||||
Args: runtime.Unknown{
|
||||
Raw: []byte(`{"hardPodAffinityWeight":5}`),
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "InterPodAffinity",
|
||||
Args: runtime.Unknown{
|
||||
Raw: []byte(`{"hardPodAffinityWeight":3}`),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -38,11 +38,6 @@ func init() {
|
||||
// RegisterConversions adds conversion functions to the given scheme.
|
||||
// Public to allow building arbitrary schemes.
|
||||
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 {
|
||||
return Convert_v1alpha1_Plugin_To_config_Plugin(a.(*v1alpha1.Plugin), b.(*config.Plugin), scope)
|
||||
}); err != nil {
|
||||
@ -113,6 +108,11 @@ func RegisterConversions(s *runtime.Scheme) error {
|
||||
}); err != nil {
|
||||
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 {
|
||||
return Convert_config_KubeSchedulerLeaderElectionConfiguration_To_v1alpha1_KubeSchedulerLeaderElectionConfiguration(a.(*config.KubeSchedulerLeaderElectionConfiguration), b.(*v1alpha1.KubeSchedulerLeaderElectionConfiguration), scope)
|
||||
}); 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 {
|
||||
if err := v1.Convert_Pointer_string_To_string(&in.SchedulerName, &out.SchedulerName, s); err != nil {
|
||||
return err
|
||||
}
|
||||
// WARNING: in.SchedulerName requires manual conversion: does not exist in peer-type
|
||||
if err := Convert_v1alpha1_SchedulerAlgorithmSource_To_config_SchedulerAlgorithmSource(&in.AlgorithmSource, &out.AlgorithmSource, s); err != nil {
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
if in.Plugins != nil {
|
||||
in, out := &in.Plugins, &out.Plugins
|
||||
*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))
|
||||
// WARNING: in.Plugins requires manual conversion: does not exist in peer-type
|
||||
// WARNING: in.PluginConfig requires manual conversion: does not exist in peer-type
|
||||
return nil
|
||||
}
|
||||
|
||||
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 {
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
if in.Plugins != nil {
|
||||
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))
|
||||
// WARNING: in.Profiles requires manual conversion: does not exist in peer-type
|
||||
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 {
|
||||
if err := componentbaseconfigv1alpha1.Convert_v1alpha1_LeaderElectionConfiguration_To_config_LeaderElectionConfiguration(&in.LeaderElectionConfiguration, &out.LeaderElectionConfiguration, s); err != nil {
|
||||
return err
|
||||
|
@ -21,6 +21,7 @@ go_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/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/component-base/config/v1alpha1: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",
|
||||
],
|
||||
)
|
||||
|
@ -24,6 +24,7 @@ import (
|
||||
componentbaseconfigv1alpha1 "k8s.io/component-base/config/v1alpha1"
|
||||
"k8s.io/kube-scheduler/config/v1alpha2"
|
||||
"k8s.io/kubernetes/pkg/scheduler/apis/config"
|
||||
"k8s.io/utils/pointer"
|
||||
|
||||
// this package shouldn't really depend on other k8s.io/kubernetes code
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
@ -36,9 +37,13 @@ func addDefaultingFuncs(scheme *runtime.Scheme) error {
|
||||
|
||||
// SetDefaults_KubeSchedulerConfiguration sets additional defaults
|
||||
func SetDefaults_KubeSchedulerConfiguration(obj *v1alpha2.KubeSchedulerConfiguration) {
|
||||
if obj.SchedulerName == nil {
|
||||
val := api.DefaultSchedulerName
|
||||
obj.SchedulerName = &val
|
||||
if len(obj.Profiles) == 0 {
|
||||
obj.Profiles = append(obj.Profiles, v1alpha2.KubeSchedulerProfile{})
|
||||
}
|
||||
// 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 &&
|
||||
|
@ -17,10 +17,10 @@ limitations under the License.
|
||||
package v1alpha2
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
componentbaseconfig "k8s.io/component-base/config/v1alpha1"
|
||||
"k8s.io/kube-scheduler/config/v1alpha2"
|
||||
@ -38,7 +38,6 @@ func TestSchedulerDefaults(t *testing.T) {
|
||||
name: "empty config",
|
||||
config: &v1alpha2.KubeSchedulerConfiguration{},
|
||||
expected: &v1alpha2.KubeSchedulerConfiguration{
|
||||
SchedulerName: pointer.StringPtr("default-scheduler"),
|
||||
AlgorithmSource: v1alpha2.SchedulerAlgorithmSource{Provider: pointer.StringPtr("DefaultProvider")},
|
||||
HealthzBindAddress: 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),
|
||||
PodInitialBackoffSeconds: pointer.Int64Ptr(1),
|
||||
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"),
|
||||
},
|
||||
expected: &v1alpha2.KubeSchedulerConfiguration{
|
||||
SchedulerName: pointer.StringPtr("default-scheduler"),
|
||||
AlgorithmSource: v1alpha2.SchedulerAlgorithmSource{Provider: pointer.StringPtr("DefaultProvider")},
|
||||
HealthzBindAddress: 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),
|
||||
PodInitialBackoffSeconds: pointer.Int64Ptr(1),
|
||||
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"),
|
||||
},
|
||||
expected: &v1alpha2.KubeSchedulerConfiguration{
|
||||
SchedulerName: pointer.StringPtr("default-scheduler"),
|
||||
AlgorithmSource: v1alpha2.SchedulerAlgorithmSource{Provider: pointer.StringPtr("DefaultProvider")},
|
||||
HealthzBindAddress: 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),
|
||||
PodInitialBackoffSeconds: pointer.Int64Ptr(1),
|
||||
PodMaxBackoffSeconds: pointer.Int64Ptr(10),
|
||||
Plugins: nil,
|
||||
Profiles: []v1alpha2.KubeSchedulerProfile{
|
||||
{SchedulerName: pointer.StringPtr("default-scheduler")},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
SetDefaults_KubeSchedulerConfiguration(tc.config)
|
||||
if !reflect.DeepEqual(tc.expected, tc.config) {
|
||||
t.Errorf("Expected:\n%#v\n\nGot:\n%#v", tc.expected, tc.config)
|
||||
if diff := cmp.Diff(tc.expected, tc.config); diff != "" {
|
||||
t.Errorf("Got unexpected defaults (-want, +got):\n%s", diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -58,6 +58,16 @@ func RegisterConversions(s *runtime.Scheme) error {
|
||||
}); err != nil {
|
||||
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 {
|
||||
return Convert_v1alpha2_Plugin_To_config_Plugin(a.(*v1alpha2.Plugin), b.(*config.Plugin), scope)
|
||||
}); 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 {
|
||||
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 {
|
||||
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 {
|
||||
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
|
||||
if in.Profiles != nil {
|
||||
in, out := &in.Profiles, &out.Profiles
|
||||
*out = make([]config.KubeSchedulerProfile, len(*in))
|
||||
for i := range *in {
|
||||
if err := Convert_v1alpha2_KubeSchedulerProfile_To_config_KubeSchedulerProfile(&(*in)[i], &(*out)[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.Plugins = nil
|
||||
out.Profiles = nil
|
||||
}
|
||||
out.PluginConfig = *(*[]config.PluginConfig)(unsafe.Pointer(&in.PluginConfig))
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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
|
||||
if in.Profiles != nil {
|
||||
in, out := &in.Profiles, &out.Profiles
|
||||
*out = make([]v1alpha2.KubeSchedulerProfile, len(*in))
|
||||
for i := range *in {
|
||||
if err := Convert_config_KubeSchedulerProfile_To_v1alpha2_KubeSchedulerProfile(&(*in)[i], &(*out)[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.Plugins = nil
|
||||
out.Profiles = nil
|
||||
}
|
||||
out.PluginConfig = *(*[]v1alpha2.PluginConfig)(unsafe.Pointer(&in.PluginConfig))
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -275,6 +281,50 @@ func Convert_config_KubeSchedulerLeaderElectionConfiguration_To_v1alpha2_KubeSch
|
||||
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 {
|
||||
out.Name = in.Name
|
||||
if err := v1.Convert_Pointer_int32_To_int32(&in.Weight, &out.Weight, s); err != nil {
|
||||
|
@ -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/field:go_default_library",
|
||||
"//staging/src/k8s.io/component-base/config/validation:go_default_library",
|
||||
"//vendor/github.com/google/go-cmp/cmp:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
@ -20,6 +20,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
@ -34,9 +35,23 @@ import (
|
||||
func ValidateKubeSchedulerConfiguration(cc *config.KubeSchedulerConfiguration) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
allErrs = append(allErrs, componentbasevalidation.ValidateClientConnectionConfiguration(&cc.ClientConnection, field.NewPath("clientConnection"))...)
|
||||
allErrs = append(allErrs, ValidateKubeSchedulerLeaderElectionConfiguration(&cc.LeaderElection, field.NewPath("leaderElection"))...)
|
||||
if len(cc.SchedulerName) == 0 {
|
||||
allErrs = append(allErrs, field.Required(field.NewPath("schedulerName"), ""))
|
||||
allErrs = append(allErrs, validateKubeSchedulerLeaderElectionConfiguration(field.NewPath("leaderElection"), &cc.LeaderElection)...)
|
||||
|
||||
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) {
|
||||
allErrs = append(allErrs, field.Invalid(field.NewPath("healthzBindAddress"), cc.HealthzBindAddress, msg))
|
||||
@ -59,13 +74,39 @@ func ValidateKubeSchedulerConfiguration(cc *config.KubeSchedulerConfiguration) f
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateKubeSchedulerLeaderElectionConfiguration ensures validation of the KubeSchedulerLeaderElectionConfiguration struct
|
||||
func ValidateKubeSchedulerLeaderElectionConfiguration(cc *config.KubeSchedulerLeaderElectionConfiguration, fldPath *field.Path) field.ErrorList {
|
||||
func validateKubeSchedulerProfile(path *field.Path, profile *config.KubeSchedulerProfile) 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{}
|
||||
if !cc.LeaderElectionConfiguration.LeaderElect {
|
||||
return allErrs
|
||||
}
|
||||
allErrs = append(allErrs, componentbasevalidation.ValidateLeaderElectionConfiguration(&cc.LeaderElectionConfiguration, field.NewPath("leaderElectionConfiguration"))...)
|
||||
allErrs = append(allErrs, componentbasevalidation.ValidateLeaderElectionConfiguration(&cc.LeaderElectionConfiguration, fldPath)...)
|
||||
return allErrs
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,6 @@ func TestValidateKubeSchedulerConfiguration(t *testing.T) {
|
||||
podInitialBackoffSeconds := int64(1)
|
||||
podMaxBackoffSeconds := int64(1)
|
||||
validConfig := &config.KubeSchedulerConfiguration{
|
||||
SchedulerName: "me",
|
||||
HealthzBindAddress: "0.0.0.0:10254",
|
||||
MetricsBindAddress: "0.0.0.0:10254",
|
||||
ClientConnection: componentbaseconfig.ClientConnectionConfiguration{
|
||||
@ -64,6 +63,30 @@ func TestValidateKubeSchedulerConfiguration(t *testing.T) {
|
||||
PodMaxBackoffSeconds: podMaxBackoffSeconds,
|
||||
BindTimeoutSeconds: testTimeout,
|
||||
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()
|
||||
@ -91,6 +114,18 @@ func TestValidateKubeSchedulerConfiguration(t *testing.T) {
|
||||
percentageOfNodesToScore101 := validConfig.DeepCopy()
|
||||
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 {
|
||||
expectedToFail bool
|
||||
config *config.KubeSchedulerConfiguration
|
||||
@ -127,16 +162,34 @@ func TestValidateKubeSchedulerConfiguration(t *testing.T) {
|
||||
expectedToFail: true,
|
||||
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 {
|
||||
errs := ValidateKubeSchedulerConfiguration(scenario.config)
|
||||
if len(errs) == 0 && scenario.expectedToFail {
|
||||
t.Errorf("Unexpected success for scenario: %s", name)
|
||||
}
|
||||
if len(errs) > 0 && !scenario.expectedToFail {
|
||||
t.Errorf("Unexpected failure for scenario: %s - %+v", name, errs)
|
||||
}
|
||||
t.Run(name, func(t *testing.T) {
|
||||
errs := ValidateKubeSchedulerConfiguration(scenario.config)
|
||||
if len(errs) == 0 && scenario.expectedToFail {
|
||||
t.Error("Unexpected success")
|
||||
}
|
||||
if len(errs) > 0 && !scenario.expectedToFail {
|
||||
t.Errorf("Unexpected failure: %+v", errs)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
39
pkg/scheduler/apis/config/zz_generated.deepcopy.go
generated
39
pkg/scheduler/apis/config/zz_generated.deepcopy.go
generated
@ -105,14 +105,9 @@ func (in *KubeSchedulerConfiguration) DeepCopyInto(out *KubeSchedulerConfigurati
|
||||
out.LeaderElection = in.LeaderElection
|
||||
out.ClientConnection = in.ClientConnection
|
||||
out.DebuggingConfiguration = in.DebuggingConfiguration
|
||||
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))
|
||||
if in.Profiles != nil {
|
||||
in, out := &in.Profiles, &out.Profiles
|
||||
*out = make([]KubeSchedulerProfile, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
@ -155,6 +150,34 @@ func (in *KubeSchedulerLeaderElectionConfiguration) DeepCopy() *KubeSchedulerLea
|
||||
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.
|
||||
func (in *LabelPreference) DeepCopyInto(out *LabelPreference) {
|
||||
*out = *in
|
||||
|
@ -39,9 +39,6 @@ const (
|
||||
type KubeSchedulerConfiguration struct {
|
||||
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 SchedulerAlgorithmSource `json:"algorithmSource"`
|
||||
|
||||
@ -90,15 +87,35 @@ type KubeSchedulerConfiguration struct {
|
||||
// the default value (10s) will be used.
|
||||
PodMaxBackoffSeconds *int64 `json:"podMaxBackoffSeconds"`
|
||||
|
||||
// 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.
|
||||
// Profiles are scheduling profiles that kube-scheduler supports. Pods can
|
||||
// choose to be scheduled under a particular profile by setting its associated
|
||||
// scheduler name. Pods that don't specify any scheduler name are scheduled
|
||||
// with the "default-scheduler" profile, if present here.
|
||||
// +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"`
|
||||
|
||||
// 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
|
||||
// +listMapKey=name
|
||||
PluginConfig []PluginConfig `json:"pluginConfig,omitempty"`
|
||||
|
@ -28,11 +28,6 @@ import (
|
||||
func (in *KubeSchedulerConfiguration) DeepCopyInto(out *KubeSchedulerConfiguration) {
|
||||
*out = *in
|
||||
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.LeaderElection.DeepCopyInto(&out.LeaderElection)
|
||||
out.ClientConnection = in.ClientConnection
|
||||
@ -72,14 +67,9 @@ func (in *KubeSchedulerConfiguration) DeepCopyInto(out *KubeSchedulerConfigurati
|
||||
*out = new(int64)
|
||||
**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))
|
||||
if in.Profiles != nil {
|
||||
in, out := &in.Profiles, &out.Profiles
|
||||
*out = make([]KubeSchedulerProfile, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
@ -122,6 +112,39 @@ func (in *KubeSchedulerLeaderElectionConfiguration) DeepCopy() *KubeSchedulerLea
|
||||
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.
|
||||
func (in *Plugin) DeepCopyInto(out *Plugin) {
|
||||
*out = *in
|
||||
|
Loading…
Reference in New Issue
Block a user