Skip to content

Commit 66386fd

Browse files
committed
Added the first predicate as a filter plugin: PodToleratesNodeTaints.
1 parent 4e1214c commit 66386fd

File tree

17 files changed

+459
-158
lines changed

17 files changed

+459
-158
lines changed

pkg/scheduler/algorithm/predicates/error.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,38 @@ var (
8282
ErrFakePredicate = newPredicateFailureError("FakePredicateError", "Nodes failed the fake predicate")
8383
)
8484

85+
var unresolvablePredicateFailureErrors = map[PredicateFailureReason]struct{}{
86+
ErrNodeSelectorNotMatch: {},
87+
ErrPodAffinityRulesNotMatch: {},
88+
ErrPodNotMatchHostName: {},
89+
ErrTaintsTolerationsNotMatch: {},
90+
ErrNodeLabelPresenceViolated: {},
91+
// Node conditions won't change when scheduler simulates removal of preemption victims.
92+
// So, it is pointless to try nodes that have not been able to host the pod due to node
93+
// conditions. These include ErrNodeNotReady, ErrNodeUnderPIDPressure, ErrNodeUnderMemoryPressure, ....
94+
ErrNodeNotReady: {},
95+
ErrNodeNetworkUnavailable: {},
96+
ErrNodeUnderDiskPressure: {},
97+
ErrNodeUnderPIDPressure: {},
98+
ErrNodeUnderMemoryPressure: {},
99+
ErrNodeUnschedulable: {},
100+
ErrNodeUnknownCondition: {},
101+
ErrVolumeZoneConflict: {},
102+
ErrVolumeNodeConflict: {},
103+
ErrVolumeBindConflict: {},
104+
}
105+
106+
// UnresolvablePredicateExists checks if there is at least one unresolvable predicate failure reason, if true
107+
// returns the first one in the list.
108+
func UnresolvablePredicateExists(reasons []PredicateFailureReason) PredicateFailureReason {
109+
for _, r := range reasons {
110+
if _, ok := unresolvablePredicateFailureErrors[r]; ok {
111+
return r
112+
}
113+
}
114+
return nil
115+
}
116+
85117
// InsufficientResourceError is an error type that indicates what kind of resource limit is
86118
// hit and caused the unfitting failure.
87119
type InsufficientResourceError struct {

pkg/scheduler/api/compatibility/compatibility_test.go

Lines changed: 66 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,11 @@ import (
3737
func TestCompatibility_v1_Scheduler(t *testing.T) {
3838
// Add serialized versions of scheduler config that exercise available options to ensure compatibility between releases
3939
schedulerFiles := map[string]struct {
40-
JSON string
41-
wantPredicates sets.String
42-
wantPrioritizers sets.String
43-
wantExtenders []schedulerapi.ExtenderConfig
40+
JSON string
41+
wantPredicates sets.String
42+
wantPrioritizers sets.String
43+
wantFilterPlugins sets.String
44+
wantExtenders []schedulerapi.ExtenderConfig
4445
}{
4546
// Do not change this JSON after the corresponding release has been tagged.
4647
// A failure indicates backwards compatibility with the specified release was broken.
@@ -214,7 +215,6 @@ func TestCompatibility_v1_Scheduler(t *testing.T) {
214215
"HostName",
215216
"NoDiskConflict",
216217
"NoVolumeZoneConflict",
217-
"PodToleratesNodeTaints",
218218
"CheckNodeMemoryPressure",
219219
"MaxEBSVolumeCount",
220220
"MaxGCEPDVolumeCount",
@@ -234,6 +234,9 @@ func TestCompatibility_v1_Scheduler(t *testing.T) {
234234
"TaintTolerationPriority",
235235
"InterPodAffinityPriority",
236236
),
237+
wantFilterPlugins: sets.NewString(
238+
"TaintToleration",
239+
),
237240
},
238241

239242
// Do not change this JSON after the corresponding release has been tagged.
@@ -279,7 +282,6 @@ func TestCompatibility_v1_Scheduler(t *testing.T) {
279282
"HostName",
280283
"NoDiskConflict",
281284
"NoVolumeZoneConflict",
282-
"PodToleratesNodeTaints",
283285
"CheckNodeMemoryPressure",
284286
"CheckNodeDiskPressure",
285287
"MaxEBSVolumeCount",
@@ -302,6 +304,9 @@ func TestCompatibility_v1_Scheduler(t *testing.T) {
302304
"InterPodAffinityPriority",
303305
"MostRequestedPriority",
304306
),
307+
wantFilterPlugins: sets.NewString(
308+
"TaintToleration",
309+
),
305310
},
306311
// Do not change this JSON after the corresponding release has been tagged.
307312
// A failure indicates backwards compatibility with the specified release was broken.
@@ -356,7 +361,6 @@ func TestCompatibility_v1_Scheduler(t *testing.T) {
356361
"HostName",
357362
"NoDiskConflict",
358363
"NoVolumeZoneConflict",
359-
"PodToleratesNodeTaints",
360364
"CheckNodeMemoryPressure",
361365
"CheckNodeDiskPressure",
362366
"MaxEBSVolumeCount",
@@ -379,6 +383,9 @@ func TestCompatibility_v1_Scheduler(t *testing.T) {
379383
"InterPodAffinityPriority",
380384
"MostRequestedPriority",
381385
),
386+
wantFilterPlugins: sets.NewString(
387+
"TaintToleration",
388+
),
382389
wantExtenders: []schedulerapi.ExtenderConfig{{
383390
URLPrefix: "/prefix",
384391
FilterVerb: "filter",
@@ -445,7 +452,6 @@ func TestCompatibility_v1_Scheduler(t *testing.T) {
445452
"HostName",
446453
"NoDiskConflict",
447454
"NoVolumeZoneConflict",
448-
"PodToleratesNodeTaints",
449455
"CheckNodeMemoryPressure",
450456
"CheckNodeDiskPressure",
451457
"CheckNodeCondition",
@@ -469,6 +475,9 @@ func TestCompatibility_v1_Scheduler(t *testing.T) {
469475
"InterPodAffinityPriority",
470476
"MostRequestedPriority",
471477
),
478+
wantFilterPlugins: sets.NewString(
479+
"TaintToleration",
480+
),
472481
wantExtenders: []schedulerapi.ExtenderConfig{{
473482
URLPrefix: "/prefix",
474483
FilterVerb: "filter",
@@ -536,7 +545,6 @@ func TestCompatibility_v1_Scheduler(t *testing.T) {
536545
"HostName",
537546
"NoDiskConflict",
538547
"NoVolumeZoneConflict",
539-
"PodToleratesNodeTaints",
540548
"CheckNodeMemoryPressure",
541549
"CheckNodeDiskPressure",
542550
"CheckNodeCondition",
@@ -561,6 +569,9 @@ func TestCompatibility_v1_Scheduler(t *testing.T) {
561569
"InterPodAffinityPriority",
562570
"MostRequestedPriority",
563571
),
572+
wantFilterPlugins: sets.NewString(
573+
"TaintToleration",
574+
),
564575
wantExtenders: []schedulerapi.ExtenderConfig{{
565576
URLPrefix: "/prefix",
566577
FilterVerb: "filter",
@@ -632,7 +643,6 @@ func TestCompatibility_v1_Scheduler(t *testing.T) {
632643
"HostName",
633644
"NoDiskConflict",
634645
"NoVolumeZoneConflict",
635-
"PodToleratesNodeTaints",
636646
"CheckNodeMemoryPressure",
637647
"CheckNodeDiskPressure",
638648
"CheckNodePIDPressure",
@@ -658,6 +668,9 @@ func TestCompatibility_v1_Scheduler(t *testing.T) {
658668
"InterPodAffinityPriority",
659669
"MostRequestedPriority",
660670
),
671+
wantFilterPlugins: sets.NewString(
672+
"TaintToleration",
673+
),
661674
wantExtenders: []schedulerapi.ExtenderConfig{{
662675
URLPrefix: "/prefix",
663676
FilterVerb: "filter",
@@ -741,7 +754,6 @@ func TestCompatibility_v1_Scheduler(t *testing.T) {
741754
"HostName",
742755
"NoDiskConflict",
743756
"NoVolumeZoneConflict",
744-
"PodToleratesNodeTaints",
745757
"CheckNodeMemoryPressure",
746758
"CheckNodeDiskPressure",
747759
"CheckNodePIDPressure",
@@ -768,6 +780,9 @@ func TestCompatibility_v1_Scheduler(t *testing.T) {
768780
"MostRequestedPriority",
769781
"RequestedToCapacityRatioPriority",
770782
),
783+
wantFilterPlugins: sets.NewString(
784+
"TaintToleration",
785+
),
771786
wantExtenders: []schedulerapi.ExtenderConfig{{
772787
URLPrefix: "/prefix",
773788
FilterVerb: "filter",
@@ -852,7 +867,6 @@ func TestCompatibility_v1_Scheduler(t *testing.T) {
852867
"HostName",
853868
"NoDiskConflict",
854869
"NoVolumeZoneConflict",
855-
"PodToleratesNodeTaints",
856870
"CheckNodeMemoryPressure",
857871
"CheckNodeDiskPressure",
858872
"CheckNodePIDPressure",
@@ -880,6 +894,9 @@ func TestCompatibility_v1_Scheduler(t *testing.T) {
880894
"MostRequestedPriority",
881895
"RequestedToCapacityRatioPriority",
882896
),
897+
wantFilterPlugins: sets.NewString(
898+
"TaintToleration",
899+
),
883900
wantExtenders: []schedulerapi.ExtenderConfig{{
884901
URLPrefix: "/prefix",
885902
FilterVerb: "filter",
@@ -963,7 +980,6 @@ func TestCompatibility_v1_Scheduler(t *testing.T) {
963980
"HostName",
964981
"NoDiskConflict",
965982
"NoVolumeZoneConflict",
966-
"PodToleratesNodeTaints",
967983
"CheckNodeMemoryPressure",
968984
"CheckNodeDiskPressure",
969985
"CheckNodePIDPressure",
@@ -992,6 +1008,9 @@ func TestCompatibility_v1_Scheduler(t *testing.T) {
9921008
"MostRequestedPriority",
9931009
"RequestedToCapacityRatioPriority",
9941010
),
1011+
wantFilterPlugins: sets.NewString(
1012+
"TaintToleration",
1013+
),
9951014
wantExtenders: []schedulerapi.ExtenderConfig{{
9961015
URLPrefix: "/prefix",
9971016
FilterVerb: "filter",
@@ -1079,7 +1098,6 @@ func TestCompatibility_v1_Scheduler(t *testing.T) {
10791098
"HostName",
10801099
"NoDiskConflict",
10811100
"NoVolumeZoneConflict",
1082-
"PodToleratesNodeTaints",
10831101
"CheckNodeMemoryPressure",
10841102
"CheckNodeDiskPressure",
10851103
"CheckNodePIDPressure",
@@ -1108,6 +1126,9 @@ func TestCompatibility_v1_Scheduler(t *testing.T) {
11081126
"MostRequestedPriority",
11091127
"RequestedToCapacityRatioPriority",
11101128
),
1129+
wantFilterPlugins: sets.NewString(
1130+
"TaintToleration",
1131+
),
11111132
wantExtenders: []schedulerapi.ExtenderConfig{{
11121133
URLPrefix: "/prefix",
11131134
FilterVerb: "filter",
@@ -1128,6 +1149,9 @@ func TestCompatibility_v1_Scheduler(t *testing.T) {
11281149
seenPredicates := sets.NewString()
11291150
seenPriorities := sets.NewString()
11301151
mandatoryPredicates := sets.NewString("CheckNodeCondition")
1152+
filterToPredicateMap := map[string]string{
1153+
"TaintToleration": "PodToleratesNodeTaints",
1154+
}
11311155

11321156
for v, tc := range schedulerFiles {
11331157
t.Run(v, func(t *testing.T) {
@@ -1163,26 +1187,39 @@ func TestCompatibility_v1_Scheduler(t *testing.T) {
11631187
algorithmSrc,
11641188
make(chan struct{}),
11651189
)
1190+
11661191
if err != nil {
11671192
t.Fatalf("%s: Error constructing: %v", v, err)
11681193
}
1169-
schedPredicates := sets.NewString()
1194+
gotPredicates := sets.NewString()
11701195
for p := range sched.Algorithm.Predicates() {
1171-
schedPredicates.Insert(p)
1196+
gotPredicates.Insert(p)
11721197
}
11731198
wantPredicates := tc.wantPredicates.Union(mandatoryPredicates)
1174-
if !schedPredicates.Equal(wantPredicates) {
1175-
t.Errorf("Got predicates %v, want %v", schedPredicates, wantPredicates)
1199+
if !gotPredicates.Equal(wantPredicates) {
1200+
t.Errorf("Got predicates %v, want %v", gotPredicates, wantPredicates)
11761201
}
1177-
schedPrioritizers := sets.NewString()
1202+
1203+
gotPrioritizers := sets.NewString()
11781204
for _, p := range sched.Algorithm.Prioritizers() {
1179-
schedPrioritizers.Insert(p.Name)
1205+
gotPrioritizers.Insert(p.Name)
1206+
}
1207+
if !gotPrioritizers.Equal(tc.wantPrioritizers) {
1208+
t.Errorf("Got prioritizers %v, want %v", gotPrioritizers, tc.wantPrioritizers)
11801209
}
11811210

1182-
if !schedPrioritizers.Equal(tc.wantPrioritizers) {
1183-
t.Errorf("Got prioritizers %v, want %v", schedPrioritizers, tc.wantPrioritizers)
1211+
gotFilterPlugins := sets.NewString()
1212+
plugins := sched.Framework.ListPlugins()
1213+
for _, p := range plugins["FilterPlugin"] {
1214+
gotFilterPlugins.Insert(p)
1215+
seenPredicates.Insert(filterToPredicateMap[p])
1216+
1217+
}
1218+
if !gotFilterPlugins.Equal(tc.wantFilterPlugins) {
1219+
t.Errorf("Got filter plugins %v, want %v", gotFilterPlugins, tc.wantFilterPlugins)
11841220
}
1185-
schedExtenders := sched.Algorithm.Extenders()
1221+
1222+
gotExtenders := sched.Algorithm.Extenders()
11861223
var wantExtenders []*core.HTTPExtender
11871224
for _, e := range tc.wantExtenders {
11881225
extender, err := core.NewHTTPExtender(&e)
@@ -1191,13 +1228,14 @@ func TestCompatibility_v1_Scheduler(t *testing.T) {
11911228
}
11921229
wantExtenders = append(wantExtenders, extender.(*core.HTTPExtender))
11931230
}
1194-
for i := range schedExtenders {
1195-
if !core.Equal(wantExtenders[i], schedExtenders[i].(*core.HTTPExtender)) {
1196-
t.Errorf("Got extender #%d %+v, want %+v", i, schedExtenders[i], wantExtenders[i])
1231+
for i := range gotExtenders {
1232+
if !core.Equal(wantExtenders[i], gotExtenders[i].(*core.HTTPExtender)) {
1233+
t.Errorf("Got extender #%d %+v, want %+v", i, gotExtenders[i], wantExtenders[i])
11971234
}
11981235
}
1199-
seenPredicates = seenPredicates.Union(schedPredicates)
1200-
seenPriorities = seenPriorities.Union(schedPrioritizers)
1236+
1237+
seenPredicates = seenPredicates.Union(gotPredicates)
1238+
seenPriorities = seenPriorities.Union(gotPrioritizers)
12011239
})
12021240
}
12031241

pkg/scheduler/core/generic_scheduler.go

Lines changed: 1 addition & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -65,27 +65,6 @@ const (
6565
minFeasibleNodesPercentageToFind = 5
6666
)
6767

68-
var unresolvablePredicateFailureErrors = map[predicates.PredicateFailureReason]struct{}{
69-
predicates.ErrNodeSelectorNotMatch: {},
70-
predicates.ErrPodAffinityRulesNotMatch: {},
71-
predicates.ErrPodNotMatchHostName: {},
72-
predicates.ErrTaintsTolerationsNotMatch: {},
73-
predicates.ErrNodeLabelPresenceViolated: {},
74-
// Node conditions won't change when scheduler simulates removal of preemption victims.
75-
// So, it is pointless to try nodes that have not been able to host the pod due to node
76-
// conditions. These include ErrNodeNotReady, ErrNodeUnderPIDPressure, ErrNodeUnderMemoryPressure, ....
77-
predicates.ErrNodeNotReady: {},
78-
predicates.ErrNodeNetworkUnavailable: {},
79-
predicates.ErrNodeUnderDiskPressure: {},
80-
predicates.ErrNodeUnderPIDPressure: {},
81-
predicates.ErrNodeUnderMemoryPressure: {},
82-
predicates.ErrNodeUnschedulable: {},
83-
predicates.ErrNodeUnknownCondition: {},
84-
predicates.ErrVolumeZoneConflict: {},
85-
predicates.ErrVolumeNodeConflict: {},
86-
predicates.ErrVolumeBindConflict: {},
87-
}
88-
8968
// FailedPredicateMap declares a map[string][]algorithm.PredicateFailureReason type.
9069
type FailedPredicateMap map[string][]predicates.PredicateFailureReason
9170

@@ -1204,16 +1183,6 @@ func (g *genericScheduler) selectVictimsOnNode(
12041183
return victims, numViolatingVictim, true
12051184
}
12061185

1207-
// unresolvablePredicateExists checks whether failedPredicates has unresolvable predicate.
1208-
func unresolvablePredicateExists(failedPredicates []predicates.PredicateFailureReason) bool {
1209-
for _, failedPredicate := range failedPredicates {
1210-
if _, ok := unresolvablePredicateFailureErrors[failedPredicate]; ok {
1211-
return true
1212-
}
1213-
}
1214-
return false
1215-
}
1216-
12171186
// nodesWherePreemptionMightHelp returns a list of nodes with failed predicates
12181187
// that may be satisfied by removing pods from the node.
12191188
func nodesWherePreemptionMightHelp(nodes []*v1.Node, fitErr *FitError) []*v1.Node {
@@ -1228,7 +1197,7 @@ func nodesWherePreemptionMightHelp(nodes []*v1.Node, fitErr *FitError) []*v1.Nod
12281197
// to rely less on such assumptions in the code when checking does not impose
12291198
// significant overhead.
12301199
// Also, we currently assume all failures returned by extender as resolvable.
1231-
if !unresolvablePredicateExists(failedPredicates) {
1200+
if predicates.UnresolvablePredicateExists(failedPredicates) == nil {
12321201
klog.V(3).Infof("Node %v is a potential node for preemption.", node.Name)
12331202
potentialNodes = append(potentialNodes, node)
12341203
}

pkg/scheduler/framework/plugins/BUILD

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@ go_library(
66
importpath = "k8s.io/kubernetes/pkg/scheduler/framework/plugins",
77
visibility = ["//visibility:public"],
88
deps = [
9+
"//pkg/scheduler/algorithm/predicates:go_default_library",
910
"//pkg/scheduler/apis/config:go_default_library",
10-
"//pkg/scheduler/framework/plugins/noop:go_default_library",
11+
"//pkg/scheduler/framework/plugins/tainttoleration:go_default_library",
1112
"//pkg/scheduler/framework/v1alpha1:go_default_library",
1213
],
1314
)
@@ -24,7 +25,9 @@ filegroup(
2425
srcs = [
2526
":package-srcs",
2627
"//pkg/scheduler/framework/plugins/examples:all-srcs",
28+
"//pkg/scheduler/framework/plugins/migration:all-srcs",
2729
"//pkg/scheduler/framework/plugins/noop:all-srcs",
30+
"//pkg/scheduler/framework/plugins/tainttoleration:all-srcs",
2831
],
2932
tags = ["automanaged"],
3033
visibility = ["//visibility:public"],

0 commit comments

Comments
 (0)