Skip to content

Commit fbe806e

Browse files
authored
Merge pull request kubernetes#95448 from alculquicondor/policy-spread
Map SelectorSpreadPriority to PodTopologySpread plugin
2 parents 3395ddb + 95dd999 commit fbe806e

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)