mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 19:56:01 +00:00
Merge pull request #105611 from damemi/simplified-multipoint-extension
Scheduler simplified MultiPoint plugin config
This commit is contained in:
commit
c0b5ed7556
@ -690,24 +690,24 @@ profiles:
|
|||||||
{
|
{
|
||||||
SchedulerName: "default-scheduler",
|
SchedulerName: "default-scheduler",
|
||||||
Plugins: &kubeschedulerconfig.Plugins{
|
Plugins: &kubeschedulerconfig.Plugins{
|
||||||
QueueSort: defaults.PluginsV1beta3.QueueSort,
|
|
||||||
PreFilter: defaults.PluginsV1beta3.PreFilter,
|
|
||||||
Filter: defaults.PluginsV1beta3.Filter,
|
|
||||||
PostFilter: defaults.PluginsV1beta3.PostFilter,
|
|
||||||
PreScore: defaults.PluginsV1beta3.PreScore,
|
|
||||||
Score: defaults.PluginsV1beta3.Score,
|
|
||||||
Reserve: kubeschedulerconfig.PluginSet{
|
Reserve: kubeschedulerconfig.PluginSet{
|
||||||
Enabled: []kubeschedulerconfig.Plugin{
|
Enabled: []kubeschedulerconfig.Plugin{
|
||||||
{Name: "foo"},
|
{Name: "foo"},
|
||||||
{Name: "bar"},
|
{Name: "bar"},
|
||||||
},
|
},
|
||||||
|
Disabled: []kubeschedulerconfig.Plugin{
|
||||||
|
{Name: names.VolumeBinding},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
PreBind: kubeschedulerconfig.PluginSet{
|
PreBind: kubeschedulerconfig.PluginSet{
|
||||||
Enabled: []kubeschedulerconfig.Plugin{
|
Enabled: []kubeschedulerconfig.Plugin{
|
||||||
{Name: "foo"},
|
{Name: "foo"},
|
||||||
},
|
},
|
||||||
|
Disabled: []kubeschedulerconfig.Plugin{
|
||||||
|
{Name: names.VolumeBinding},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Bind: defaults.PluginsV1beta3.Bind,
|
MultiPoint: defaults.PluginsV1beta3.MultiPoint,
|
||||||
},
|
},
|
||||||
PluginConfig: []kubeschedulerconfig.PluginConfig{
|
PluginConfig: []kubeschedulerconfig.PluginConfig{
|
||||||
{
|
{
|
||||||
@ -918,19 +918,15 @@ profiles:
|
|||||||
{
|
{
|
||||||
SchedulerName: "foo-profile",
|
SchedulerName: "foo-profile",
|
||||||
Plugins: &kubeschedulerconfig.Plugins{
|
Plugins: &kubeschedulerconfig.Plugins{
|
||||||
QueueSort: defaults.PluginsV1beta3.QueueSort,
|
MultiPoint: defaults.PluginsV1beta3.MultiPoint,
|
||||||
PreFilter: defaults.PluginsV1beta3.PreFilter,
|
|
||||||
Filter: defaults.PluginsV1beta3.Filter,
|
|
||||||
PostFilter: defaults.PluginsV1beta3.PostFilter,
|
|
||||||
PreScore: defaults.PluginsV1beta3.PreScore,
|
|
||||||
Score: defaults.PluginsV1beta3.Score,
|
|
||||||
Bind: defaults.PluginsV1beta3.Bind,
|
|
||||||
PreBind: defaults.PluginsV1beta3.PreBind,
|
|
||||||
Reserve: kubeschedulerconfig.PluginSet{
|
Reserve: kubeschedulerconfig.PluginSet{
|
||||||
Enabled: []kubeschedulerconfig.Plugin{
|
Enabled: []kubeschedulerconfig.Plugin{
|
||||||
{Name: "foo"},
|
{Name: "foo"},
|
||||||
{Name: names.VolumeBinding},
|
{Name: names.VolumeBinding},
|
||||||
},
|
},
|
||||||
|
Disabled: []kubeschedulerconfig.Plugin{
|
||||||
|
{Name: names.VolumeBinding},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PluginConfig: defaults.PluginConfigsV1beta3,
|
PluginConfig: defaults.PluginConfigsV1beta3,
|
||||||
@ -938,14 +934,12 @@ profiles:
|
|||||||
{
|
{
|
||||||
SchedulerName: "bar-profile",
|
SchedulerName: "bar-profile",
|
||||||
Plugins: &kubeschedulerconfig.Plugins{
|
Plugins: &kubeschedulerconfig.Plugins{
|
||||||
QueueSort: defaults.PluginsV1beta3.QueueSort,
|
MultiPoint: defaults.PluginsV1beta3.MultiPoint,
|
||||||
PreFilter: defaults.PluginsV1beta3.PreFilter,
|
PreBind: kubeschedulerconfig.PluginSet{
|
||||||
Filter: defaults.PluginsV1beta3.Filter,
|
Disabled: []kubeschedulerconfig.Plugin{
|
||||||
PostFilter: defaults.PluginsV1beta3.PostFilter,
|
{Name: names.VolumeBinding},
|
||||||
PreScore: defaults.PluginsV1beta3.PreScore,
|
},
|
||||||
Score: defaults.PluginsV1beta3.Score,
|
},
|
||||||
Bind: defaults.PluginsV1beta3.Bind,
|
|
||||||
Reserve: defaults.PluginsV1beta3.Reserve,
|
|
||||||
},
|
},
|
||||||
PluginConfig: []kubeschedulerconfig.PluginConfig{
|
PluginConfig: []kubeschedulerconfig.PluginConfig{
|
||||||
{
|
{
|
||||||
|
@ -82,8 +82,46 @@ users:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// plugin config
|
// plugin config
|
||||||
pluginConfigFile := filepath.Join(tmpDir, "plugin.yaml")
|
pluginConfigFilev1beta3 := filepath.Join(tmpDir, "pluginv1beta3.yaml")
|
||||||
if err := ioutil.WriteFile(pluginConfigFile, []byte(fmt.Sprintf(`
|
if err := ioutil.WriteFile(pluginConfigFilev1beta3, []byte(fmt.Sprintf(`
|
||||||
|
apiVersion: kubescheduler.config.k8s.io/v1beta3
|
||||||
|
kind: KubeSchedulerConfiguration
|
||||||
|
clientConnection:
|
||||||
|
kubeconfig: "%s"
|
||||||
|
profiles:
|
||||||
|
- plugins:
|
||||||
|
multiPoint:
|
||||||
|
enabled:
|
||||||
|
- name: DefaultBinder
|
||||||
|
- name: PrioritySort
|
||||||
|
- name: DefaultPreemption
|
||||||
|
- name: VolumeBinding
|
||||||
|
- name: NodeResourcesFit
|
||||||
|
- name: NodePorts
|
||||||
|
- name: InterPodAffinity
|
||||||
|
- name: TaintToleration
|
||||||
|
disabled:
|
||||||
|
- name: "*"
|
||||||
|
preFilter:
|
||||||
|
disabled:
|
||||||
|
- name: VolumeBinding
|
||||||
|
- name: InterPodAffinity
|
||||||
|
filter:
|
||||||
|
disabled:
|
||||||
|
- name: VolumeBinding
|
||||||
|
- name: InterPodAffinity
|
||||||
|
- name: TaintToleration
|
||||||
|
score:
|
||||||
|
disabled:
|
||||||
|
- name: VolumeBinding
|
||||||
|
- name: NodeResourcesFit
|
||||||
|
`, configKubeconfig)), os.FileMode(0600)); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// plugin config
|
||||||
|
pluginConfigFilev1beta2 := filepath.Join(tmpDir, "pluginv1beta2.yaml")
|
||||||
|
if err := ioutil.WriteFile(pluginConfigFilev1beta2, []byte(fmt.Sprintf(`
|
||||||
apiVersion: kubescheduler.config.k8s.io/v1beta2
|
apiVersion: kubescheduler.config.k8s.io/v1beta2
|
||||||
kind: KubeSchedulerConfiguration
|
kind: KubeSchedulerConfiguration
|
||||||
clientConnection:
|
clientConnection:
|
||||||
@ -188,20 +226,19 @@ leaderElection:
|
|||||||
wantPlugins: map[string]*config.Plugins{
|
wantPlugins: map[string]*config.Plugins{
|
||||||
"default-scheduler": func() *config.Plugins {
|
"default-scheduler": func() *config.Plugins {
|
||||||
plugins := &config.Plugins{
|
plugins := &config.Plugins{
|
||||||
QueueSort: defaults.PluginsV1beta3.QueueSort,
|
QueueSort: defaults.ExpandedPluginsV1beta3.QueueSort,
|
||||||
PreFilter: defaults.PluginsV1beta3.PreFilter,
|
PreFilter: defaults.ExpandedPluginsV1beta3.PreFilter,
|
||||||
Filter: defaults.PluginsV1beta3.Filter,
|
Filter: defaults.ExpandedPluginsV1beta3.Filter,
|
||||||
PostFilter: defaults.PluginsV1beta3.PostFilter,
|
PostFilter: defaults.ExpandedPluginsV1beta3.PostFilter,
|
||||||
PreScore: defaults.PluginsV1beta3.PreScore,
|
PreScore: defaults.ExpandedPluginsV1beta3.PreScore,
|
||||||
Score: defaults.PluginsV1beta3.Score,
|
Score: defaults.ExpandedPluginsV1beta3.Score,
|
||||||
Bind: defaults.PluginsV1beta3.Bind,
|
Bind: defaults.ExpandedPluginsV1beta3.Bind,
|
||||||
PreBind: defaults.PluginsV1beta3.PreBind,
|
PreBind: defaults.ExpandedPluginsV1beta3.PreBind,
|
||||||
Reserve: defaults.PluginsV1beta3.Reserve,
|
Reserve: defaults.ExpandedPluginsV1beta3.Reserve,
|
||||||
}
|
}
|
||||||
plugins.PreScore.Enabled = append(plugins.PreScore.Enabled, config.Plugin{Name: names.SelectorSpread, Weight: 0})
|
plugins.PreScore.Enabled = append(plugins.PreScore.Enabled, config.Plugin{Name: names.SelectorSpread, Weight: 0})
|
||||||
plugins.Score.Enabled = append(
|
plugins.Score.Enabled = append(
|
||||||
plugins.Score.Enabled,
|
plugins.Score.Enabled,
|
||||||
config.Plugin{Name: names.VolumeBinding, Weight: 1},
|
|
||||||
config.Plugin{Name: names.SelectorSpread, Weight: 1},
|
config.Plugin{Name: names.SelectorSpread, Weight: 1},
|
||||||
)
|
)
|
||||||
return plugins
|
return plugins
|
||||||
@ -218,13 +255,53 @@ leaderElection:
|
|||||||
"--kubeconfig", configKubeconfig,
|
"--kubeconfig", configKubeconfig,
|
||||||
},
|
},
|
||||||
wantPlugins: map[string]*config.Plugins{
|
wantPlugins: map[string]*config.Plugins{
|
||||||
"default-scheduler": defaults.PluginsV1beta3,
|
"default-scheduler": defaults.ExpandedPluginsV1beta3,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "component configuration",
|
name: "component configuration v1beta2",
|
||||||
flags: []string{
|
flags: []string{
|
||||||
"--config", pluginConfigFile,
|
"--config", pluginConfigFilev1beta2,
|
||||||
|
"--kubeconfig", configKubeconfig,
|
||||||
|
},
|
||||||
|
wantPlugins: map[string]*config.Plugins{
|
||||||
|
"default-scheduler": {
|
||||||
|
Bind: config.PluginSet{Enabled: []config.Plugin{{Name: "DefaultBinder"}}},
|
||||||
|
Filter: config.PluginSet{
|
||||||
|
Enabled: []config.Plugin{
|
||||||
|
{Name: "NodeResourcesFit"},
|
||||||
|
{Name: "NodePorts"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
PreFilter: config.PluginSet{
|
||||||
|
Enabled: []config.Plugin{
|
||||||
|
{Name: "NodeResourcesFit"},
|
||||||
|
{Name: "NodePorts"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
PostFilter: config.PluginSet{Enabled: []config.Plugin{{Name: "DefaultPreemption"}}},
|
||||||
|
PreScore: config.PluginSet{
|
||||||
|
Enabled: []config.Plugin{
|
||||||
|
{Name: "InterPodAffinity"},
|
||||||
|
{Name: "TaintToleration"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
QueueSort: config.PluginSet{Enabled: []config.Plugin{{Name: "PrioritySort"}}},
|
||||||
|
Score: config.PluginSet{
|
||||||
|
Enabled: []config.Plugin{
|
||||||
|
{Name: "InterPodAffinity", Weight: 1},
|
||||||
|
{Name: "TaintToleration", Weight: 1},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Reserve: config.PluginSet{Enabled: []config.Plugin{{Name: "VolumeBinding"}}},
|
||||||
|
PreBind: config.PluginSet{Enabled: []config.Plugin{{Name: "VolumeBinding"}}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "component configuration v1beta3",
|
||||||
|
flags: []string{
|
||||||
|
"--config", pluginConfigFilev1beta3,
|
||||||
"--kubeconfig", configKubeconfig,
|
"--kubeconfig", configKubeconfig,
|
||||||
},
|
},
|
||||||
wantPlugins: map[string]*config.Plugins{
|
wantPlugins: map[string]*config.Plugins{
|
||||||
|
@ -151,8 +151,36 @@ var PluginConfigsV1beta2 = []config.PluginConfig{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// PluginsV1beta3 default set of v1beta3 plugins.
|
// PluginsV1beta3 is the set of default v1beta3 plugins (before MultiPoint expansion)
|
||||||
var PluginsV1beta3 = &config.Plugins{
|
var PluginsV1beta3 = &config.Plugins{
|
||||||
|
MultiPoint: config.PluginSet{
|
||||||
|
Enabled: []config.Plugin{
|
||||||
|
{Name: names.PrioritySort},
|
||||||
|
{Name: names.NodeUnschedulable},
|
||||||
|
{Name: names.NodeName},
|
||||||
|
{Name: names.TaintToleration, Weight: 3},
|
||||||
|
{Name: names.NodeAffinity, Weight: 2},
|
||||||
|
{Name: names.NodePorts},
|
||||||
|
{Name: names.NodeResourcesFit, Weight: 1},
|
||||||
|
{Name: names.VolumeRestrictions},
|
||||||
|
{Name: names.EBSLimits},
|
||||||
|
{Name: names.GCEPDLimits},
|
||||||
|
{Name: names.NodeVolumeLimits},
|
||||||
|
{Name: names.AzureDiskLimits},
|
||||||
|
{Name: names.VolumeBinding},
|
||||||
|
{Name: names.VolumeZone},
|
||||||
|
{Name: names.PodTopologySpread, Weight: 2},
|
||||||
|
{Name: names.InterPodAffinity, Weight: 2},
|
||||||
|
{Name: names.DefaultPreemption},
|
||||||
|
{Name: names.NodeResourcesBalancedAllocation, Weight: 1},
|
||||||
|
{Name: names.ImageLocality, Weight: 1},
|
||||||
|
{Name: names.DefaultBinder},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExpandedPluginsV1beta3 default set of v1beta3 plugins after MultiPoint expansion
|
||||||
|
var ExpandedPluginsV1beta3 = &config.Plugins{
|
||||||
QueueSort: config.PluginSet{
|
QueueSort: config.PluginSet{
|
||||||
Enabled: []config.Plugin{
|
Enabled: []config.Plugin{
|
||||||
{Name: names.PrioritySort},
|
{Name: names.PrioritySort},
|
||||||
@ -160,13 +188,13 @@ var PluginsV1beta3 = &config.Plugins{
|
|||||||
},
|
},
|
||||||
PreFilter: config.PluginSet{
|
PreFilter: config.PluginSet{
|
||||||
Enabled: []config.Plugin{
|
Enabled: []config.Plugin{
|
||||||
{Name: names.NodeResourcesFit},
|
{Name: names.NodeAffinity},
|
||||||
{Name: names.NodePorts},
|
{Name: names.NodePorts},
|
||||||
|
{Name: names.NodeResourcesFit},
|
||||||
{Name: names.VolumeRestrictions},
|
{Name: names.VolumeRestrictions},
|
||||||
|
{Name: names.VolumeBinding},
|
||||||
{Name: names.PodTopologySpread},
|
{Name: names.PodTopologySpread},
|
||||||
{Name: names.InterPodAffinity},
|
{Name: names.InterPodAffinity},
|
||||||
{Name: names.VolumeBinding},
|
|
||||||
{Name: names.NodeAffinity},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Filter: config.PluginSet{
|
Filter: config.PluginSet{
|
||||||
@ -195,32 +223,37 @@ var PluginsV1beta3 = &config.Plugins{
|
|||||||
},
|
},
|
||||||
PreScore: config.PluginSet{
|
PreScore: config.PluginSet{
|
||||||
Enabled: []config.Plugin{
|
Enabled: []config.Plugin{
|
||||||
{Name: names.InterPodAffinity},
|
|
||||||
{Name: names.PodTopologySpread},
|
|
||||||
{Name: names.TaintToleration},
|
{Name: names.TaintToleration},
|
||||||
{Name: names.NodeAffinity},
|
{Name: names.NodeAffinity},
|
||||||
|
{Name: names.PodTopologySpread},
|
||||||
|
{Name: names.InterPodAffinity},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Score: config.PluginSet{
|
Score: config.PluginSet{
|
||||||
Enabled: []config.Plugin{
|
Enabled: []config.Plugin{
|
||||||
{Name: names.NodeResourcesBalancedAllocation, Weight: 1},
|
// Weight is tripled because:
|
||||||
{Name: names.ImageLocality, Weight: 1},
|
|
||||||
{Name: names.NodeResourcesFit, Weight: 1},
|
|
||||||
// Weight is doubled because:
|
|
||||||
// - This is a score coming from user preference.
|
// - This is a score coming from user preference.
|
||||||
{Name: names.InterPodAffinity, Weight: 2},
|
// - Usage of node tainting to group nodes in the cluster is increasing becoming a use-case
|
||||||
|
// for many user workloads
|
||||||
|
{Name: names.TaintToleration, Weight: 3},
|
||||||
// Weight is doubled because:
|
// Weight is doubled because:
|
||||||
// - This is a score coming from user preference.
|
// - This is a score coming from user preference.
|
||||||
{Name: names.NodeAffinity, Weight: 2},
|
{Name: names.NodeAffinity, Weight: 2},
|
||||||
// Weight is doubled because:
|
{Name: names.NodeResourcesFit, Weight: 1},
|
||||||
// - This is a score coming from user preference.
|
|
||||||
// - It makes its signal comparable to NodeResourcesLeastAllocated.
|
|
||||||
{Name: names.PodTopologySpread, Weight: 2},
|
|
||||||
// Weight is tripled because:
|
// Weight is tripled because:
|
||||||
// - This is a score coming from user preference.
|
// - This is a score coming from user preference.
|
||||||
// - Usage of node tainting to group nodes in the cluster is increasing becoming a use-case
|
// - Usage of node tainting to group nodes in the cluster is increasing becoming a use-case
|
||||||
// for many user workloads
|
// for many user workloads
|
||||||
{Name: names.TaintToleration, Weight: 3},
|
{Name: names.VolumeBinding, Weight: 1},
|
||||||
|
// Weight is doubled because:
|
||||||
|
// - This is a score coming from user preference.
|
||||||
|
// - It makes its signal comparable to NodeResourcesLeastAllocated.
|
||||||
|
{Name: names.PodTopologySpread, Weight: 2},
|
||||||
|
// Weight is doubled because:
|
||||||
|
// - This is a score coming from user preference.
|
||||||
|
{Name: names.InterPodAffinity, Weight: 2},
|
||||||
|
{Name: names.NodeResourcesBalancedAllocation, Weight: 1},
|
||||||
|
{Name: names.ImageLocality, Weight: 1},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Reserve: config.PluginSet{
|
Reserve: config.PluginSet{
|
||||||
|
@ -161,6 +161,9 @@ type Plugins struct {
|
|||||||
|
|
||||||
// PostBind is a list of plugins that should be invoked after a pod is successfully bound.
|
// PostBind is a list of plugins that should be invoked after a pod is successfully bound.
|
||||||
PostBind PluginSet
|
PostBind PluginSet
|
||||||
|
|
||||||
|
// MultiPoint is a simplified config field for enabling plugins for all valid extension points
|
||||||
|
MultiPoint PluginSet
|
||||||
}
|
}
|
||||||
|
|
||||||
// PluginSet specifies enabled and disabled plugins for an extension point.
|
// PluginSet specifies enabled and disabled plugins for an extension point.
|
||||||
|
@ -757,6 +757,9 @@ func autoConvert_v1beta2_Plugins_To_config_Plugins(in *v1beta2.Plugins, out *con
|
|||||||
if err := Convert_v1beta2_PluginSet_To_config_PluginSet(&in.PostBind, &out.PostBind, s); err != nil {
|
if err := Convert_v1beta2_PluginSet_To_config_PluginSet(&in.PostBind, &out.PostBind, s); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := Convert_v1beta2_PluginSet_To_config_PluginSet(&in.MultiPoint, &out.MultiPoint, s); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -799,6 +802,9 @@ func autoConvert_config_Plugins_To_v1beta2_Plugins(in *config.Plugins, out *v1be
|
|||||||
if err := Convert_config_PluginSet_To_v1beta2_PluginSet(&in.PostBind, &out.PostBind, s); err != nil {
|
if err := Convert_config_PluginSet_To_v1beta2_PluginSet(&in.PostBind, &out.PostBind, s); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := Convert_config_PluginSet_To_v1beta2_PluginSet(&in.MultiPoint, &out.MultiPoint, s); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,30 +29,15 @@ import (
|
|||||||
// getDefaultPlugins returns the default set of plugins.
|
// getDefaultPlugins returns the default set of plugins.
|
||||||
func getDefaultPlugins() *v1beta3.Plugins {
|
func getDefaultPlugins() *v1beta3.Plugins {
|
||||||
plugins := &v1beta3.Plugins{
|
plugins := &v1beta3.Plugins{
|
||||||
QueueSort: v1beta3.PluginSet{
|
MultiPoint: v1beta3.PluginSet{
|
||||||
Enabled: []v1beta3.Plugin{
|
Enabled: []v1beta3.Plugin{
|
||||||
{Name: names.PrioritySort},
|
{Name: names.PrioritySort},
|
||||||
},
|
|
||||||
},
|
|
||||||
PreFilter: v1beta3.PluginSet{
|
|
||||||
Enabled: []v1beta3.Plugin{
|
|
||||||
{Name: names.NodeResourcesFit},
|
|
||||||
{Name: names.NodePorts},
|
|
||||||
{Name: names.VolumeRestrictions},
|
|
||||||
{Name: names.PodTopologySpread},
|
|
||||||
{Name: names.InterPodAffinity},
|
|
||||||
{Name: names.VolumeBinding},
|
|
||||||
{Name: names.NodeAffinity},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Filter: v1beta3.PluginSet{
|
|
||||||
Enabled: []v1beta3.Plugin{
|
|
||||||
{Name: names.NodeUnschedulable},
|
{Name: names.NodeUnschedulable},
|
||||||
{Name: names.NodeName},
|
{Name: names.NodeName},
|
||||||
{Name: names.TaintToleration},
|
{Name: names.TaintToleration, Weight: pointer.Int32(3)},
|
||||||
{Name: names.NodeAffinity},
|
{Name: names.NodeAffinity, Weight: pointer.Int32(2)},
|
||||||
{Name: names.NodePorts},
|
{Name: names.NodePorts},
|
||||||
{Name: names.NodeResourcesFit},
|
{Name: names.NodeResourcesFit, Weight: pointer.Int32(1)},
|
||||||
{Name: names.VolumeRestrictions},
|
{Name: names.VolumeRestrictions},
|
||||||
{Name: names.EBSLimits},
|
{Name: names.EBSLimits},
|
||||||
{Name: names.GCEPDLimits},
|
{Name: names.GCEPDLimits},
|
||||||
@ -60,57 +45,11 @@ func getDefaultPlugins() *v1beta3.Plugins {
|
|||||||
{Name: names.AzureDiskLimits},
|
{Name: names.AzureDiskLimits},
|
||||||
{Name: names.VolumeBinding},
|
{Name: names.VolumeBinding},
|
||||||
{Name: names.VolumeZone},
|
{Name: names.VolumeZone},
|
||||||
{Name: names.PodTopologySpread},
|
{Name: names.PodTopologySpread, Weight: pointer.Int32(2)},
|
||||||
{Name: names.InterPodAffinity},
|
{Name: names.InterPodAffinity, Weight: pointer.Int32(2)},
|
||||||
},
|
|
||||||
},
|
|
||||||
PostFilter: v1beta3.PluginSet{
|
|
||||||
Enabled: []v1beta3.Plugin{
|
|
||||||
{Name: names.DefaultPreemption},
|
{Name: names.DefaultPreemption},
|
||||||
},
|
{Name: names.NodeResourcesBalancedAllocation, Weight: pointer.Int32(1)},
|
||||||
},
|
{Name: names.ImageLocality, Weight: pointer.Int32(1)},
|
||||||
PreScore: v1beta3.PluginSet{
|
|
||||||
Enabled: []v1beta3.Plugin{
|
|
||||||
{Name: names.InterPodAffinity},
|
|
||||||
{Name: names.PodTopologySpread},
|
|
||||||
{Name: names.TaintToleration},
|
|
||||||
{Name: names.NodeAffinity},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Score: v1beta3.PluginSet{
|
|
||||||
Enabled: []v1beta3.Plugin{
|
|
||||||
{Name: names.NodeResourcesBalancedAllocation, Weight: pointer.Int32Ptr(1)},
|
|
||||||
{Name: names.ImageLocality, Weight: pointer.Int32Ptr(1)},
|
|
||||||
{Name: names.NodeResourcesFit, Weight: pointer.Int32Ptr(1)},
|
|
||||||
// Weight is doubled because:
|
|
||||||
// - This is a score coming from user preference.
|
|
||||||
{Name: names.InterPodAffinity, Weight: pointer.Int32Ptr(2)},
|
|
||||||
// Weight is doubled because:
|
|
||||||
// - This is a score coming from user preference.
|
|
||||||
{Name: names.NodeAffinity, Weight: pointer.Int32Ptr(2)},
|
|
||||||
// Weight is doubled because:
|
|
||||||
// - This is a score coming from user preference.
|
|
||||||
// - It makes its signal comparable to NodeResourcesFit.LeastAllocated.
|
|
||||||
{Name: names.PodTopologySpread, Weight: pointer.Int32Ptr(2)},
|
|
||||||
// Weight is tripled because:
|
|
||||||
// - This is a score coming from user preference.
|
|
||||||
// - Usage of node tainting to group nodes in the cluster is becoming a valid use-case more often
|
|
||||||
// for many user workloads
|
|
||||||
{Name: names.TaintToleration, Weight: pointer.Int32Ptr(3)},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Reserve: v1beta3.PluginSet{
|
|
||||||
Enabled: []v1beta3.Plugin{
|
|
||||||
{Name: names.VolumeBinding},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
PreBind: v1beta3.PluginSet{
|
|
||||||
Enabled: []v1beta3.Plugin{
|
|
||||||
{Name: names.VolumeBinding},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Bind: v1beta3.PluginSet{
|
|
||||||
Enabled: []v1beta3.Plugin{
|
|
||||||
{Name: names.DefaultBinder},
|
{Name: names.DefaultBinder},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -121,18 +60,12 @@ func getDefaultPlugins() *v1beta3.Plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func applyFeatureGates(config *v1beta3.Plugins) {
|
func applyFeatureGates(config *v1beta3.Plugins) {
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(features.VolumeCapacityPriority) {
|
|
||||||
config.Score.Enabled = append(config.Score.Enabled, v1beta3.Plugin{Name: names.VolumeBinding, Weight: pointer.Int32Ptr(1)})
|
|
||||||
}
|
|
||||||
|
|
||||||
if !utilfeature.DefaultFeatureGate.Enabled(features.DefaultPodTopologySpread) {
|
if !utilfeature.DefaultFeatureGate.Enabled(features.DefaultPodTopologySpread) {
|
||||||
// When feature is enabled, the default spreading is done by
|
// When feature is enabled, the default spreading is done by
|
||||||
// PodTopologySpread plugin, which is enabled by default.
|
// PodTopologySpread plugin, which is enabled by default.
|
||||||
klog.InfoS("Registering SelectorSpread plugin")
|
klog.InfoS("Registering SelectorSpread plugin")
|
||||||
s := v1beta3.Plugin{Name: names.SelectorSpread}
|
s := v1beta3.Plugin{Name: names.SelectorSpread, Weight: pointer.Int32Ptr(1)}
|
||||||
config.PreScore.Enabled = append(config.PreScore.Enabled, s)
|
config.MultiPoint.Enabled = append(config.MultiPoint.Enabled, s)
|
||||||
s.Weight = pointer.Int32Ptr(1)
|
|
||||||
config.Score.Enabled = append(config.Score.Enabled, s)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,6 +75,7 @@ func mergePlugins(defaultPlugins, customPlugins *v1beta3.Plugins) *v1beta3.Plugi
|
|||||||
return defaultPlugins
|
return defaultPlugins
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defaultPlugins.MultiPoint = mergePluginSet(defaultPlugins.MultiPoint, customPlugins.MultiPoint)
|
||||||
defaultPlugins.QueueSort = mergePluginSet(defaultPlugins.QueueSort, customPlugins.QueueSort)
|
defaultPlugins.QueueSort = mergePluginSet(defaultPlugins.QueueSort, customPlugins.QueueSort)
|
||||||
defaultPlugins.PreFilter = mergePluginSet(defaultPlugins.PreFilter, customPlugins.PreFilter)
|
defaultPlugins.PreFilter = mergePluginSet(defaultPlugins.PreFilter, customPlugins.PreFilter)
|
||||||
defaultPlugins.Filter = mergePluginSet(defaultPlugins.Filter, customPlugins.Filter)
|
defaultPlugins.Filter = mergePluginSet(defaultPlugins.Filter, customPlugins.Filter)
|
||||||
@ -166,9 +100,22 @@ func mergePluginSet(defaultPluginSet, customPluginSet v1beta3.PluginSet) v1beta3
|
|||||||
enabledCustomPlugins := make(map[string]pluginIndex)
|
enabledCustomPlugins := make(map[string]pluginIndex)
|
||||||
// replacedPluginIndex is a set of index of plugins, which have replaced the default plugins.
|
// replacedPluginIndex is a set of index of plugins, which have replaced the default plugins.
|
||||||
replacedPluginIndex := sets.NewInt()
|
replacedPluginIndex := sets.NewInt()
|
||||||
|
var disabled []v1beta3.Plugin
|
||||||
for _, disabledPlugin := range customPluginSet.Disabled {
|
for _, disabledPlugin := range customPluginSet.Disabled {
|
||||||
|
// if the user is manually disabling any (or all, with "*") default plugins for an extension point,
|
||||||
|
// we need to track that so that the MultiPoint extension logic in the framework can know to skip
|
||||||
|
// inserting unspecified default plugins to this point.
|
||||||
|
disabled = append(disabled, v1beta3.Plugin{Name: disabledPlugin.Name})
|
||||||
disabledPlugins.Insert(disabledPlugin.Name)
|
disabledPlugins.Insert(disabledPlugin.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// With MultiPoint, we may now have some disabledPlugins in the default registry
|
||||||
|
// For example, we enable PluginX with Filter+Score through MultiPoint but disable its Score plugin by default.
|
||||||
|
for _, disabledPlugin := range defaultPluginSet.Disabled {
|
||||||
|
disabled = append(disabled, v1beta3.Plugin{Name: disabledPlugin.Name})
|
||||||
|
disabledPlugins.Insert(disabledPlugin.Name)
|
||||||
|
}
|
||||||
|
|
||||||
for index, enabledPlugin := range customPluginSet.Enabled {
|
for index, enabledPlugin := range customPluginSet.Enabled {
|
||||||
enabledCustomPlugins[enabledPlugin.Name] = pluginIndex{index, enabledPlugin}
|
enabledCustomPlugins[enabledPlugin.Name] = pluginIndex{index, enabledPlugin}
|
||||||
}
|
}
|
||||||
@ -197,5 +144,5 @@ func mergePluginSet(defaultPluginSet, customPluginSet v1beta3.PluginSet) v1beta3
|
|||||||
enabledPlugins = append(enabledPlugins, plugin)
|
enabledPlugins = append(enabledPlugins, plugin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return v1beta3.PluginSet{Enabled: enabledPlugins}
|
return v1beta3.PluginSet{Enabled: enabledPlugins, Disabled: disabled}
|
||||||
}
|
}
|
||||||
|
@ -38,30 +38,15 @@ func TestApplyFeatureGates(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "Feature gates disabled",
|
name: "Feature gates disabled",
|
||||||
wantConfig: &v1beta3.Plugins{
|
wantConfig: &v1beta3.Plugins{
|
||||||
QueueSort: v1beta3.PluginSet{
|
MultiPoint: v1beta3.PluginSet{
|
||||||
Enabled: []v1beta3.Plugin{
|
Enabled: []v1beta3.Plugin{
|
||||||
{Name: names.PrioritySort},
|
{Name: names.PrioritySort},
|
||||||
},
|
|
||||||
},
|
|
||||||
PreFilter: v1beta3.PluginSet{
|
|
||||||
Enabled: []v1beta3.Plugin{
|
|
||||||
{Name: names.NodeResourcesFit},
|
|
||||||
{Name: names.NodePorts},
|
|
||||||
{Name: names.VolumeRestrictions},
|
|
||||||
{Name: names.PodTopologySpread},
|
|
||||||
{Name: names.InterPodAffinity},
|
|
||||||
{Name: names.VolumeBinding},
|
|
||||||
{Name: names.NodeAffinity},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Filter: v1beta3.PluginSet{
|
|
||||||
Enabled: []v1beta3.Plugin{
|
|
||||||
{Name: names.NodeUnschedulable},
|
{Name: names.NodeUnschedulable},
|
||||||
{Name: names.NodeName},
|
{Name: names.NodeName},
|
||||||
{Name: names.TaintToleration},
|
{Name: names.TaintToleration, Weight: pointer.Int32(3)},
|
||||||
{Name: names.NodeAffinity},
|
{Name: names.NodeAffinity, Weight: pointer.Int32(2)},
|
||||||
{Name: names.NodePorts},
|
{Name: names.NodePorts},
|
||||||
{Name: names.NodeResourcesFit},
|
{Name: names.NodeResourcesFit, Weight: pointer.Int32(1)},
|
||||||
{Name: names.VolumeRestrictions},
|
{Name: names.VolumeRestrictions},
|
||||||
{Name: names.EBSLimits},
|
{Name: names.EBSLimits},
|
||||||
{Name: names.GCEPDLimits},
|
{Name: names.GCEPDLimits},
|
||||||
@ -69,46 +54,11 @@ func TestApplyFeatureGates(t *testing.T) {
|
|||||||
{Name: names.AzureDiskLimits},
|
{Name: names.AzureDiskLimits},
|
||||||
{Name: names.VolumeBinding},
|
{Name: names.VolumeBinding},
|
||||||
{Name: names.VolumeZone},
|
{Name: names.VolumeZone},
|
||||||
{Name: names.PodTopologySpread},
|
{Name: names.PodTopologySpread, Weight: pointer.Int32(2)},
|
||||||
{Name: names.InterPodAffinity},
|
{Name: names.InterPodAffinity, Weight: pointer.Int32(2)},
|
||||||
},
|
|
||||||
},
|
|
||||||
PostFilter: v1beta3.PluginSet{
|
|
||||||
Enabled: []v1beta3.Plugin{
|
|
||||||
{Name: names.DefaultPreemption},
|
{Name: names.DefaultPreemption},
|
||||||
},
|
{Name: names.NodeResourcesBalancedAllocation, Weight: pointer.Int32(1)},
|
||||||
},
|
{Name: names.ImageLocality, Weight: pointer.Int32(1)},
|
||||||
PreScore: v1beta3.PluginSet{
|
|
||||||
Enabled: []v1beta3.Plugin{
|
|
||||||
{Name: names.InterPodAffinity},
|
|
||||||
{Name: names.PodTopologySpread},
|
|
||||||
{Name: names.TaintToleration},
|
|
||||||
{Name: names.NodeAffinity},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Score: v1beta3.PluginSet{
|
|
||||||
Enabled: []v1beta3.Plugin{
|
|
||||||
{Name: names.NodeResourcesBalancedAllocation, Weight: pointer.Int32Ptr(1)},
|
|
||||||
{Name: names.ImageLocality, Weight: pointer.Int32Ptr(1)},
|
|
||||||
{Name: names.NodeResourcesFit, Weight: pointer.Int32Ptr(1)},
|
|
||||||
{Name: names.InterPodAffinity, Weight: pointer.Int32Ptr(2)},
|
|
||||||
{Name: names.NodeAffinity, Weight: pointer.Int32Ptr(2)},
|
|
||||||
{Name: names.PodTopologySpread, Weight: pointer.Int32Ptr(2)},
|
|
||||||
{Name: names.TaintToleration, Weight: pointer.Int32Ptr(3)},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Reserve: v1beta3.PluginSet{
|
|
||||||
Enabled: []v1beta3.Plugin{
|
|
||||||
{Name: names.VolumeBinding},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
PreBind: v1beta3.PluginSet{
|
|
||||||
Enabled: []v1beta3.Plugin{
|
|
||||||
{Name: names.VolumeBinding},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Bind: v1beta3.PluginSet{
|
|
||||||
Enabled: []v1beta3.Plugin{
|
|
||||||
{Name: names.DefaultBinder},
|
{Name: names.DefaultBinder},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -120,30 +70,15 @@ func TestApplyFeatureGates(t *testing.T) {
|
|||||||
features.DefaultPodTopologySpread: false,
|
features.DefaultPodTopologySpread: false,
|
||||||
},
|
},
|
||||||
wantConfig: &v1beta3.Plugins{
|
wantConfig: &v1beta3.Plugins{
|
||||||
QueueSort: v1beta3.PluginSet{
|
MultiPoint: v1beta3.PluginSet{
|
||||||
Enabled: []v1beta3.Plugin{
|
Enabled: []v1beta3.Plugin{
|
||||||
{Name: names.PrioritySort},
|
{Name: names.PrioritySort},
|
||||||
},
|
|
||||||
},
|
|
||||||
PreFilter: v1beta3.PluginSet{
|
|
||||||
Enabled: []v1beta3.Plugin{
|
|
||||||
{Name: names.NodeResourcesFit},
|
|
||||||
{Name: names.NodePorts},
|
|
||||||
{Name: names.VolumeRestrictions},
|
|
||||||
{Name: names.PodTopologySpread},
|
|
||||||
{Name: names.InterPodAffinity},
|
|
||||||
{Name: names.VolumeBinding},
|
|
||||||
{Name: names.NodeAffinity},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Filter: v1beta3.PluginSet{
|
|
||||||
Enabled: []v1beta3.Plugin{
|
|
||||||
{Name: names.NodeUnschedulable},
|
{Name: names.NodeUnschedulable},
|
||||||
{Name: names.NodeName},
|
{Name: names.NodeName},
|
||||||
{Name: names.TaintToleration},
|
{Name: names.TaintToleration, Weight: pointer.Int32(3)},
|
||||||
{Name: names.NodeAffinity},
|
{Name: names.NodeAffinity, Weight: pointer.Int32(2)},
|
||||||
{Name: names.NodePorts},
|
{Name: names.NodePorts},
|
||||||
{Name: names.NodeResourcesFit},
|
{Name: names.NodeResourcesFit, Weight: pointer.Int32(1)},
|
||||||
{Name: names.VolumeRestrictions},
|
{Name: names.VolumeRestrictions},
|
||||||
{Name: names.EBSLimits},
|
{Name: names.EBSLimits},
|
||||||
{Name: names.GCEPDLimits},
|
{Name: names.GCEPDLimits},
|
||||||
@ -151,49 +86,13 @@ func TestApplyFeatureGates(t *testing.T) {
|
|||||||
{Name: names.AzureDiskLimits},
|
{Name: names.AzureDiskLimits},
|
||||||
{Name: names.VolumeBinding},
|
{Name: names.VolumeBinding},
|
||||||
{Name: names.VolumeZone},
|
{Name: names.VolumeZone},
|
||||||
{Name: names.PodTopologySpread},
|
{Name: names.PodTopologySpread, Weight: pointer.Int32(2)},
|
||||||
{Name: names.InterPodAffinity},
|
{Name: names.InterPodAffinity, Weight: pointer.Int32(2)},
|
||||||
},
|
|
||||||
},
|
|
||||||
PostFilter: v1beta3.PluginSet{
|
|
||||||
Enabled: []v1beta3.Plugin{
|
|
||||||
{Name: names.DefaultPreemption},
|
{Name: names.DefaultPreemption},
|
||||||
},
|
{Name: names.NodeResourcesBalancedAllocation, Weight: pointer.Int32(1)},
|
||||||
},
|
{Name: names.ImageLocality, Weight: pointer.Int32(1)},
|
||||||
PreScore: v1beta3.PluginSet{
|
|
||||||
Enabled: []v1beta3.Plugin{
|
|
||||||
{Name: names.InterPodAffinity},
|
|
||||||
{Name: names.PodTopologySpread},
|
|
||||||
{Name: names.TaintToleration},
|
|
||||||
{Name: names.NodeAffinity},
|
|
||||||
{Name: names.SelectorSpread},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Score: v1beta3.PluginSet{
|
|
||||||
Enabled: []v1beta3.Plugin{
|
|
||||||
{Name: names.NodeResourcesBalancedAllocation, Weight: pointer.Int32Ptr(1)},
|
|
||||||
{Name: names.ImageLocality, Weight: pointer.Int32Ptr(1)},
|
|
||||||
{Name: names.NodeResourcesFit, Weight: pointer.Int32Ptr(1)},
|
|
||||||
{Name: names.InterPodAffinity, Weight: pointer.Int32Ptr(2)},
|
|
||||||
{Name: names.NodeAffinity, Weight: pointer.Int32Ptr(2)},
|
|
||||||
{Name: names.PodTopologySpread, Weight: pointer.Int32Ptr(2)},
|
|
||||||
{Name: names.TaintToleration, Weight: pointer.Int32Ptr(3)},
|
|
||||||
{Name: names.SelectorSpread, Weight: pointer.Int32Ptr(1)},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Reserve: v1beta3.PluginSet{
|
|
||||||
Enabled: []v1beta3.Plugin{
|
|
||||||
{Name: names.VolumeBinding},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
PreBind: v1beta3.PluginSet{
|
|
||||||
Enabled: []v1beta3.Plugin{
|
|
||||||
{Name: names.VolumeBinding},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Bind: v1beta3.PluginSet{
|
|
||||||
Enabled: []v1beta3.Plugin{
|
|
||||||
{Name: names.DefaultBinder},
|
{Name: names.DefaultBinder},
|
||||||
|
{Name: names.SelectorSpread, Weight: pointer.Int32(1)},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -276,6 +175,9 @@ func TestMergePlugins(t *testing.T) {
|
|||||||
{Name: "CustomPlugin"},
|
{Name: "CustomPlugin"},
|
||||||
{Name: "DefaultPlugin2"},
|
{Name: "DefaultPlugin2"},
|
||||||
},
|
},
|
||||||
|
Disabled: []v1beta3.Plugin{
|
||||||
|
{Name: "DefaultPlugin2"},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -308,6 +210,9 @@ func TestMergePlugins(t *testing.T) {
|
|||||||
{Name: "DefaultPlugin1"},
|
{Name: "DefaultPlugin1"},
|
||||||
{Name: "DefaultPlugin2"},
|
{Name: "DefaultPlugin2"},
|
||||||
},
|
},
|
||||||
|
Disabled: []v1beta3.Plugin{
|
||||||
|
{Name: "*"},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -338,6 +243,9 @@ func TestMergePlugins(t *testing.T) {
|
|||||||
{Name: "DefaultPlugin2"},
|
{Name: "DefaultPlugin2"},
|
||||||
{Name: "DefaultPlugin1"},
|
{Name: "DefaultPlugin1"},
|
||||||
},
|
},
|
||||||
|
Disabled: []v1beta3.Plugin{
|
||||||
|
{Name: "*"},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -451,12 +359,197 @@ func TestMergePlugins(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "Append custom MultiPoint plugin",
|
||||||
|
customPlugins: &v1beta3.Plugins{
|
||||||
|
MultiPoint: v1beta3.PluginSet{
|
||||||
|
Enabled: []v1beta3.Plugin{
|
||||||
|
{Name: "CustomPlugin"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
defaultPlugins: &v1beta3.Plugins{
|
||||||
|
MultiPoint: v1beta3.PluginSet{
|
||||||
|
Enabled: []v1beta3.Plugin{
|
||||||
|
{Name: "DefaultPlugin1"},
|
||||||
|
{Name: "DefaultPlugin2"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedPlugins: &v1beta3.Plugins{
|
||||||
|
MultiPoint: v1beta3.PluginSet{
|
||||||
|
Enabled: []v1beta3.Plugin{
|
||||||
|
{Name: "DefaultPlugin1"},
|
||||||
|
{Name: "DefaultPlugin2"},
|
||||||
|
{Name: "CustomPlugin"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Append disabled Multipoint plugins",
|
||||||
|
customPlugins: &v1beta3.Plugins{
|
||||||
|
MultiPoint: v1beta3.PluginSet{
|
||||||
|
Enabled: []v1beta3.Plugin{
|
||||||
|
{Name: "CustomPlugin"},
|
||||||
|
{Name: "CustomPlugin2"},
|
||||||
|
},
|
||||||
|
Disabled: []v1beta3.Plugin{
|
||||||
|
{Name: "DefaultPlugin2"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Score: v1beta3.PluginSet{
|
||||||
|
Disabled: []v1beta3.Plugin{
|
||||||
|
{Name: "CustomPlugin2"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
defaultPlugins: &v1beta3.Plugins{
|
||||||
|
MultiPoint: v1beta3.PluginSet{
|
||||||
|
Enabled: []v1beta3.Plugin{
|
||||||
|
{Name: "DefaultPlugin1"},
|
||||||
|
{Name: "DefaultPlugin2"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedPlugins: &v1beta3.Plugins{
|
||||||
|
MultiPoint: v1beta3.PluginSet{
|
||||||
|
Enabled: []v1beta3.Plugin{
|
||||||
|
{Name: "DefaultPlugin1"},
|
||||||
|
{Name: "CustomPlugin"},
|
||||||
|
{Name: "CustomPlugin2"},
|
||||||
|
},
|
||||||
|
Disabled: []v1beta3.Plugin{
|
||||||
|
{Name: "DefaultPlugin2"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Score: v1beta3.PluginSet{
|
||||||
|
Disabled: []v1beta3.Plugin{
|
||||||
|
{Name: "CustomPlugin2"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "override default MultiPoint plugins with custom value",
|
||||||
|
customPlugins: &v1beta3.Plugins{
|
||||||
|
MultiPoint: v1beta3.PluginSet{
|
||||||
|
Enabled: []v1beta3.Plugin{
|
||||||
|
{Name: "DefaultPlugin", Weight: pointer.Int32(5)},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
defaultPlugins: &v1beta3.Plugins{
|
||||||
|
MultiPoint: v1beta3.PluginSet{
|
||||||
|
Enabled: []v1beta3.Plugin{
|
||||||
|
{Name: "DefaultPlugin"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedPlugins: &v1beta3.Plugins{
|
||||||
|
MultiPoint: v1beta3.PluginSet{
|
||||||
|
Enabled: []v1beta3.Plugin{
|
||||||
|
{Name: "DefaultPlugin", Weight: pointer.Int32(5)},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "disabled MultiPoint plugin in default set",
|
||||||
|
defaultPlugins: &v1beta3.Plugins{
|
||||||
|
MultiPoint: v1beta3.PluginSet{
|
||||||
|
Enabled: []v1beta3.Plugin{
|
||||||
|
{Name: "DefaultPlugin"},
|
||||||
|
},
|
||||||
|
Disabled: []v1beta3.Plugin{
|
||||||
|
{Name: "DefaultPlugin2"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
customPlugins: &v1beta3.Plugins{
|
||||||
|
MultiPoint: v1beta3.PluginSet{
|
||||||
|
Enabled: []v1beta3.Plugin{
|
||||||
|
{Name: "CustomPlugin"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedPlugins: &v1beta3.Plugins{
|
||||||
|
MultiPoint: v1beta3.PluginSet{
|
||||||
|
Enabled: []v1beta3.Plugin{
|
||||||
|
{Name: "DefaultPlugin"},
|
||||||
|
{Name: "CustomPlugin"},
|
||||||
|
},
|
||||||
|
Disabled: []v1beta3.Plugin{
|
||||||
|
{Name: "DefaultPlugin2"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "disabled MultiPoint plugin in default set for specific extension point",
|
||||||
|
defaultPlugins: &v1beta3.Plugins{
|
||||||
|
MultiPoint: v1beta3.PluginSet{
|
||||||
|
Enabled: []v1beta3.Plugin{
|
||||||
|
{Name: "DefaultPlugin"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Score: v1beta3.PluginSet{
|
||||||
|
Disabled: []v1beta3.Plugin{
|
||||||
|
{Name: "DefaultPlugin2"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
customPlugins: &v1beta3.Plugins{
|
||||||
|
MultiPoint: v1beta3.PluginSet{
|
||||||
|
Enabled: []v1beta3.Plugin{
|
||||||
|
{Name: "CustomPlugin"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedPlugins: &v1beta3.Plugins{
|
||||||
|
MultiPoint: v1beta3.PluginSet{
|
||||||
|
Enabled: []v1beta3.Plugin{
|
||||||
|
{Name: "DefaultPlugin"},
|
||||||
|
{Name: "CustomPlugin"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Score: v1beta3.PluginSet{
|
||||||
|
Disabled: []v1beta3.Plugin{
|
||||||
|
{Name: "DefaultPlugin2"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "multipoint with only disabled gets merged",
|
||||||
|
defaultPlugins: &v1beta3.Plugins{
|
||||||
|
MultiPoint: v1beta3.PluginSet{
|
||||||
|
Enabled: []v1beta3.Plugin{
|
||||||
|
{Name: "DefaultPlugin"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
customPlugins: &v1beta3.Plugins{
|
||||||
|
MultiPoint: v1beta3.PluginSet{
|
||||||
|
Disabled: []v1beta3.Plugin{
|
||||||
|
{Name: "DefaultPlugin"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedPlugins: &v1beta3.Plugins{
|
||||||
|
MultiPoint: v1beta3.PluginSet{
|
||||||
|
Disabled: []v1beta3.Plugin{
|
||||||
|
{Name: "DefaultPlugin"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
test.defaultPlugins = mergePlugins(test.defaultPlugins, test.customPlugins)
|
gotPlugins := mergePlugins(test.defaultPlugins, test.customPlugins)
|
||||||
if d := cmp.Diff(test.expectedPlugins, test.defaultPlugins); d != "" {
|
if d := cmp.Diff(test.expectedPlugins, gotPlugins); d != "" {
|
||||||
t.Fatalf("plugins mismatch (-want +got):\n%s", d)
|
t.Fatalf("plugins mismatch (-want +got):\n%s", d)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -42,6 +42,7 @@ func pluginsNames(p *v1beta3.Plugins) []string {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
extensions := []v1beta3.PluginSet{
|
extensions := []v1beta3.PluginSet{
|
||||||
|
p.MultiPoint,
|
||||||
p.PreFilter,
|
p.PreFilter,
|
||||||
p.Filter,
|
p.Filter,
|
||||||
p.PostFilter,
|
p.PostFilter,
|
||||||
@ -66,7 +67,6 @@ func pluginsNames(p *v1beta3.Plugins) []string {
|
|||||||
func setDefaults_KubeSchedulerProfile(prof *v1beta3.KubeSchedulerProfile) {
|
func setDefaults_KubeSchedulerProfile(prof *v1beta3.KubeSchedulerProfile) {
|
||||||
// Set default plugins.
|
// Set default plugins.
|
||||||
prof.Plugins = mergePlugins(getDefaultPlugins(), prof.Plugins)
|
prof.Plugins = mergePlugins(getDefaultPlugins(), prof.Plugins)
|
||||||
|
|
||||||
// Set default plugin configs.
|
// Set default plugin configs.
|
||||||
scheme := GetPluginArgConversionScheme()
|
scheme := GetPluginArgConversionScheme()
|
||||||
existingConfigs := sets.NewString()
|
existingConfigs := sets.NewString()
|
||||||
|
@ -325,30 +325,15 @@ func TestSchedulerDefaults(t *testing.T) {
|
|||||||
{
|
{
|
||||||
SchedulerName: pointer.StringPtr("custom-scheduler"),
|
SchedulerName: pointer.StringPtr("custom-scheduler"),
|
||||||
Plugins: &v1beta3.Plugins{
|
Plugins: &v1beta3.Plugins{
|
||||||
QueueSort: v1beta3.PluginSet{
|
MultiPoint: v1beta3.PluginSet{
|
||||||
Enabled: []v1beta3.Plugin{
|
Enabled: []v1beta3.Plugin{
|
||||||
{Name: names.PrioritySort},
|
{Name: names.PrioritySort},
|
||||||
},
|
|
||||||
},
|
|
||||||
PreFilter: v1beta3.PluginSet{
|
|
||||||
Enabled: []v1beta3.Plugin{
|
|
||||||
{Name: names.NodeResourcesFit},
|
|
||||||
{Name: names.NodePorts},
|
|
||||||
{Name: names.VolumeRestrictions},
|
|
||||||
{Name: names.PodTopologySpread},
|
|
||||||
{Name: names.InterPodAffinity},
|
|
||||||
{Name: names.VolumeBinding},
|
|
||||||
{Name: names.NodeAffinity},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Filter: v1beta3.PluginSet{
|
|
||||||
Enabled: []v1beta3.Plugin{
|
|
||||||
{Name: names.NodeUnschedulable},
|
{Name: names.NodeUnschedulable},
|
||||||
{Name: names.NodeName},
|
{Name: names.NodeName},
|
||||||
{Name: names.TaintToleration},
|
{Name: names.TaintToleration, Weight: pointer.Int32(3)},
|
||||||
{Name: names.NodeAffinity},
|
{Name: names.NodeAffinity, Weight: pointer.Int32(2)},
|
||||||
{Name: names.NodePorts},
|
{Name: names.NodePorts},
|
||||||
{Name: names.NodeResourcesFit},
|
{Name: names.NodeResourcesFit, Weight: pointer.Int32(1)},
|
||||||
{Name: names.VolumeRestrictions},
|
{Name: names.VolumeRestrictions},
|
||||||
{Name: names.EBSLimits},
|
{Name: names.EBSLimits},
|
||||||
{Name: names.GCEPDLimits},
|
{Name: names.GCEPDLimits},
|
||||||
@ -356,48 +341,21 @@ func TestSchedulerDefaults(t *testing.T) {
|
|||||||
{Name: names.AzureDiskLimits},
|
{Name: names.AzureDiskLimits},
|
||||||
{Name: names.VolumeBinding},
|
{Name: names.VolumeBinding},
|
||||||
{Name: names.VolumeZone},
|
{Name: names.VolumeZone},
|
||||||
{Name: names.PodTopologySpread},
|
{Name: names.PodTopologySpread, Weight: pointer.Int32(2)},
|
||||||
{Name: names.InterPodAffinity},
|
{Name: names.InterPodAffinity, Weight: pointer.Int32(2)},
|
||||||
},
|
|
||||||
},
|
|
||||||
PostFilter: v1beta3.PluginSet{
|
|
||||||
Enabled: []v1beta3.Plugin{
|
|
||||||
{Name: names.DefaultPreemption},
|
{Name: names.DefaultPreemption},
|
||||||
},
|
{Name: names.NodeResourcesBalancedAllocation, Weight: pointer.Int32(1)},
|
||||||
},
|
{Name: names.ImageLocality, Weight: pointer.Int32(1)},
|
||||||
PreScore: v1beta3.PluginSet{
|
{Name: names.DefaultBinder},
|
||||||
Enabled: []v1beta3.Plugin{
|
|
||||||
{Name: names.InterPodAffinity},
|
|
||||||
{Name: names.PodTopologySpread},
|
|
||||||
{Name: names.TaintToleration},
|
|
||||||
{Name: names.NodeAffinity},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Score: v1beta3.PluginSet{
|
|
||||||
Enabled: []v1beta3.Plugin{
|
|
||||||
{Name: names.NodeResourcesBalancedAllocation, Weight: pointer.Int32Ptr(1)},
|
|
||||||
{Name: names.ImageLocality, Weight: pointer.Int32Ptr(1)},
|
|
||||||
{Name: names.NodeResourcesFit, Weight: pointer.Int32Ptr(1)},
|
|
||||||
{Name: names.InterPodAffinity, Weight: pointer.Int32Ptr(2)},
|
|
||||||
{Name: names.NodeAffinity, Weight: pointer.Int32Ptr(2)},
|
|
||||||
{Name: names.PodTopologySpread, Weight: pointer.Int32Ptr(2)},
|
|
||||||
{Name: names.TaintToleration, Weight: pointer.Int32Ptr(3)},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Reserve: v1beta3.PluginSet{
|
|
||||||
Enabled: []v1beta3.Plugin{
|
|
||||||
{Name: names.VolumeBinding},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
PreBind: v1beta3.PluginSet{
|
|
||||||
Enabled: []v1beta3.Plugin{
|
|
||||||
{Name: names.VolumeBinding},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Bind: v1beta3.PluginSet{
|
Bind: v1beta3.PluginSet{
|
||||||
Enabled: []v1beta3.Plugin{
|
Enabled: []v1beta3.Plugin{
|
||||||
{Name: "BarPlugin"},
|
{Name: "BarPlugin"},
|
||||||
},
|
},
|
||||||
|
Disabled: []v1beta3.Plugin{
|
||||||
|
{Name: names.DefaultBinder},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PluginConfig: pluginConfigs,
|
PluginConfig: pluginConfigs,
|
||||||
|
@ -747,6 +747,9 @@ func autoConvert_v1beta3_Plugins_To_config_Plugins(in *v1beta3.Plugins, out *con
|
|||||||
if err := Convert_v1beta3_PluginSet_To_config_PluginSet(&in.PostBind, &out.PostBind, s); err != nil {
|
if err := Convert_v1beta3_PluginSet_To_config_PluginSet(&in.PostBind, &out.PostBind, s); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := Convert_v1beta3_PluginSet_To_config_PluginSet(&in.MultiPoint, &out.MultiPoint, s); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -789,6 +792,9 @@ func autoConvert_config_Plugins_To_v1beta3_Plugins(in *config.Plugins, out *v1be
|
|||||||
if err := Convert_config_PluginSet_To_v1beta3_PluginSet(&in.PostBind, &out.PostBind, s); err != nil {
|
if err := Convert_config_PluginSet_To_v1beta3_PluginSet(&in.PostBind, &out.PostBind, s); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := Convert_config_PluginSet_To_v1beta3_PluginSet(&in.MultiPoint, &out.MultiPoint, s); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -395,6 +395,7 @@ func (in *Plugins) DeepCopyInto(out *Plugins) {
|
|||||||
in.PreBind.DeepCopyInto(&out.PreBind)
|
in.PreBind.DeepCopyInto(&out.PreBind)
|
||||||
in.Bind.DeepCopyInto(&out.Bind)
|
in.Bind.DeepCopyInto(&out.Bind)
|
||||||
in.PostBind.DeepCopyInto(&out.PostBind)
|
in.PostBind.DeepCopyInto(&out.PostBind)
|
||||||
|
in.MultiPoint.DeepCopyInto(&out.MultiPoint)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -289,22 +289,6 @@ func NewFramework(r Registry, profile *config.KubeSchedulerProfile, opts ...Opti
|
|||||||
return f, nil
|
return f, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var totalPriority int64
|
|
||||||
for _, e := range profile.Plugins.Score.Enabled {
|
|
||||||
// a weight of zero is not permitted, plugins can be disabled explicitly
|
|
||||||
// when configured.
|
|
||||||
f.scorePluginWeight[e.Name] = int(e.Weight)
|
|
||||||
if f.scorePluginWeight[e.Name] == 0 {
|
|
||||||
f.scorePluginWeight[e.Name] = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checks totalPriority against MaxTotalScore to avoid overflow
|
|
||||||
if int64(f.scorePluginWeight[e.Name])*framework.MaxNodeScore > framework.MaxTotalScore-totalPriority {
|
|
||||||
return nil, fmt.Errorf("total score of Score plugins could overflow")
|
|
||||||
}
|
|
||||||
totalPriority += int64(f.scorePluginWeight[e.Name]) * framework.MaxNodeScore
|
|
||||||
}
|
|
||||||
|
|
||||||
// get needed plugins from config
|
// get needed plugins from config
|
||||||
pg := f.pluginsNeeded(profile.Plugins)
|
pg := f.pluginsNeeded(profile.Plugins)
|
||||||
|
|
||||||
@ -346,12 +330,28 @@ func NewFramework(r Registry, profile *config.KubeSchedulerProfile, opts ...Opti
|
|||||||
fillEventToPluginMap(p, options.clusterEventMap)
|
fillEventToPluginMap(p, options.clusterEventMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// initialize plugins per individual extension points
|
||||||
for _, e := range f.getExtensionPoints(profile.Plugins) {
|
for _, e := range f.getExtensionPoints(profile.Plugins) {
|
||||||
if err := updatePluginList(e.slicePtr, *e.plugins, pluginsMap); err != nil {
|
if err := updatePluginList(e.slicePtr, *e.plugins, pluginsMap); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// initialize multiPoint plugins to their expanded extension points
|
||||||
|
if len(profile.Plugins.MultiPoint.Enabled) > 0 {
|
||||||
|
if err := f.expandMultiPointPlugins(profile, pluginsMap); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(f.queueSortPlugins) != 1 {
|
||||||
|
return nil, fmt.Errorf("one queue sort plugin required for profile with scheduler name %q", profile.SchedulerName)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := getScoreWeights(f, pluginsMap, append(profile.Plugins.Score.Enabled, profile.Plugins.MultiPoint.Enabled...)); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// Verifying the score weights again since Plugin.Name() could return a different
|
// Verifying the score weights again since Plugin.Name() could return a different
|
||||||
// value from the one used in the configuration.
|
// value from the one used in the configuration.
|
||||||
for _, scorePlugin := range f.scorePlugins {
|
for _, scorePlugin := range f.scorePlugins {
|
||||||
@ -384,6 +384,106 @@ func NewFramework(r Registry, profile *config.KubeSchedulerProfile, opts ...Opti
|
|||||||
return f, nil
|
return f, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getScoreWeights makes sure that, between MultiPoint-Score plugin weights and individual Score
|
||||||
|
// plugin weights there is not an overflow of MaxTotalScore.
|
||||||
|
func getScoreWeights(f *frameworkImpl, pluginsMap map[string]framework.Plugin, plugins []config.Plugin) error {
|
||||||
|
var totalPriority int64
|
||||||
|
scorePlugins := reflect.ValueOf(&f.scorePlugins).Elem()
|
||||||
|
pluginType := scorePlugins.Type().Elem()
|
||||||
|
for _, e := range plugins {
|
||||||
|
pg := pluginsMap[e.Name]
|
||||||
|
if !reflect.TypeOf(pg).Implements(pluginType) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// We append MultiPoint plugins to the list of Score plugins. So if this plugin has already been
|
||||||
|
// encountered, let the individual Score weight take precedence.
|
||||||
|
if _, ok := f.scorePluginWeight[e.Name]; ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// a weight of zero is not permitted, plugins can be disabled explicitly
|
||||||
|
// when configured.
|
||||||
|
f.scorePluginWeight[e.Name] = int(e.Weight)
|
||||||
|
if f.scorePluginWeight[e.Name] == 0 {
|
||||||
|
f.scorePluginWeight[e.Name] = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks totalPriority against MaxTotalScore to avoid overflow
|
||||||
|
if int64(f.scorePluginWeight[e.Name])*framework.MaxNodeScore > framework.MaxTotalScore-totalPriority {
|
||||||
|
return fmt.Errorf("total score of Score plugins could overflow")
|
||||||
|
}
|
||||||
|
totalPriority += int64(f.scorePluginWeight[e.Name]) * framework.MaxNodeScore
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *frameworkImpl) expandMultiPointPlugins(profile *config.KubeSchedulerProfile, pluginsMap map[string]framework.Plugin) error {
|
||||||
|
// initialize MultiPoint plugins
|
||||||
|
for _, e := range f.getExtensionPoints(profile.Plugins) {
|
||||||
|
plugins := reflect.ValueOf(e.slicePtr).Elem()
|
||||||
|
pluginType := plugins.Type().Elem()
|
||||||
|
// build enabledSet of plugins already registered via normal extension points
|
||||||
|
// to check double registration
|
||||||
|
enabledSet := sets.NewString()
|
||||||
|
for _, plugin := range e.plugins.Enabled {
|
||||||
|
enabledSet.Insert(plugin.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
disabledSet := sets.NewString()
|
||||||
|
for _, disabledPlugin := range e.plugins.Disabled {
|
||||||
|
disabledSet.Insert(disabledPlugin.Name)
|
||||||
|
}
|
||||||
|
if disabledSet.Has("*") {
|
||||||
|
klog.V(4).InfoS("all plugins disabled for extension point, skipping MultiPoint expansion", "extension", pluginType)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// track plugins enabled via multipoint separately from those enabled by specific extensions,
|
||||||
|
// so that we can distinguish between double-registration and explicit overrides
|
||||||
|
multiPointEnabled := sets.NewString()
|
||||||
|
|
||||||
|
for _, ep := range profile.Plugins.MultiPoint.Enabled {
|
||||||
|
pg, ok := pluginsMap[ep.Name]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("%s %q does not exist", pluginType.Name(), ep.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// if this plugin doesn't implement the type for the current extension we're trying to expand, skip
|
||||||
|
if !reflect.TypeOf(pg).Implements(pluginType) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// a plugin that's enabled via MultiPoint can still be disabled for specific extension points
|
||||||
|
if disabledSet.Has(ep.Name) {
|
||||||
|
klog.V(4).InfoS("plugin disabled for extension point", "plugin", ep.Name, "extension", pluginType)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// if this plugin has already been enabled by the specific extension point,
|
||||||
|
// the user intent is to override the default plugin or make some other explicit setting.
|
||||||
|
// Either way, discard the MultiPoint value for this plugin.
|
||||||
|
// This maintains expected behavior for overriding default plugins (see https://github.com/kubernetes/kubernetes/pull/99582)
|
||||||
|
if enabledSet.Has(ep.Name) {
|
||||||
|
klog.InfoS("MultiPoint plugin is explicitly re-configured; overriding", "plugin", ep.Name)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// if this plugin is already registered via MultiPoint, then this is
|
||||||
|
// a double registration and an error in the config.
|
||||||
|
if multiPointEnabled.Has(ep.Name) {
|
||||||
|
return fmt.Errorf("plugin %q already registered as %q", ep.Name, pluginType.Name())
|
||||||
|
}
|
||||||
|
|
||||||
|
// we only need to update the multipoint set, since we already have the specific extension set from above
|
||||||
|
multiPointEnabled.Insert(ep.Name)
|
||||||
|
|
||||||
|
newPlugins := reflect.Append(plugins, reflect.ValueOf(pg))
|
||||||
|
plugins.Set(newPlugins)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func fillEventToPluginMap(p framework.Plugin, eventToPlugins map[framework.ClusterEvent]sets.String) {
|
func fillEventToPluginMap(p framework.Plugin, eventToPlugins map[framework.ClusterEvent]sets.String) {
|
||||||
ext, ok := p.(framework.EnqueueExtensions)
|
ext, ok := p.(framework.EnqueueExtensions)
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -1174,6 +1274,9 @@ func (f *frameworkImpl) pluginsNeeded(plugins *config.Plugins) map[string]config
|
|||||||
for _, e := range f.getExtensionPoints(plugins) {
|
for _, e := range f.getExtensionPoints(plugins) {
|
||||||
find(e.plugins)
|
find(e.plugins)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse MultiPoint separately since they are not returned by f.getExtensionPoints()
|
||||||
|
find(&plugins.MultiPoint)
|
||||||
return pgMap
|
return pgMap
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,6 +119,10 @@ func (pl *TestScorePlugin) Name() string {
|
|||||||
return pl.name
|
return pl.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (pl *TestScorePlugin) PreScore(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodes []*v1.Node) *framework.Status {
|
||||||
|
return framework.NewStatus(framework.Code(pl.inj.PreScoreStatus), "injected status")
|
||||||
|
}
|
||||||
|
|
||||||
func (pl *TestScorePlugin) Score(ctx context.Context, state *framework.CycleState, p *v1.Pod, nodeName string) (int64, *framework.Status) {
|
func (pl *TestScorePlugin) Score(ctx context.Context, state *framework.CycleState, p *v1.Pod, nodeName string) (int64, *framework.Status) {
|
||||||
return setScoreRes(pl.inj)
|
return setScoreRes(pl.inj)
|
||||||
}
|
}
|
||||||
@ -490,6 +494,281 @@ func TestNewFrameworkErrors(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNewFrameworkMultiPointExpansion(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
plugins *config.Plugins
|
||||||
|
wantPlugins *config.Plugins
|
||||||
|
wantErr string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "plugin expansion",
|
||||||
|
plugins: &config.Plugins{
|
||||||
|
MultiPoint: config.PluginSet{
|
||||||
|
Enabled: []config.Plugin{
|
||||||
|
{Name: testPlugin, Weight: 5},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantPlugins: &config.Plugins{
|
||||||
|
QueueSort: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
PreFilter: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
Filter: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
PostFilter: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
PreScore: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
Score: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin, Weight: 5}}},
|
||||||
|
Reserve: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
Permit: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
PreBind: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
Bind: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
PostBind: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "disable MultiPoint plugin at some extension points",
|
||||||
|
plugins: &config.Plugins{
|
||||||
|
MultiPoint: config.PluginSet{
|
||||||
|
Enabled: []config.Plugin{
|
||||||
|
{Name: testPlugin},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
PreScore: config.PluginSet{
|
||||||
|
Disabled: []config.Plugin{
|
||||||
|
{Name: testPlugin},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Score: config.PluginSet{
|
||||||
|
Disabled: []config.Plugin{
|
||||||
|
{Name: testPlugin},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantPlugins: &config.Plugins{
|
||||||
|
QueueSort: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
PreFilter: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
Filter: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
PostFilter: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
Reserve: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
Permit: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
PreBind: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
Bind: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
PostBind: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Multiple MultiPoint plugins",
|
||||||
|
plugins: &config.Plugins{
|
||||||
|
MultiPoint: config.PluginSet{
|
||||||
|
Enabled: []config.Plugin{
|
||||||
|
{Name: testPlugin},
|
||||||
|
{Name: scorePlugin1},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantPlugins: &config.Plugins{
|
||||||
|
QueueSort: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
PreFilter: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
Filter: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
PostFilter: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
PreScore: config.PluginSet{Enabled: []config.Plugin{
|
||||||
|
{Name: testPlugin},
|
||||||
|
{Name: scorePlugin1},
|
||||||
|
}},
|
||||||
|
Score: config.PluginSet{Enabled: []config.Plugin{
|
||||||
|
{Name: testPlugin, Weight: 1},
|
||||||
|
{Name: scorePlugin1, Weight: 1},
|
||||||
|
}},
|
||||||
|
Reserve: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
Permit: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
PreBind: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
Bind: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
PostBind: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "disable MultiPoint extension",
|
||||||
|
plugins: &config.Plugins{
|
||||||
|
MultiPoint: config.PluginSet{
|
||||||
|
Enabled: []config.Plugin{
|
||||||
|
{Name: testPlugin},
|
||||||
|
{Name: scorePlugin1},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
PreScore: config.PluginSet{
|
||||||
|
Disabled: []config.Plugin{
|
||||||
|
{Name: "*"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantPlugins: &config.Plugins{
|
||||||
|
QueueSort: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
PreFilter: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
Filter: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
PostFilter: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
Score: config.PluginSet{Enabled: []config.Plugin{
|
||||||
|
{Name: testPlugin, Weight: 1},
|
||||||
|
{Name: scorePlugin1, Weight: 1},
|
||||||
|
}},
|
||||||
|
Reserve: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
Permit: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
PreBind: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
Bind: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
PostBind: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Reorder MultiPoint plugins (specified extension takes precedence)",
|
||||||
|
plugins: &config.Plugins{
|
||||||
|
MultiPoint: config.PluginSet{
|
||||||
|
Enabled: []config.Plugin{
|
||||||
|
{Name: scoreWithNormalizePlugin1},
|
||||||
|
{Name: testPlugin},
|
||||||
|
{Name: scorePlugin1},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Score: config.PluginSet{
|
||||||
|
Enabled: []config.Plugin{
|
||||||
|
{Name: scorePlugin1},
|
||||||
|
{Name: testPlugin},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantPlugins: &config.Plugins{
|
||||||
|
QueueSort: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
PreFilter: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
Filter: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
PostFilter: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
PreScore: config.PluginSet{Enabled: []config.Plugin{
|
||||||
|
{Name: testPlugin},
|
||||||
|
{Name: scorePlugin1},
|
||||||
|
}},
|
||||||
|
Score: config.PluginSet{Enabled: []config.Plugin{
|
||||||
|
{Name: scorePlugin1, Weight: 1},
|
||||||
|
{Name: testPlugin, Weight: 1},
|
||||||
|
{Name: scoreWithNormalizePlugin1, Weight: 1},
|
||||||
|
}},
|
||||||
|
Reserve: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
Permit: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
PreBind: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
Bind: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
PostBind: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Override MultiPoint plugins weights",
|
||||||
|
plugins: &config.Plugins{
|
||||||
|
MultiPoint: config.PluginSet{
|
||||||
|
Enabled: []config.Plugin{
|
||||||
|
{Name: testPlugin},
|
||||||
|
{Name: scorePlugin1},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Score: config.PluginSet{
|
||||||
|
Enabled: []config.Plugin{
|
||||||
|
{Name: scorePlugin1, Weight: 5},
|
||||||
|
{Name: testPlugin, Weight: 3},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantPlugins: &config.Plugins{
|
||||||
|
QueueSort: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
PreFilter: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
Filter: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
PostFilter: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
PreScore: config.PluginSet{Enabled: []config.Plugin{
|
||||||
|
{Name: testPlugin},
|
||||||
|
{Name: scorePlugin1},
|
||||||
|
}},
|
||||||
|
Score: config.PluginSet{Enabled: []config.Plugin{
|
||||||
|
{Name: scorePlugin1, Weight: 5},
|
||||||
|
{Name: testPlugin, Weight: 3},
|
||||||
|
}},
|
||||||
|
Reserve: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
Permit: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
PreBind: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
Bind: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
PostBind: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "disable and enable MultiPoint plugins with '*'",
|
||||||
|
plugins: &config.Plugins{
|
||||||
|
MultiPoint: config.PluginSet{
|
||||||
|
Enabled: []config.Plugin{
|
||||||
|
{Name: queueSortPlugin},
|
||||||
|
{Name: bindPlugin},
|
||||||
|
{Name: scorePlugin1},
|
||||||
|
},
|
||||||
|
Disabled: []config.Plugin{
|
||||||
|
{Name: "*"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantPlugins: &config.Plugins{
|
||||||
|
QueueSort: config.PluginSet{Enabled: []config.Plugin{{Name: queueSortPlugin}}},
|
||||||
|
PreScore: config.PluginSet{Enabled: []config.Plugin{
|
||||||
|
{Name: scorePlugin1},
|
||||||
|
}},
|
||||||
|
Score: config.PluginSet{Enabled: []config.Plugin{
|
||||||
|
{Name: scorePlugin1, Weight: 1},
|
||||||
|
}},
|
||||||
|
Bind: config.PluginSet{Enabled: []config.Plugin{{Name: bindPlugin}}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "disable and enable MultiPoint plugin by name",
|
||||||
|
plugins: &config.Plugins{
|
||||||
|
MultiPoint: config.PluginSet{
|
||||||
|
Enabled: []config.Plugin{
|
||||||
|
{Name: bindPlugin},
|
||||||
|
{Name: queueSortPlugin},
|
||||||
|
{Name: scorePlugin1},
|
||||||
|
},
|
||||||
|
Disabled: []config.Plugin{
|
||||||
|
{Name: scorePlugin1},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantPlugins: &config.Plugins{
|
||||||
|
QueueSort: config.PluginSet{Enabled: []config.Plugin{{Name: queueSortPlugin}}},
|
||||||
|
PreScore: config.PluginSet{Enabled: []config.Plugin{
|
||||||
|
{Name: scorePlugin1},
|
||||||
|
}},
|
||||||
|
Score: config.PluginSet{Enabled: []config.Plugin{
|
||||||
|
{Name: scorePlugin1, Weight: 1},
|
||||||
|
}},
|
||||||
|
Bind: config.PluginSet{Enabled: []config.Plugin{{Name: bindPlugin}}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Expect 'already registered' error",
|
||||||
|
plugins: &config.Plugins{
|
||||||
|
MultiPoint: config.PluginSet{
|
||||||
|
Enabled: []config.Plugin{
|
||||||
|
{Name: testPlugin},
|
||||||
|
{Name: testPlugin},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: "already registered",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range tests {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
fw, err := NewFramework(registry, &config.KubeSchedulerProfile{Plugins: tc.plugins})
|
||||||
|
if (err != nil && tc.wantErr == "") || (err == nil && tc.wantErr != "") || (err != nil && !strings.Contains(err.Error(), tc.wantErr)) {
|
||||||
|
t.Errorf("Unexpected error, got %v, expect: %s", err, tc.wantErr)
|
||||||
|
}
|
||||||
|
if tc.wantErr == "" {
|
||||||
|
if diff := cmp.Diff(tc.wantPlugins, fw.ListPlugins()); diff != "" {
|
||||||
|
t.Errorf("Unexpected eventToPlugin map (-want,+got):%s", diff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// fakeNoopPlugin doesn't implement interface framework.EnqueueExtensions.
|
// fakeNoopPlugin doesn't implement interface framework.EnqueueExtensions.
|
||||||
type fakeNoopPlugin struct{}
|
type fakeNoopPlugin struct{}
|
||||||
|
|
||||||
|
@ -20,7 +20,6 @@ package profile
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/client-go/kubernetes/scheme"
|
"k8s.io/client-go/kubernetes/scheme"
|
||||||
@ -55,13 +54,13 @@ func NewMap(cfgs []config.KubeSchedulerProfile, r frameworkruntime.Registry, rec
|
|||||||
v := cfgValidator{m: m}
|
v := cfgValidator{m: m}
|
||||||
|
|
||||||
for _, cfg := range cfgs {
|
for _, cfg := range cfgs {
|
||||||
if err := v.validate(cfg); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
p, err := newProfile(cfg, r, recorderFact, opts...)
|
p, err := newProfile(cfg, r, recorderFact, opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("creating profile for scheduler name %s: %v", cfg.SchedulerName, err)
|
return nil, fmt.Errorf("creating profile for scheduler name %s: %v", cfg.SchedulerName, err)
|
||||||
}
|
}
|
||||||
|
if err := v.validate(cfg, p); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
m[cfg.SchedulerName] = p
|
m[cfg.SchedulerName] = p
|
||||||
}
|
}
|
||||||
return m, nil
|
return m, nil
|
||||||
@ -86,20 +85,18 @@ type cfgValidator struct {
|
|||||||
queueSortArgs runtime.Object
|
queueSortArgs runtime.Object
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *cfgValidator) validate(cfg config.KubeSchedulerProfile) error {
|
func (v *cfgValidator) validate(cfg config.KubeSchedulerProfile, f framework.Framework) error {
|
||||||
if len(cfg.SchedulerName) == 0 {
|
if len(f.ProfileName()) == 0 {
|
||||||
return errors.New("scheduler name is needed")
|
return errors.New("scheduler name is needed")
|
||||||
}
|
}
|
||||||
if cfg.Plugins == nil {
|
if cfg.Plugins == nil {
|
||||||
return fmt.Errorf("plugins required for profile with scheduler name %q", cfg.SchedulerName)
|
return fmt.Errorf("plugins required for profile with scheduler name %q", f.ProfileName())
|
||||||
}
|
}
|
||||||
if v.m[cfg.SchedulerName] != nil {
|
if v.m[f.ProfileName()] != nil {
|
||||||
return fmt.Errorf("duplicate profile with scheduler name %q", cfg.SchedulerName)
|
return fmt.Errorf("duplicate profile with scheduler name %q", f.ProfileName())
|
||||||
}
|
}
|
||||||
if len(cfg.Plugins.QueueSort.Enabled) != 1 {
|
|
||||||
return fmt.Errorf("one queue sort plugin required for profile with scheduler name %q", cfg.SchedulerName)
|
queueSort := f.ListPlugins().QueueSort.Enabled[0].Name
|
||||||
}
|
|
||||||
queueSort := cfg.Plugins.QueueSort.Enabled[0].Name
|
|
||||||
var queueSortArgs runtime.Object
|
var queueSortArgs runtime.Object
|
||||||
for _, plCfg := range cfg.PluginConfig {
|
for _, plCfg := range cfg.PluginConfig {
|
||||||
if plCfg.Name == queueSort {
|
if plCfg.Name == queueSort {
|
||||||
|
@ -31,10 +31,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var fakeRegistry = frameworkruntime.Registry{
|
var fakeRegistry = frameworkruntime.Registry{
|
||||||
"QueueSort": newFakePlugin,
|
"QueueSort": newFakePlugin("QueueSort"),
|
||||||
"Bind1": newFakePlugin,
|
"Bind1": newFakePlugin("Bind1"),
|
||||||
"Bind2": newFakePlugin,
|
"Bind2": newFakePlugin("Bind2"),
|
||||||
"Another": newFakePlugin,
|
"Another": newFakePlugin("Another"),
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewMap(t *testing.T) {
|
func TestNewMap(t *testing.T) {
|
||||||
@ -260,10 +260,12 @@ func TestNewMap(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type fakePlugin struct{}
|
type fakePlugin struct {
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
func (p *fakePlugin) Name() string {
|
func (p *fakePlugin) Name() string {
|
||||||
return ""
|
return p.name
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *fakePlugin) Less(*framework.QueuedPodInfo, *framework.QueuedPodInfo) bool {
|
func (p *fakePlugin) Less(*framework.QueuedPodInfo, *framework.QueuedPodInfo) bool {
|
||||||
@ -274,8 +276,10 @@ func (p *fakePlugin) Bind(context.Context, *framework.CycleState, *v1.Pod, strin
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newFakePlugin(_ runtime.Object, _ framework.Handle) (framework.Plugin, error) {
|
func newFakePlugin(name string) func(object runtime.Object, handle framework.Handle) (framework.Plugin, error) {
|
||||||
return &fakePlugin{}, nil
|
return func(_ runtime.Object, _ framework.Handle) (framework.Plugin, error) {
|
||||||
|
return &fakePlugin{name: name}, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func nilRecorderFactory(_ string) events.EventRecorder {
|
func nilRecorderFactory(_ string) events.EventRecorder {
|
||||||
|
@ -191,6 +191,9 @@ type Plugins struct {
|
|||||||
|
|
||||||
// PostBind is a list of plugins that should be invoked after a pod is successfully bound.
|
// PostBind is a list of plugins that should be invoked after a pod is successfully bound.
|
||||||
PostBind PluginSet `json:"postBind,omitempty"`
|
PostBind PluginSet `json:"postBind,omitempty"`
|
||||||
|
|
||||||
|
// MultiPoint is a simplified config section to enable plugins for all valid extension points.
|
||||||
|
MultiPoint PluginSet `json:"multiPoint,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// PluginSet specifies enabled and disabled plugins for an extension point.
|
// PluginSet specifies enabled and disabled plugins for an extension point.
|
||||||
|
@ -452,6 +452,7 @@ func (in *Plugins) DeepCopyInto(out *Plugins) {
|
|||||||
in.PreBind.DeepCopyInto(&out.PreBind)
|
in.PreBind.DeepCopyInto(&out.PreBind)
|
||||||
in.Bind.DeepCopyInto(&out.Bind)
|
in.Bind.DeepCopyInto(&out.Bind)
|
||||||
in.PostBind.DeepCopyInto(&out.PostBind)
|
in.PostBind.DeepCopyInto(&out.PostBind)
|
||||||
|
in.MultiPoint.DeepCopyInto(&out.MultiPoint)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,6 +184,24 @@ type Plugins struct {
|
|||||||
|
|
||||||
// PostBind is a list of plugins that should be invoked after a pod is successfully bound.
|
// PostBind is a list of plugins that should be invoked after a pod is successfully bound.
|
||||||
PostBind PluginSet `json:"postBind,omitempty"`
|
PostBind PluginSet `json:"postBind,omitempty"`
|
||||||
|
|
||||||
|
// MultiPoint is a simplified config section to enable plugins for all valid extension points.
|
||||||
|
// Plugins enabled through MultiPoint will automatically register for every individual extension
|
||||||
|
// point the plugin has implemented. Disabling a plugin through MultiPoint disables that behavior.
|
||||||
|
// The same is true for disabling "*" through MultiPoint (no default plugins will be automatically registered).
|
||||||
|
// Plugins can still be disabled through their individual extension points.
|
||||||
|
//
|
||||||
|
// In terms of precedence, plugin config follows this basic hierarchy
|
||||||
|
// 1. Specific extension points
|
||||||
|
// 2. Explicitly configured MultiPoint plugins
|
||||||
|
// 3. The set of default plugins, as MultiPoint plugins
|
||||||
|
// This implies that a higher precedence plugin will run first and overwrite any settings within MultiPoint.
|
||||||
|
// Explicitly user-configured plugins also take a higher precedence over default plugins.
|
||||||
|
// Within this hierarchy, an Enabled setting takes precedence over Disabled. For example, if a plugin is
|
||||||
|
// set in both `multiPoint.Enabled` and `multiPoint.Disabled`, the plugin will be enabled. Similarly,
|
||||||
|
// including `multiPoint.Disabled = '*'` and `multiPoint.Enabled = pluginA` will still register that specific
|
||||||
|
// plugin through MultiPoint. This follows the same behavior as all other extension point configurations.
|
||||||
|
MultiPoint PluginSet `json:"multiPoint,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// PluginSet specifies enabled and disabled plugins for an extension point.
|
// PluginSet specifies enabled and disabled plugins for an extension point.
|
||||||
|
@ -442,6 +442,7 @@ func (in *Plugins) DeepCopyInto(out *Plugins) {
|
|||||||
in.PreBind.DeepCopyInto(&out.PreBind)
|
in.PreBind.DeepCopyInto(&out.PreBind)
|
||||||
in.Bind.DeepCopyInto(&out.Bind)
|
in.Bind.DeepCopyInto(&out.Bind)
|
||||||
in.PostBind.DeepCopyInto(&out.PostBind)
|
in.PostBind.DeepCopyInto(&out.PostBind)
|
||||||
|
in.MultiPoint.DeepCopyInto(&out.MultiPoint)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1259,6 +1259,11 @@ func TestBindPlugin(t *testing.T) {
|
|||||||
Profiles: []v1beta3.KubeSchedulerProfile{{
|
Profiles: []v1beta3.KubeSchedulerProfile{{
|
||||||
SchedulerName: pointer.StringPtr(v1.DefaultSchedulerName),
|
SchedulerName: pointer.StringPtr(v1.DefaultSchedulerName),
|
||||||
Plugins: &v1beta3.Plugins{
|
Plugins: &v1beta3.Plugins{
|
||||||
|
MultiPoint: v1beta3.PluginSet{
|
||||||
|
Disabled: []v1beta3.Plugin{
|
||||||
|
{Name: defaultbinder.Name},
|
||||||
|
},
|
||||||
|
},
|
||||||
Reserve: v1beta3.PluginSet{
|
Reserve: v1beta3.PluginSet{
|
||||||
Enabled: []v1beta3.Plugin{{Name: reservePlugin.Name()}},
|
Enabled: []v1beta3.Plugin{{Name: reservePlugin.Name()}},
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user