@@ -21,9 +21,9 @@ import (
21
21
"fmt"
22
22
23
23
v1 "k8s.io/api/core/v1"
24
+ "k8s.io/apimachinery/pkg/labels"
24
25
"k8s.io/apimachinery/pkg/runtime"
25
26
"k8s.io/kubernetes/pkg/scheduler/algorithm/predicates"
26
- "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities"
27
27
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/migration"
28
28
framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1"
29
29
"k8s.io/kubernetes/pkg/scheduler/nodeinfo"
@@ -60,8 +60,8 @@ func validateNoConflict(presentLabels []string, absentLabels []string) error {
60
60
61
61
// New initializes a new plugin and returns it.
62
62
func New (plArgs * runtime.Unknown , handle framework.FrameworkHandle ) (framework.Plugin , error ) {
63
- args := & Args {}
64
- if err := framework .DecodeInto (plArgs , args ); err != nil {
63
+ args := Args {}
64
+ if err := framework .DecodeInto (plArgs , & args ); err != nil {
65
65
return nil , err
66
66
}
67
67
if err := validateNoConflict (args .PresentLabels , args .AbsentLabels ); err != nil {
@@ -70,20 +70,16 @@ func New(plArgs *runtime.Unknown, handle framework.FrameworkHandle) (framework.P
70
70
if err := validateNoConflict (args .PresentLabelsPreference , args .AbsentLabelsPreference ); err != nil {
71
71
return nil , err
72
72
}
73
- // Note that the reduce function is always nil therefore it's ignored.
74
- prioritize , _ := priorities .NewNodeLabelPriority (args .PresentLabelsPreference , args .AbsentLabelsPreference )
75
73
return & NodeLabel {
76
- handle : handle ,
77
- predicate : predicates .NewNodeLabelPredicate (args .PresentLabels , args .AbsentLabels ),
78
- prioritize : prioritize ,
74
+ handle : handle ,
75
+ Args : args ,
79
76
}, nil
80
77
}
81
78
82
79
// NodeLabel checks whether a pod can fit based on the node labels which match a filter that it requests.
83
80
type NodeLabel struct {
84
- handle framework.FrameworkHandle
85
- predicate predicates.FitPredicate
86
- prioritize priorities.PriorityMapFunction
81
+ handle framework.FrameworkHandle
82
+ Args
87
83
}
88
84
89
85
var _ framework.FilterPlugin = & NodeLabel {}
@@ -95,10 +91,31 @@ func (pl *NodeLabel) Name() string {
95
91
}
96
92
97
93
// Filter invoked at the filter extension point.
94
+ // It checks whether all of the specified labels exists on a node or not, regardless of their value
95
+ //
96
+ // Consider the cases where the nodes are placed in regions/zones/racks and these are identified by labels
97
+ // In some cases, it is required that only nodes that are part of ANY of the defined regions/zones/racks be selected
98
+ //
99
+ // Alternately, eliminating nodes that have a certain label, regardless of value, is also useful
100
+ // A node may have a label with "retiring" as key and the date as the value
101
+ // and it may be desirable to avoid scheduling new pods on this node.
98
102
func (pl * NodeLabel ) Filter (ctx context.Context , _ * framework.CycleState , pod * v1.Pod , nodeInfo * nodeinfo.NodeInfo ) * framework.Status {
99
- // Note that NodeLabelPredicate doesn't use predicate metadata, hence passing nil here.
100
- _ , reasons , err := pl .predicate (pod , nil , nodeInfo )
101
- return migration .PredicateResultToFrameworkStatus (reasons , err )
103
+ node := nodeInfo .Node ()
104
+ nodeLabels := labels .Set (node .Labels )
105
+ check := func (labels []string , presence bool ) bool {
106
+ for _ , label := range labels {
107
+ exists := nodeLabels .Has (label )
108
+ if (exists && ! presence ) || (! exists && presence ) {
109
+ return false
110
+ }
111
+ }
112
+ return true
113
+ }
114
+ if check (pl .PresentLabels , true ) && check (pl .AbsentLabels , false ) {
115
+ return nil
116
+ }
117
+
118
+ return migration .PredicateResultToFrameworkStatus ([]predicates.PredicateFailureReason {predicates .ErrNodeLabelPresenceViolated }, nil )
102
119
}
103
120
104
121
// Score invoked at the score extension point.
@@ -107,9 +124,23 @@ func (pl *NodeLabel) Score(ctx context.Context, state *framework.CycleState, pod
107
124
if err != nil {
108
125
return 0 , framework .NewStatus (framework .Error , fmt .Sprintf ("getting node %q from Snapshot: %v" , nodeName , err ))
109
126
}
110
- // Note that node label priority function doesn't use metadata, hence passing nil here.
111
- s , err := pl .prioritize (pod , nil , nodeInfo )
112
- return s .Score , migration .ErrorToFrameworkStatus (err )
127
+
128
+ node := nodeInfo .Node ()
129
+ score := int64 (0 )
130
+ for _ , label := range pl .PresentLabelsPreference {
131
+ if labels .Set (node .Labels ).Has (label ) {
132
+ score += framework .MaxNodeScore
133
+ }
134
+ }
135
+ for _ , label := range pl .AbsentLabelsPreference {
136
+ if ! labels .Set (node .Labels ).Has (label ) {
137
+ score += framework .MaxNodeScore
138
+ }
139
+ }
140
+ // Take average score for each label to ensure the score doesn't exceed MaxNodeScore.
141
+ score /= int64 (len (pl .PresentLabelsPreference ) + len (pl .AbsentLabelsPreference ))
142
+
143
+ return score , nil
113
144
}
114
145
115
146
// ScoreExtensions of the Score plugin.
0 commit comments