@@ -31,7 +31,8 @@ type NodeGroupState struct {
31
31
scaleUpLock scaleLock
32
32
33
33
// used for tracking which nodes are tainted. testing when in dry mode
34
- taintTracker []string
34
+ taintTracker []string
35
+ forceTaintTracker []string
35
36
36
37
// used for tracking scale delta across runs, useful for reducing hysteresis
37
38
scaleDelta int
@@ -54,11 +55,12 @@ type Opts struct {
54
55
// scaleOpts provides options for a scale function
55
56
// wraps options that would be passed as args
56
57
type scaleOpts struct {
57
- nodes []* v1.Node
58
- taintedNodes []* v1.Node
59
- untaintedNodes []* v1.Node
60
- nodeGroup * NodeGroupState
61
- nodesDelta int
58
+ nodes []* v1.Node
59
+ taintedNodes []* v1.Node
60
+ forceTaintedNodes []* v1.Node
61
+ untaintedNodes []* v1.Node
62
+ nodeGroup * NodeGroupState
63
+ nodesDelta int
62
64
}
63
65
64
66
// NewController creates a new controller with the specified options
@@ -116,36 +118,52 @@ func (c *Controller) dryMode(nodeGroup *NodeGroupState) bool {
116
118
}
117
119
118
120
// filterNodes separates nodes between tainted and untainted nodes
119
- func (c * Controller ) filterNodes (nodeGroup * NodeGroupState , allNodes []* v1.Node ) (untaintedNodes , taintedNodes , cordonedNodes []* v1.Node ) {
121
+ func (c * Controller ) filterNodes (nodeGroup * NodeGroupState , allNodes []* v1.Node ) (untaintedNodes , taintedNodes , forceTaintedNodes , cordonedNodes []* v1.Node ) {
120
122
untaintedNodes = make ([]* v1.Node , 0 , len (allNodes ))
121
123
taintedNodes = make ([]* v1.Node , 0 , len (allNodes ))
124
+ forceTaintedNodes = make ([]* v1.Node , 0 , len (allNodes ))
122
125
cordonedNodes = make ([]* v1.Node , 0 , len (allNodes ))
123
126
124
127
for _ , node := range allNodes {
128
+ var tainted bool
129
+ var forceTainted bool
130
+ var untainted bool
131
+
125
132
if c .dryMode (nodeGroup ) {
126
- var contains bool
127
133
for _ , name := range nodeGroup .taintTracker {
128
134
if node .Name == name {
129
- contains = true
135
+ tainted = true
130
136
break
131
137
}
132
138
}
133
- if ! contains {
134
- untaintedNodes = append (untaintedNodes , node )
135
- } else {
136
- taintedNodes = append (taintedNodes , node )
139
+
140
+ for _ , name := range nodeGroup .forceTaintTracker {
141
+ if node .Name == name {
142
+ forceTainted = true
143
+ break
144
+ }
137
145
}
146
+
147
+ untainted = ! forceTainted && ! tainted
148
+
138
149
} else {
139
150
// If the node is Unschedulable (cordoned), separate it out from the tainted/untainted
140
151
if node .Spec .Unschedulable {
141
152
cordonedNodes = append (cordonedNodes , node )
142
153
continue
143
154
}
144
- if _ , tainted := k8s .GetToBeRemovedTaint (node ); ! tainted {
145
- untaintedNodes = append (untaintedNodes , node )
146
- } else {
147
- taintedNodes = append (taintedNodes , node )
148
- }
155
+
156
+ _ , forceTainted = k8s .GetToBeForceRemovedTaint (node )
157
+ _ , tainted = k8s .GetToBeRemovedTaint (node )
158
+ untainted = ! forceTainted && ! tainted
159
+ }
160
+
161
+ if forceTainted {
162
+ forceTaintedNodes = append (forceTaintedNodes , node )
163
+ } else if tainted {
164
+ taintedNodes = append (taintedNodes , node )
165
+ } else if untainted {
166
+ untaintedNodes = append (untaintedNodes , node )
149
167
}
150
168
}
151
169
@@ -210,20 +228,22 @@ func (c *Controller) scaleNodeGroup(nodegroup string, nodeGroup *NodeGroupState)
210
228
}
211
229
212
230
// Filter into untainted and tainted nodes
213
- untaintedNodes , taintedNodes , cordonedNodes := c .filterNodes (nodeGroup , allNodes )
231
+ untaintedNodes , taintedNodes , forceTaintedNodes , cordonedNodes := c .filterNodes (nodeGroup , allNodes )
214
232
215
233
// Metrics and Logs
216
234
log .WithField ("nodegroup" , nodegroup ).Infof ("pods total: %v" , len (pods ))
217
235
log .WithField ("nodegroup" , nodegroup ).Infof ("nodes remaining total: %v" , len (allNodes ))
218
236
log .WithField ("nodegroup" , nodegroup ).Infof ("cordoned nodes remaining total: %v" , len (cordonedNodes ))
219
237
log .WithField ("nodegroup" , nodegroup ).Infof ("nodes remaining untainted: %v" , len (untaintedNodes ))
220
238
log .WithField ("nodegroup" , nodegroup ).Infof ("nodes remaining tainted: %v" , len (taintedNodes ))
239
+ log .WithField ("nodegroup" , nodegroup ).Infof ("nodes remaining force tainted: %v" , len (forceTaintedNodes ))
221
240
log .WithField ("nodegroup" , nodegroup ).Infof ("Minimum Node: %v" , nodeGroup .Opts .MinNodes )
222
241
log .WithField ("nodegroup" , nodegroup ).Infof ("Maximum Node: %v" , nodeGroup .Opts .MaxNodes )
223
242
metrics .NodeGroupNodes .WithLabelValues (nodegroup ).Set (float64 (len (allNodes )))
224
243
metrics .NodeGroupNodesCordoned .WithLabelValues (nodegroup ).Set (float64 (len (cordonedNodes )))
225
244
metrics .NodeGroupNodesUntainted .WithLabelValues (nodegroup ).Set (float64 (len (untaintedNodes )))
226
245
metrics .NodeGroupNodesTainted .WithLabelValues (nodegroup ).Set (float64 (len (taintedNodes )))
246
+ metrics .NodeGroupNodesForceTainted .WithLabelValues (nodegroup ).Set (float64 (len (forceTaintedNodes )))
227
247
metrics .NodeGroupPods .WithLabelValues (nodegroup ).Set (float64 (len (pods )))
228
248
229
249
// We want to be really simple right now so we don't do anything if we are outside the range of allowed nodes
@@ -288,11 +308,12 @@ func (c *Controller) scaleNodeGroup(nodegroup string, nodeGroup *NodeGroupState)
288
308
if len (untaintedNodes ) < nodeGroup .Opts .MinNodes {
289
309
log .WithField ("nodegroup" , nodegroup ).Warn ("There are less untainted nodes than the minimum" )
290
310
result , err := c .ScaleUp (scaleOpts {
291
- nodes : allNodes ,
292
- nodesDelta : nodeGroup .Opts .MinNodes - len (untaintedNodes ),
293
- nodeGroup : nodeGroup ,
294
- taintedNodes : taintedNodes ,
295
- untaintedNodes : untaintedNodes ,
311
+ nodes : allNodes ,
312
+ nodesDelta : nodeGroup .Opts .MinNodes - len (untaintedNodes ),
313
+ nodeGroup : nodeGroup ,
314
+ taintedNodes : taintedNodes ,
315
+ forceTaintedNodes : forceTaintedNodes ,
316
+ untaintedNodes : untaintedNodes ,
296
317
})
297
318
if err != nil {
298
319
log .WithField ("nodegroup" , nodegroup ).Error (err )
@@ -382,10 +403,21 @@ func (c *Controller) scaleNodeGroup(nodegroup string, nodeGroup *NodeGroupState)
382
403
log .WithField ("nodegroup" , nodegroup ).Debugf ("Delta: %v" , nodesDelta )
383
404
384
405
scaleOptions := scaleOpts {
385
- nodes : allNodes ,
386
- taintedNodes : taintedNodes ,
387
- untaintedNodes : untaintedNodes ,
388
- nodeGroup : nodeGroup ,
406
+ nodes : allNodes ,
407
+ taintedNodes : taintedNodes ,
408
+ forceTaintedNodes : forceTaintedNodes ,
409
+ untaintedNodes : untaintedNodes ,
410
+ nodeGroup : nodeGroup ,
411
+ }
412
+
413
+ // Check for nodes tainted for force removal
414
+ var forceRemoved int
415
+ var forceActionErr error
416
+ forceRemoved , forceActionErr = c .TryRemoveForceTaintedNodes (scaleOptions )
417
+ log .WithField ("nodegroup" , nodegroup ).Infof ("Reaper: There were %v empty nodes force deleted this round" , forceRemoved )
418
+
419
+ if forceActionErr != nil {
420
+ log .WithField ("nodegroup" , nodegroup ).Error (forceActionErr )
389
421
}
390
422
391
423
// Perform a scale up, do nothing or scale down based on the nodes delta
0 commit comments