Skip to content

Commit 17630c3

Browse files
authored
Merge pull request kubernetes#91793 from alculquicondor/new-default-spread
Use PodTopologySpread for default spreading
2 parents 9089568 + 170f81c commit 17630c3

File tree

10 files changed

+330
-17
lines changed

10 files changed

+330
-17
lines changed

cmd/kube-scheduler/app/server_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,8 @@ profiles:
177177
"PreScorePlugin": {
178178
{Name: "InterPodAffinity"},
179179
{Name: "PodTopologySpread"},
180-
{Name: "DefaultPodTopologySpread"},
181180
{Name: "TaintToleration"},
181+
{Name: "DefaultPodTopologySpread"},
182182
},
183183
"ScorePlugin": {
184184
{Name: "NodeResourcesBalancedAllocation", Weight: 1},
@@ -188,8 +188,8 @@ profiles:
188188
{Name: "NodeAffinity", Weight: 1},
189189
{Name: "NodePreferAvoidPods", Weight: 10000},
190190
{Name: "PodTopologySpread", Weight: 2},
191-
{Name: "DefaultPodTopologySpread", Weight: 1},
192191
{Name: "TaintToleration", Weight: 1},
192+
{Name: "DefaultPodTopologySpread", Weight: 1},
193193
},
194194
"BindPlugin": {{Name: "DefaultBinder"}},
195195
"ReservePlugin": {{Name: "VolumeBinding"}},
@@ -308,8 +308,8 @@ profiles:
308308
"PreScorePlugin": {
309309
{Name: "InterPodAffinity"},
310310
{Name: "PodTopologySpread"},
311-
{Name: "DefaultPodTopologySpread"},
312311
{Name: "TaintToleration"},
312+
{Name: "DefaultPodTopologySpread"},
313313
},
314314
"ScorePlugin": {
315315
{Name: "NodeResourcesBalancedAllocation", Weight: 1},
@@ -319,8 +319,8 @@ profiles:
319319
{Name: "NodeAffinity", Weight: 1},
320320
{Name: "NodePreferAvoidPods", Weight: 10000},
321321
{Name: "PodTopologySpread", Weight: 2},
322-
{Name: "DefaultPodTopologySpread", Weight: 1},
323322
{Name: "TaintToleration", Weight: 1},
323+
{Name: "DefaultPodTopologySpread", Weight: 1},
324324
},
325325
"BindPlugin": {{Name: "DefaultBinder"}},
326326
"ReservePlugin": {{Name: "VolumeBinding"}},

pkg/features/kube_features.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,13 @@ const (
293293
// Enables CSI Inline volumes support for pods
294294
CSIInlineVolume featuregate.Feature = "CSIInlineVolume"
295295

296+
// owner: @alculquicondor
297+
// alpha: v1.19
298+
//
299+
// Enables the use of PodTopologySpread scheduling plugin to do default
300+
// spreading and disables legacy DefaultPodTopologySpread plugin.
301+
DefaultPodTopologySpread featuregate.Feature = "DefaultPodTopologySpread"
302+
296303
// owner: @tallclair
297304
// alpha: v1.12
298305
// beta: v1.14
@@ -660,6 +667,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
660667
HugePageStorageMediumSize: {Default: false, PreRelease: featuregate.Alpha},
661668
ExternalPolicyForExternalIP: {Default: true, PreRelease: featuregate.GA}, // remove in 1.20
662669
AnyVolumeDataSource: {Default: false, PreRelease: featuregate.Alpha},
670+
DefaultPodTopologySpread: {Default: false, PreRelease: featuregate.Alpha},
663671

664672
// inherited features from generic apiserver, relisted here to get a conflict if it is changed
665673
// unintentionally on either side:

pkg/scheduler/algorithmprovider/BUILD

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ go_library(
1111
srcs = ["registry.go"],
1212
importpath = "k8s.io/kubernetes/pkg/scheduler/algorithmprovider",
1313
deps = [
14+
"//pkg/features:go_default_library",
1415
"//pkg/scheduler/apis/config:go_default_library",
1516
"//pkg/scheduler/framework/plugins/defaultbinder:go_default_library",
1617
"//pkg/scheduler/framework/plugins/defaultpodtopologyspread:go_default_library",
@@ -29,6 +30,8 @@ go_library(
2930
"//pkg/scheduler/framework/plugins/volumebinding:go_default_library",
3031
"//pkg/scheduler/framework/plugins/volumerestrictions:go_default_library",
3132
"//pkg/scheduler/framework/plugins/volumezone:go_default_library",
33+
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
34+
"//vendor/k8s.io/klog/v2:go_default_library",
3235
],
3336
)
3437

@@ -37,6 +40,7 @@ go_test(
3740
srcs = ["registry_test.go"],
3841
embed = [":go_default_library"],
3942
deps = [
43+
"//pkg/features:go_default_library",
4044
"//pkg/scheduler/apis/config:go_default_library",
4145
"//pkg/scheduler/framework/plugins/defaultbinder:go_default_library",
4246
"//pkg/scheduler/framework/plugins/defaultpodtopologyspread:go_default_library",
@@ -55,6 +59,9 @@ go_test(
5559
"//pkg/scheduler/framework/plugins/volumebinding:go_default_library",
5660
"//pkg/scheduler/framework/plugins/volumerestrictions:go_default_library",
5761
"//pkg/scheduler/framework/plugins/volumezone:go_default_library",
62+
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
63+
"//staging/src/k8s.io/component-base/featuregate:go_default_library",
64+
"//staging/src/k8s.io/component-base/featuregate/testing:go_default_library",
5865
"//vendor/github.com/google/go-cmp/cmp:go_default_library",
5966
],
6067
)

pkg/scheduler/algorithmprovider/registry.go

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ import (
2020
"sort"
2121
"strings"
2222

23+
utilfeature "k8s.io/apiserver/pkg/util/feature"
24+
"k8s.io/klog/v2"
25+
"k8s.io/kubernetes/pkg/features"
2326
schedulerapi "k8s.io/kubernetes/pkg/scheduler/apis/config"
2427
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/defaultbinder"
2528
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/defaultpodtopologyspread"
@@ -49,7 +52,10 @@ type Registry map[string]*schedulerapi.Plugins
4952
// NewRegistry returns an algorithm provider registry instance.
5053
func NewRegistry() Registry {
5154
defaultConfig := getDefaultConfig()
55+
applyFeatureGates(defaultConfig)
56+
5257
caConfig := getClusterAutoscalerConfig()
58+
applyFeatureGates(caConfig)
5359

5460
return Registry{
5561
schedulerapi.SchedulerDefaultProviderName: defaultConfig,
@@ -106,7 +112,6 @@ func getDefaultConfig() *schedulerapi.Plugins {
106112
Enabled: []schedulerapi.Plugin{
107113
{Name: interpodaffinity.Name},
108114
{Name: podtopologyspread.Name},
109-
{Name: defaultpodtopologyspread.Name},
110115
{Name: tainttoleration.Name},
111116
},
112117
},
@@ -122,7 +127,6 @@ func getDefaultConfig() *schedulerapi.Plugins {
122127
// - This is a score coming from user preference.
123128
// - It makes its signal comparable to NodeResourcesLeastAllocated.
124129
{Name: podtopologyspread.Name, Weight: 2},
125-
{Name: defaultpodtopologyspread.Name, Weight: 1},
126130
{Name: tainttoleration.Name, Weight: 1},
127131
},
128132
},
@@ -164,3 +168,15 @@ func getClusterAutoscalerConfig() *schedulerapi.Plugins {
164168
}
165169
return caConfig
166170
}
171+
172+
func applyFeatureGates(config *schedulerapi.Plugins) {
173+
if !utilfeature.DefaultFeatureGate.Enabled(features.DefaultPodTopologySpread) {
174+
// When feature is enabled, the default spreading is done by
175+
// PodTopologySpread plugin, which is enabled by default.
176+
klog.Infof("Registering DefaultPodTopologySpread plugin")
177+
s := schedulerapi.Plugin{Name: defaultpodtopologyspread.Name}
178+
config.PreScore.Enabled = append(config.PreScore.Enabled, s)
179+
s.Weight = 1
180+
config.Score.Enabled = append(config.Score.Enabled, s)
181+
}
182+
}

pkg/scheduler/algorithmprovider/registry_test.go

Lines changed: 194 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@ import (
2020
"testing"
2121

2222
"github.com/google/go-cmp/cmp"
23+
"k8s.io/component-base/featuregate"
2324

25+
utilfeature "k8s.io/apiserver/pkg/util/feature"
26+
featuregatetesting "k8s.io/component-base/featuregate/testing"
27+
"k8s.io/kubernetes/pkg/features"
2428
schedulerapi "k8s.io/kubernetes/pkg/scheduler/apis/config"
2529
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/defaultbinder"
2630
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/defaultpodtopologyspread"
@@ -79,8 +83,8 @@ func TestClusterAutoscalerProvider(t *testing.T) {
7983
Enabled: []schedulerapi.Plugin{
8084
{Name: interpodaffinity.Name},
8185
{Name: podtopologyspread.Name},
82-
{Name: defaultpodtopologyspread.Name},
8386
{Name: tainttoleration.Name},
87+
{Name: defaultpodtopologyspread.Name},
8488
},
8589
},
8690
Score: &schedulerapi.PluginSet{
@@ -92,8 +96,8 @@ func TestClusterAutoscalerProvider(t *testing.T) {
9296
{Name: nodeaffinity.Name, Weight: 1},
9397
{Name: nodepreferavoidpods.Name, Weight: 10000},
9498
{Name: podtopologyspread.Name, Weight: 2},
95-
{Name: defaultpodtopologyspread.Name, Weight: 1},
9699
{Name: tainttoleration.Name, Weight: 1},
100+
{Name: defaultpodtopologyspread.Name, Weight: 1},
97101
},
98102
},
99103
Reserve: &schedulerapi.PluginSet{
@@ -129,3 +133,191 @@ func TestClusterAutoscalerProvider(t *testing.T) {
129133
t.Errorf("unexpected config diff (-want, +got): %s", diff)
130134
}
131135
}
136+
137+
func TestApplyFeatureGates(t *testing.T) {
138+
tests := []struct {
139+
name string
140+
feature featuregate.Feature
141+
wantConfig *schedulerapi.Plugins
142+
}{
143+
{
144+
name: "Feature gates disabled",
145+
wantConfig: &schedulerapi.Plugins{
146+
QueueSort: &schedulerapi.PluginSet{
147+
Enabled: []schedulerapi.Plugin{
148+
{Name: queuesort.Name},
149+
},
150+
},
151+
PreFilter: &schedulerapi.PluginSet{
152+
Enabled: []schedulerapi.Plugin{
153+
{Name: noderesources.FitName},
154+
{Name: nodeports.Name},
155+
{Name: podtopologyspread.Name},
156+
{Name: interpodaffinity.Name},
157+
},
158+
},
159+
Filter: &schedulerapi.PluginSet{
160+
Enabled: []schedulerapi.Plugin{
161+
{Name: nodeunschedulable.Name},
162+
{Name: noderesources.FitName},
163+
{Name: nodename.Name},
164+
{Name: nodeports.Name},
165+
{Name: nodeaffinity.Name},
166+
{Name: volumerestrictions.Name},
167+
{Name: tainttoleration.Name},
168+
{Name: nodevolumelimits.EBSName},
169+
{Name: nodevolumelimits.GCEPDName},
170+
{Name: nodevolumelimits.CSIName},
171+
{Name: nodevolumelimits.AzureDiskName},
172+
{Name: volumebinding.Name},
173+
{Name: volumezone.Name},
174+
{Name: podtopologyspread.Name},
175+
{Name: interpodaffinity.Name},
176+
},
177+
},
178+
PreScore: &schedulerapi.PluginSet{
179+
Enabled: []schedulerapi.Plugin{
180+
{Name: interpodaffinity.Name},
181+
{Name: podtopologyspread.Name},
182+
{Name: tainttoleration.Name},
183+
{Name: defaultpodtopologyspread.Name},
184+
},
185+
},
186+
Score: &schedulerapi.PluginSet{
187+
Enabled: []schedulerapi.Plugin{
188+
{Name: noderesources.BalancedAllocationName, Weight: 1},
189+
{Name: imagelocality.Name, Weight: 1},
190+
{Name: interpodaffinity.Name, Weight: 1},
191+
{Name: noderesources.LeastAllocatedName, Weight: 1},
192+
{Name: nodeaffinity.Name, Weight: 1},
193+
{Name: nodepreferavoidpods.Name, Weight: 10000},
194+
{Name: podtopologyspread.Name, Weight: 2},
195+
{Name: tainttoleration.Name, Weight: 1},
196+
{Name: defaultpodtopologyspread.Name, Weight: 1},
197+
},
198+
},
199+
Reserve: &schedulerapi.PluginSet{
200+
Enabled: []schedulerapi.Plugin{
201+
{Name: volumebinding.Name},
202+
},
203+
},
204+
Unreserve: &schedulerapi.PluginSet{
205+
Enabled: []schedulerapi.Plugin{
206+
{Name: volumebinding.Name},
207+
},
208+
},
209+
PreBind: &schedulerapi.PluginSet{
210+
Enabled: []schedulerapi.Plugin{
211+
{Name: volumebinding.Name},
212+
},
213+
},
214+
Bind: &schedulerapi.PluginSet{
215+
Enabled: []schedulerapi.Plugin{
216+
{Name: defaultbinder.Name},
217+
},
218+
},
219+
PostBind: &schedulerapi.PluginSet{
220+
Enabled: []schedulerapi.Plugin{
221+
{Name: volumebinding.Name},
222+
},
223+
},
224+
},
225+
},
226+
{
227+
name: "NewDefaultPodTopologySpread enabled",
228+
feature: features.DefaultPodTopologySpread,
229+
wantConfig: &schedulerapi.Plugins{
230+
QueueSort: &schedulerapi.PluginSet{
231+
Enabled: []schedulerapi.Plugin{
232+
{Name: queuesort.Name},
233+
},
234+
},
235+
PreFilter: &schedulerapi.PluginSet{
236+
Enabled: []schedulerapi.Plugin{
237+
{Name: noderesources.FitName},
238+
{Name: nodeports.Name},
239+
{Name: podtopologyspread.Name},
240+
{Name: interpodaffinity.Name},
241+
},
242+
},
243+
Filter: &schedulerapi.PluginSet{
244+
Enabled: []schedulerapi.Plugin{
245+
{Name: nodeunschedulable.Name},
246+
{Name: noderesources.FitName},
247+
{Name: nodename.Name},
248+
{Name: nodeports.Name},
249+
{Name: nodeaffinity.Name},
250+
{Name: volumerestrictions.Name},
251+
{Name: tainttoleration.Name},
252+
{Name: nodevolumelimits.EBSName},
253+
{Name: nodevolumelimits.GCEPDName},
254+
{Name: nodevolumelimits.CSIName},
255+
{Name: nodevolumelimits.AzureDiskName},
256+
{Name: volumebinding.Name},
257+
{Name: volumezone.Name},
258+
{Name: podtopologyspread.Name},
259+
{Name: interpodaffinity.Name},
260+
},
261+
},
262+
PreScore: &schedulerapi.PluginSet{
263+
Enabled: []schedulerapi.Plugin{
264+
{Name: interpodaffinity.Name},
265+
{Name: podtopologyspread.Name},
266+
{Name: tainttoleration.Name},
267+
},
268+
},
269+
Score: &schedulerapi.PluginSet{
270+
Enabled: []schedulerapi.Plugin{
271+
{Name: noderesources.BalancedAllocationName, Weight: 1},
272+
{Name: imagelocality.Name, Weight: 1},
273+
{Name: interpodaffinity.Name, Weight: 1},
274+
{Name: noderesources.LeastAllocatedName, Weight: 1},
275+
{Name: nodeaffinity.Name, Weight: 1},
276+
{Name: nodepreferavoidpods.Name, Weight: 10000},
277+
{Name: podtopologyspread.Name, Weight: 2},
278+
{Name: tainttoleration.Name, Weight: 1},
279+
},
280+
},
281+
Reserve: &schedulerapi.PluginSet{
282+
Enabled: []schedulerapi.Plugin{
283+
{Name: volumebinding.Name},
284+
},
285+
},
286+
Unreserve: &schedulerapi.PluginSet{
287+
Enabled: []schedulerapi.Plugin{
288+
{Name: volumebinding.Name},
289+
},
290+
},
291+
PreBind: &schedulerapi.PluginSet{
292+
Enabled: []schedulerapi.Plugin{
293+
{Name: volumebinding.Name},
294+
},
295+
},
296+
Bind: &schedulerapi.PluginSet{
297+
Enabled: []schedulerapi.Plugin{
298+
{Name: defaultbinder.Name},
299+
},
300+
},
301+
PostBind: &schedulerapi.PluginSet{
302+
Enabled: []schedulerapi.Plugin{
303+
{Name: volumebinding.Name},
304+
},
305+
},
306+
},
307+
},
308+
}
309+
310+
for _, test := range tests {
311+
t.Run(test.name, func(t *testing.T) {
312+
if test.feature != "" {
313+
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, test.feature, true)()
314+
}
315+
316+
r := NewRegistry()
317+
gotConfig := r[schedulerapi.SchedulerDefaultProviderName]
318+
if diff := cmp.Diff(test.wantConfig, gotConfig); diff != "" {
319+
t.Errorf("unexpected config diff (-want, +got): %s", diff)
320+
}
321+
})
322+
}
323+
}

0 commit comments

Comments
 (0)