Skip to content

Commit 95dd999

Browse files
Map SelectorSpreadPriority to PodTopologySpread plugin
when DefaultPodTopologySpread feature is enabled If SelectorSpreadPriority is in use, PodTopologySpread gets inevitably enabled. When only EvenPodsSpreadPriority is in use, PodTopologySpread is configured without system defaults. Change-Id: I2389a585cd8ad0bd35b0d2acae1665cd46908b3e
1 parent e3d7d06 commit 95dd999

File tree

3 files changed

+224
-4
lines changed

3 files changed

+224
-4
lines changed

pkg/scheduler/framework/plugins/BUILD

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ go_library(
99
importpath = "k8s.io/kubernetes/pkg/scheduler/framework/plugins",
1010
visibility = ["//visibility:public"],
1111
deps = [
12+
"//pkg/features:go_default_library",
1213
"//pkg/scheduler/apis/config:go_default_library",
1314
"//pkg/scheduler/framework/plugins/defaultbinder:go_default_library",
1415
"//pkg/scheduler/framework/plugins/defaultpreemption:go_default_library",
@@ -32,6 +33,7 @@ go_library(
3233
"//pkg/scheduler/framework/plugins/volumezone:go_default_library",
3334
"//pkg/scheduler/framework/runtime:go_default_library",
3435
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
36+
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
3537
"//vendor/k8s.io/klog/v2:go_default_library",
3638
],
3739
)
@@ -79,10 +81,21 @@ go_test(
7981
srcs = ["legacy_registry_test.go"],
8082
embed = [":go_default_library"],
8183
deps = [
84+
"//pkg/features:go_default_library",
8285
"//pkg/scheduler/apis/config:go_default_library",
86+
"//pkg/scheduler/framework/plugins/imagelocality:go_default_library",
87+
"//pkg/scheduler/framework/plugins/interpodaffinity:go_default_library",
88+
"//pkg/scheduler/framework/plugins/nodeaffinity:go_default_library",
89+
"//pkg/scheduler/framework/plugins/nodepreferavoidpods:go_default_library",
90+
"//pkg/scheduler/framework/plugins/noderesources:go_default_library",
8391
"//pkg/scheduler/framework/plugins/nodeunschedulable:go_default_library",
92+
"//pkg/scheduler/framework/plugins/podtopologyspread:go_default_library",
93+
"//pkg/scheduler/framework/plugins/selectorspread:go_default_library",
8494
"//pkg/scheduler/framework/plugins/tainttoleration:go_default_library",
8595
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
96+
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
97+
"//staging/src/k8s.io/component-base/featuregate:go_default_library",
98+
"//staging/src/k8s.io/component-base/featuregate/testing:go_default_library",
8699
"//vendor/github.com/google/go-cmp/cmp:go_default_library",
87100
],
88101
)

pkg/scheduler/framework/plugins/legacy_registry.go

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ import (
2121
"sort"
2222

2323
"k8s.io/apimachinery/pkg/util/sets"
24+
"k8s.io/apiserver/pkg/util/feature"
2425
"k8s.io/klog/v2"
26+
"k8s.io/kubernetes/pkg/features"
2527
"k8s.io/kubernetes/pkg/scheduler/apis/config"
2628
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/imagelocality"
2729
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/interpodaffinity"
@@ -327,9 +329,29 @@ func NewLegacyRegistry() *LegacyRegistry {
327329

328330
// Register Priorities.
329331
registry.registerPriorityConfigProducer(SelectorSpreadPriority,
330-
func(args ConfigProducerArgs, plugins *config.Plugins, _ *[]config.PluginConfig) {
331-
plugins.Score = appendToPluginSet(plugins.Score, selectorspread.Name, &args.Weight)
332-
plugins.PreScore = appendToPluginSet(plugins.PreScore, selectorspread.Name, nil)
332+
func(args ConfigProducerArgs, plugins *config.Plugins, pluginConfig *[]config.PluginConfig) {
333+
if !feature.DefaultFeatureGate.Enabled(features.DefaultPodTopologySpread) {
334+
plugins.Score = appendToPluginSet(plugins.Score, selectorspread.Name, &args.Weight)
335+
plugins.PreScore = appendToPluginSet(plugins.PreScore, selectorspread.Name, nil)
336+
return
337+
}
338+
plugins.Score = appendToPluginSet(plugins.Score, podtopologyspread.Name, &args.Weight)
339+
plugins.PreScore = appendToPluginSet(plugins.PreScore, podtopologyspread.Name, nil)
340+
plArgs := config.PodTopologySpreadArgs{
341+
DefaultingType: config.SystemDefaulting,
342+
}
343+
// The order in which SelectorSpreadPriority or EvenPodsSpreadPriority producers
344+
// are called is not guaranteed. Override or append configuration.
345+
for i, e := range *pluginConfig {
346+
if e.Name == podtopologyspread.Name {
347+
(*pluginConfig)[i].Args = &plArgs
348+
return
349+
}
350+
}
351+
*pluginConfig = append(*pluginConfig, config.PluginConfig{
352+
Name: podtopologyspread.Name,
353+
Args: &plArgs,
354+
})
333355
})
334356
registry.registerPriorityConfigProducer(TaintTolerationPriority,
335357
func(args ConfigProducerArgs, plugins *config.Plugins, _ *[]config.PluginConfig) {
@@ -402,9 +424,25 @@ func NewLegacyRegistry() *LegacyRegistry {
402424
}
403425
})
404426
registry.registerPriorityConfigProducer(EvenPodsSpreadPriority,
405-
func(args ConfigProducerArgs, plugins *config.Plugins, _ *[]config.PluginConfig) {
427+
func(args ConfigProducerArgs, plugins *config.Plugins, pluginConfig *[]config.PluginConfig) {
406428
plugins.PreScore = appendToPluginSet(plugins.PreScore, podtopologyspread.Name, nil)
407429
plugins.Score = appendToPluginSet(plugins.Score, podtopologyspread.Name, &args.Weight)
430+
if feature.DefaultFeatureGate.Enabled(features.DefaultPodTopologySpread) {
431+
// The order in which SelectorSpreadPriority or EvenPodsSpreadPriority producers
432+
// are called is not guaranteed. If plugin was not configured yet, append
433+
// configuration where system default constraints are disabled.
434+
for _, e := range *pluginConfig {
435+
if e.Name == podtopologyspread.Name {
436+
return
437+
}
438+
}
439+
*pluginConfig = append(*pluginConfig, config.PluginConfig{
440+
Name: podtopologyspread.Name,
441+
Args: &config.PodTopologySpreadArgs{
442+
DefaultingType: config.ListDefaulting,
443+
},
444+
})
445+
}
408446
})
409447

410448
return registry
@@ -489,6 +527,15 @@ func appendToPluginSet(set *config.PluginSet, name string, weight *int32) *confi
489527
if set == nil {
490528
set = &config.PluginSet{}
491529
}
530+
for _, e := range set.Enabled {
531+
if e.Name == name {
532+
// Keep the max weight.
533+
if weight != nil && *weight > e.Weight {
534+
e.Weight = *weight
535+
}
536+
return set
537+
}
538+
}
492539
cfg := config.Plugin{Name: name}
493540
if weight != nil {
494541
cfg.Weight = *weight

pkg/scheduler/framework/plugins/legacy_registry_test.go

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,19 @@ import (
2121

2222
"github.com/google/go-cmp/cmp"
2323
"k8s.io/apimachinery/pkg/util/sets"
24+
"k8s.io/apiserver/pkg/util/feature"
25+
"k8s.io/component-base/featuregate"
26+
featuregatetesting "k8s.io/component-base/featuregate/testing"
27+
"k8s.io/kubernetes/pkg/features"
2428
"k8s.io/kubernetes/pkg/scheduler/apis/config"
29+
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/imagelocality"
30+
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/interpodaffinity"
31+
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodeaffinity"
32+
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodepreferavoidpods"
33+
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/noderesources"
2534
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodeunschedulable"
35+
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/podtopologyspread"
36+
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/selectorspread"
2637
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/tainttoleration"
2738
)
2839

@@ -93,3 +104,152 @@ func TestRegisterConfigProducers(t *testing.T) {
93104
t.Errorf("unexpected plugin configuration (-want, +got): %s", diff)
94105
}
95106
}
107+
108+
func TestAppendPriorityConfigs(t *testing.T) {
109+
cases := []struct {
110+
name string
111+
features map[featuregate.Feature]bool
112+
keys map[string]int64
113+
args ConfigProducerArgs
114+
wantPlugins config.Plugins
115+
wantPluginConfig []config.PluginConfig
116+
}{
117+
{
118+
name: "default priorities",
119+
wantPlugins: config.Plugins{
120+
PreScore: &config.PluginSet{
121+
Enabled: []config.Plugin{
122+
{Name: podtopologyspread.Name},
123+
{Name: interpodaffinity.Name},
124+
{Name: selectorspread.Name},
125+
{Name: tainttoleration.Name},
126+
},
127+
},
128+
Score: &config.PluginSet{
129+
Enabled: []config.Plugin{
130+
{Name: noderesources.BalancedAllocationName, Weight: 1},
131+
{Name: podtopologyspread.Name, Weight: 2},
132+
{Name: imagelocality.Name, Weight: 1},
133+
{Name: interpodaffinity.Name, Weight: 1},
134+
{Name: noderesources.LeastAllocatedName, Weight: 1},
135+
{Name: nodeaffinity.Name, Weight: 1},
136+
{Name: nodepreferavoidpods.Name, Weight: 10000},
137+
{Name: selectorspread.Name, Weight: 1},
138+
{Name: tainttoleration.Name, Weight: 1},
139+
},
140+
},
141+
},
142+
},
143+
{
144+
name: "DefaultPodTopologySpread enabled, SelectorSpreadPriority only",
145+
features: map[featuregate.Feature]bool{
146+
features.DefaultPodTopologySpread: true,
147+
},
148+
keys: map[string]int64{
149+
SelectorSpreadPriority: 3,
150+
},
151+
wantPlugins: config.Plugins{
152+
PreScore: &config.PluginSet{
153+
Enabled: []config.Plugin{
154+
{Name: podtopologyspread.Name},
155+
},
156+
},
157+
Score: &config.PluginSet{
158+
Enabled: []config.Plugin{
159+
{Name: podtopologyspread.Name, Weight: 3},
160+
},
161+
},
162+
},
163+
wantPluginConfig: []config.PluginConfig{
164+
{
165+
Name: podtopologyspread.Name,
166+
Args: &config.PodTopologySpreadArgs{
167+
DefaultingType: config.SystemDefaulting,
168+
},
169+
},
170+
},
171+
},
172+
{
173+
name: "DefaultPodTopologySpread enabled, EvenPodsSpreadPriority only",
174+
features: map[featuregate.Feature]bool{
175+
features.DefaultPodTopologySpread: true,
176+
},
177+
keys: map[string]int64{
178+
EvenPodsSpreadPriority: 4,
179+
},
180+
wantPlugins: config.Plugins{
181+
PreScore: &config.PluginSet{
182+
Enabled: []config.Plugin{
183+
{Name: podtopologyspread.Name},
184+
},
185+
},
186+
Score: &config.PluginSet{
187+
Enabled: []config.Plugin{
188+
{Name: podtopologyspread.Name, Weight: 4},
189+
},
190+
},
191+
},
192+
wantPluginConfig: []config.PluginConfig{
193+
{
194+
Name: podtopologyspread.Name,
195+
Args: &config.PodTopologySpreadArgs{
196+
DefaultingType: config.ListDefaulting,
197+
},
198+
},
199+
},
200+
},
201+
{
202+
name: "DefaultPodTopologySpread enabled, SelectorSpreadPriority+EvenPodsSpreadPriority",
203+
features: map[featuregate.Feature]bool{
204+
features.DefaultPodTopologySpread: true,
205+
},
206+
keys: map[string]int64{
207+
SelectorSpreadPriority: 1,
208+
EvenPodsSpreadPriority: 2,
209+
},
210+
wantPlugins: config.Plugins{
211+
PreScore: &config.PluginSet{
212+
Enabled: []config.Plugin{
213+
{Name: podtopologyspread.Name},
214+
},
215+
},
216+
Score: &config.PluginSet{
217+
Enabled: []config.Plugin{
218+
{Name: podtopologyspread.Name, Weight: 2},
219+
},
220+
},
221+
},
222+
wantPluginConfig: []config.PluginConfig{
223+
{
224+
Name: podtopologyspread.Name,
225+
Args: &config.PodTopologySpreadArgs{
226+
DefaultingType: config.SystemDefaulting,
227+
},
228+
},
229+
},
230+
},
231+
}
232+
for _, tc := range cases {
233+
t.Run(tc.name, func(t *testing.T) {
234+
for k, v := range tc.features {
235+
defer featuregatetesting.SetFeatureGateDuringTest(t, feature.DefaultFeatureGate, k, v)()
236+
}
237+
238+
r := NewLegacyRegistry()
239+
keys := tc.keys
240+
if keys == nil {
241+
keys = r.DefaultPriorities
242+
}
243+
plugins, pluginConfig, err := r.AppendPriorityConfigs(keys, &tc.args, config.Plugins{}, nil)
244+
if err != nil {
245+
t.Fatalf("Appending Priority Configs: %v", err)
246+
}
247+
if diff := cmp.Diff(tc.wantPlugins, plugins); diff != "" {
248+
t.Errorf("Unexpected Plugin (-want,+got):\n%s", diff)
249+
}
250+
if diff := cmp.Diff(tc.wantPluginConfig, pluginConfig); diff != "" {
251+
t.Errorf("Unexpected PluginConfig (-want,+got):\n%s", diff)
252+
}
253+
})
254+
}
255+
}

0 commit comments

Comments
 (0)