Use PodTopologySpread for default spreading
Under the feature gate DefaultPodTopologySpread, which will disable the legacy DefaultPodTopologySpread plugin from the default algorithm providers. Signed-off-by: Aldo Culquicondor <acondor@google.com>
This commit is contained in:
@@ -11,6 +11,7 @@ go_library(
|
||||
srcs = ["registry.go"],
|
||||
importpath = "k8s.io/kubernetes/pkg/scheduler/algorithmprovider",
|
||||
deps = [
|
||||
"//pkg/features:go_default_library",
|
||||
"//pkg/scheduler/apis/config:go_default_library",
|
||||
"//pkg/scheduler/framework/plugins/defaultbinder:go_default_library",
|
||||
"//pkg/scheduler/framework/plugins/defaultpodtopologyspread:go_default_library",
|
||||
@@ -29,6 +30,8 @@ go_library(
|
||||
"//pkg/scheduler/framework/plugins/volumebinding:go_default_library",
|
||||
"//pkg/scheduler/framework/plugins/volumerestrictions:go_default_library",
|
||||
"//pkg/scheduler/framework/plugins/volumezone:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//vendor/k8s.io/klog/v2:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -37,6 +40,7 @@ go_test(
|
||||
srcs = ["registry_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/features:go_default_library",
|
||||
"//pkg/scheduler/apis/config:go_default_library",
|
||||
"//pkg/scheduler/framework/plugins/defaultbinder:go_default_library",
|
||||
"//pkg/scheduler/framework/plugins/defaultpodtopologyspread:go_default_library",
|
||||
@@ -55,6 +59,9 @@ go_test(
|
||||
"//pkg/scheduler/framework/plugins/volumebinding:go_default_library",
|
||||
"//pkg/scheduler/framework/plugins/volumerestrictions:go_default_library",
|
||||
"//pkg/scheduler/framework/plugins/volumezone:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//staging/src/k8s.io/component-base/featuregate:go_default_library",
|
||||
"//staging/src/k8s.io/component-base/featuregate/testing:go_default_library",
|
||||
"//vendor/github.com/google/go-cmp/cmp:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -20,6 +20,9 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/klog/v2"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
schedulerapi "k8s.io/kubernetes/pkg/scheduler/apis/config"
|
||||
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/defaultbinder"
|
||||
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/defaultpodtopologyspread"
|
||||
@@ -49,7 +52,10 @@ type Registry map[string]*schedulerapi.Plugins
|
||||
// NewRegistry returns an algorithm provider registry instance.
|
||||
func NewRegistry() Registry {
|
||||
defaultConfig := getDefaultConfig()
|
||||
applyFeatureGates(defaultConfig)
|
||||
|
||||
caConfig := getClusterAutoscalerConfig()
|
||||
applyFeatureGates(caConfig)
|
||||
|
||||
return Registry{
|
||||
schedulerapi.SchedulerDefaultProviderName: defaultConfig,
|
||||
@@ -106,7 +112,6 @@ func getDefaultConfig() *schedulerapi.Plugins {
|
||||
Enabled: []schedulerapi.Plugin{
|
||||
{Name: interpodaffinity.Name},
|
||||
{Name: podtopologyspread.Name},
|
||||
{Name: defaultpodtopologyspread.Name},
|
||||
{Name: tainttoleration.Name},
|
||||
},
|
||||
},
|
||||
@@ -122,7 +127,6 @@ func getDefaultConfig() *schedulerapi.Plugins {
|
||||
// - This is a score coming from user preference.
|
||||
// - It makes its signal comparable to NodeResourcesLeastAllocated.
|
||||
{Name: podtopologyspread.Name, Weight: 2},
|
||||
{Name: defaultpodtopologyspread.Name, Weight: 1},
|
||||
{Name: tainttoleration.Name, Weight: 1},
|
||||
},
|
||||
},
|
||||
@@ -164,3 +168,15 @@ func getClusterAutoscalerConfig() *schedulerapi.Plugins {
|
||||
}
|
||||
return caConfig
|
||||
}
|
||||
|
||||
func applyFeatureGates(config *schedulerapi.Plugins) {
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.DefaultPodTopologySpread) {
|
||||
// When feature is enabled, the default spreading is done by
|
||||
// PodTopologySpread plugin, which is enabled by default.
|
||||
klog.Infof("Registering DefaultPodTopologySpread plugin")
|
||||
s := schedulerapi.Plugin{Name: defaultpodtopologyspread.Name}
|
||||
config.PreScore.Enabled = append(config.PreScore.Enabled, s)
|
||||
s.Weight = 1
|
||||
config.Score.Enabled = append(config.Score.Enabled, s)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,11 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"k8s.io/component-base/featuregate"
|
||||
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
schedulerapi "k8s.io/kubernetes/pkg/scheduler/apis/config"
|
||||
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/defaultbinder"
|
||||
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/defaultpodtopologyspread"
|
||||
@@ -79,8 +83,8 @@ func TestClusterAutoscalerProvider(t *testing.T) {
|
||||
Enabled: []schedulerapi.Plugin{
|
||||
{Name: interpodaffinity.Name},
|
||||
{Name: podtopologyspread.Name},
|
||||
{Name: defaultpodtopologyspread.Name},
|
||||
{Name: tainttoleration.Name},
|
||||
{Name: defaultpodtopologyspread.Name},
|
||||
},
|
||||
},
|
||||
Score: &schedulerapi.PluginSet{
|
||||
@@ -92,8 +96,8 @@ func TestClusterAutoscalerProvider(t *testing.T) {
|
||||
{Name: nodeaffinity.Name, Weight: 1},
|
||||
{Name: nodepreferavoidpods.Name, Weight: 10000},
|
||||
{Name: podtopologyspread.Name, Weight: 2},
|
||||
{Name: defaultpodtopologyspread.Name, Weight: 1},
|
||||
{Name: tainttoleration.Name, Weight: 1},
|
||||
{Name: defaultpodtopologyspread.Name, Weight: 1},
|
||||
},
|
||||
},
|
||||
Reserve: &schedulerapi.PluginSet{
|
||||
@@ -129,3 +133,191 @@ func TestClusterAutoscalerProvider(t *testing.T) {
|
||||
t.Errorf("unexpected config diff (-want, +got): %s", diff)
|
||||
}
|
||||
}
|
||||
|
||||
func TestApplyFeatureGates(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
feature featuregate.Feature
|
||||
wantConfig *schedulerapi.Plugins
|
||||
}{
|
||||
{
|
||||
name: "Feature gates disabled",
|
||||
wantConfig: &schedulerapi.Plugins{
|
||||
QueueSort: &schedulerapi.PluginSet{
|
||||
Enabled: []schedulerapi.Plugin{
|
||||
{Name: queuesort.Name},
|
||||
},
|
||||
},
|
||||
PreFilter: &schedulerapi.PluginSet{
|
||||
Enabled: []schedulerapi.Plugin{
|
||||
{Name: noderesources.FitName},
|
||||
{Name: nodeports.Name},
|
||||
{Name: podtopologyspread.Name},
|
||||
{Name: interpodaffinity.Name},
|
||||
},
|
||||
},
|
||||
Filter: &schedulerapi.PluginSet{
|
||||
Enabled: []schedulerapi.Plugin{
|
||||
{Name: nodeunschedulable.Name},
|
||||
{Name: noderesources.FitName},
|
||||
{Name: nodename.Name},
|
||||
{Name: nodeports.Name},
|
||||
{Name: nodeaffinity.Name},
|
||||
{Name: volumerestrictions.Name},
|
||||
{Name: tainttoleration.Name},
|
||||
{Name: nodevolumelimits.EBSName},
|
||||
{Name: nodevolumelimits.GCEPDName},
|
||||
{Name: nodevolumelimits.CSIName},
|
||||
{Name: nodevolumelimits.AzureDiskName},
|
||||
{Name: volumebinding.Name},
|
||||
{Name: volumezone.Name},
|
||||
{Name: podtopologyspread.Name},
|
||||
{Name: interpodaffinity.Name},
|
||||
},
|
||||
},
|
||||
PreScore: &schedulerapi.PluginSet{
|
||||
Enabled: []schedulerapi.Plugin{
|
||||
{Name: interpodaffinity.Name},
|
||||
{Name: podtopologyspread.Name},
|
||||
{Name: tainttoleration.Name},
|
||||
{Name: defaultpodtopologyspread.Name},
|
||||
},
|
||||
},
|
||||
Score: &schedulerapi.PluginSet{
|
||||
Enabled: []schedulerapi.Plugin{
|
||||
{Name: noderesources.BalancedAllocationName, Weight: 1},
|
||||
{Name: imagelocality.Name, Weight: 1},
|
||||
{Name: interpodaffinity.Name, Weight: 1},
|
||||
{Name: noderesources.LeastAllocatedName, Weight: 1},
|
||||
{Name: nodeaffinity.Name, Weight: 1},
|
||||
{Name: nodepreferavoidpods.Name, Weight: 10000},
|
||||
{Name: podtopologyspread.Name, Weight: 2},
|
||||
{Name: tainttoleration.Name, Weight: 1},
|
||||
{Name: defaultpodtopologyspread.Name, Weight: 1},
|
||||
},
|
||||
},
|
||||
Reserve: &schedulerapi.PluginSet{
|
||||
Enabled: []schedulerapi.Plugin{
|
||||
{Name: volumebinding.Name},
|
||||
},
|
||||
},
|
||||
Unreserve: &schedulerapi.PluginSet{
|
||||
Enabled: []schedulerapi.Plugin{
|
||||
{Name: volumebinding.Name},
|
||||
},
|
||||
},
|
||||
PreBind: &schedulerapi.PluginSet{
|
||||
Enabled: []schedulerapi.Plugin{
|
||||
{Name: volumebinding.Name},
|
||||
},
|
||||
},
|
||||
Bind: &schedulerapi.PluginSet{
|
||||
Enabled: []schedulerapi.Plugin{
|
||||
{Name: defaultbinder.Name},
|
||||
},
|
||||
},
|
||||
PostBind: &schedulerapi.PluginSet{
|
||||
Enabled: []schedulerapi.Plugin{
|
||||
{Name: volumebinding.Name},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "NewDefaultPodTopologySpread enabled",
|
||||
feature: features.DefaultPodTopologySpread,
|
||||
wantConfig: &schedulerapi.Plugins{
|
||||
QueueSort: &schedulerapi.PluginSet{
|
||||
Enabled: []schedulerapi.Plugin{
|
||||
{Name: queuesort.Name},
|
||||
},
|
||||
},
|
||||
PreFilter: &schedulerapi.PluginSet{
|
||||
Enabled: []schedulerapi.Plugin{
|
||||
{Name: noderesources.FitName},
|
||||
{Name: nodeports.Name},
|
||||
{Name: podtopologyspread.Name},
|
||||
{Name: interpodaffinity.Name},
|
||||
},
|
||||
},
|
||||
Filter: &schedulerapi.PluginSet{
|
||||
Enabled: []schedulerapi.Plugin{
|
||||
{Name: nodeunschedulable.Name},
|
||||
{Name: noderesources.FitName},
|
||||
{Name: nodename.Name},
|
||||
{Name: nodeports.Name},
|
||||
{Name: nodeaffinity.Name},
|
||||
{Name: volumerestrictions.Name},
|
||||
{Name: tainttoleration.Name},
|
||||
{Name: nodevolumelimits.EBSName},
|
||||
{Name: nodevolumelimits.GCEPDName},
|
||||
{Name: nodevolumelimits.CSIName},
|
||||
{Name: nodevolumelimits.AzureDiskName},
|
||||
{Name: volumebinding.Name},
|
||||
{Name: volumezone.Name},
|
||||
{Name: podtopologyspread.Name},
|
||||
{Name: interpodaffinity.Name},
|
||||
},
|
||||
},
|
||||
PreScore: &schedulerapi.PluginSet{
|
||||
Enabled: []schedulerapi.Plugin{
|
||||
{Name: interpodaffinity.Name},
|
||||
{Name: podtopologyspread.Name},
|
||||
{Name: tainttoleration.Name},
|
||||
},
|
||||
},
|
||||
Score: &schedulerapi.PluginSet{
|
||||
Enabled: []schedulerapi.Plugin{
|
||||
{Name: noderesources.BalancedAllocationName, Weight: 1},
|
||||
{Name: imagelocality.Name, Weight: 1},
|
||||
{Name: interpodaffinity.Name, Weight: 1},
|
||||
{Name: noderesources.LeastAllocatedName, Weight: 1},
|
||||
{Name: nodeaffinity.Name, Weight: 1},
|
||||
{Name: nodepreferavoidpods.Name, Weight: 10000},
|
||||
{Name: podtopologyspread.Name, Weight: 2},
|
||||
{Name: tainttoleration.Name, Weight: 1},
|
||||
},
|
||||
},
|
||||
Reserve: &schedulerapi.PluginSet{
|
||||
Enabled: []schedulerapi.Plugin{
|
||||
{Name: volumebinding.Name},
|
||||
},
|
||||
},
|
||||
Unreserve: &schedulerapi.PluginSet{
|
||||
Enabled: []schedulerapi.Plugin{
|
||||
{Name: volumebinding.Name},
|
||||
},
|
||||
},
|
||||
PreBind: &schedulerapi.PluginSet{
|
||||
Enabled: []schedulerapi.Plugin{
|
||||
{Name: volumebinding.Name},
|
||||
},
|
||||
},
|
||||
Bind: &schedulerapi.PluginSet{
|
||||
Enabled: []schedulerapi.Plugin{
|
||||
{Name: defaultbinder.Name},
|
||||
},
|
||||
},
|
||||
PostBind: &schedulerapi.PluginSet{
|
||||
Enabled: []schedulerapi.Plugin{
|
||||
{Name: volumebinding.Name},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
if test.feature != "" {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, test.feature, true)()
|
||||
}
|
||||
|
||||
r := NewRegistry()
|
||||
gotConfig := r[schedulerapi.SchedulerDefaultProviderName]
|
||||
if diff := cmp.Diff(test.wantConfig, gotConfig); diff != "" {
|
||||
t.Errorf("unexpected config diff (-want, +got): %s", diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user