@@ -151,16 +151,12 @@ func (tc TaintConfig) isExplicitlyReportedTaint(taint string) bool {
151
151
return ok
152
152
}
153
153
154
- // getKeyShortName converts taint key to short name for logging
155
- func getKeyShortName (key string ) string {
156
- switch key {
157
- case ToBeDeletedTaint :
158
- return "ToBeDeletedTaint"
159
- case DeletionCandidateTaint :
160
- return "DeletionCandidateTaint"
161
- default :
162
- return key
154
+ func taintKeys (taints []apiv1.Taint ) []string {
155
+ var keys []string
156
+ for _ , taint := range taints {
157
+ keys = append (keys , taint .Key )
163
158
}
159
+ return keys
164
160
}
165
161
166
162
// MarkToBeDeleted sets a taint that makes the node unschedulable.
@@ -170,7 +166,7 @@ func MarkToBeDeleted(node *apiv1.Node, client kube_client.Interface, cordonNode
170
166
Value : fmt .Sprint (time .Now ().Unix ()),
171
167
Effect : apiv1 .TaintEffectNoSchedule ,
172
168
}
173
- return AddTaint (node , client , taint , cordonNode )
169
+ return AddTaints (node , client , []apiv1. Taint { taint } , cordonNode )
174
170
}
175
171
176
172
// MarkDeletionCandidate sets a soft taint that makes the node preferably unschedulable.
@@ -180,11 +176,11 @@ func MarkDeletionCandidate(node *apiv1.Node, client kube_client.Interface) error
180
176
Value : fmt .Sprint (time .Now ().Unix ()),
181
177
Effect : apiv1 .TaintEffectPreferNoSchedule ,
182
178
}
183
- return AddTaint (node , client , taint , false )
179
+ return AddTaints (node , client , []apiv1. Taint { taint } , false )
184
180
}
185
181
186
- // AddTaint sets the specified taint on the node.
187
- func AddTaint (node * apiv1.Node , client kube_client.Interface , taint apiv1.Taint , cordonNode bool ) error {
182
+ // AddTaints sets the specified taints on the node.
183
+ func AddTaints (node * apiv1.Node , client kube_client.Interface , taints [] apiv1.Taint , cordonNode bool ) error {
188
184
retryDeadline := time .Now ().Add (maxRetryDeadline )
189
185
freshNode := node .DeepCopy ()
190
186
var err error
@@ -194,12 +190,12 @@ func AddTaint(node *apiv1.Node, client kube_client.Interface, taint apiv1.Taint,
194
190
// Get the newest version of the node.
195
191
freshNode , err = client .CoreV1 ().Nodes ().Get (context .TODO (), node .Name , metav1.GetOptions {})
196
192
if err != nil || freshNode == nil {
197
- klog .Warningf ("Error while adding %v taint on node %v: %v" , getKeyShortName ( taint . Key ), node .Name , err )
193
+ klog .Warningf ("Error while adding %v taints on node %v: %v" , strings . Join ( taintKeys ( taints ), "," ), node .Name , err )
198
194
return fmt .Errorf ("failed to get node %v: %v" , node .Name , err )
199
195
}
200
196
}
201
197
202
- if ! addTaintToSpec (freshNode , taint , cordonNode ) {
198
+ if ! addTaintsToSpec (freshNode , taints , cordonNode ) {
203
199
if ! refresh {
204
200
// Make sure we have the latest version before skipping update.
205
201
refresh = true
@@ -215,22 +211,27 @@ func AddTaint(node *apiv1.Node, client kube_client.Interface, taint apiv1.Taint,
215
211
}
216
212
217
213
if err != nil {
218
- klog .Warningf ("Error while adding %v taint on node %v: %v" , getKeyShortName ( taint . Key ), node .Name , err )
214
+ klog .Warningf ("Error while adding %v taints on node %v: %v" , strings . Join ( taintKeys ( taints ), "," ), node .Name , err )
219
215
return err
220
216
}
221
- klog .V (1 ).Infof ("Successfully added %v on node %v" , getKeyShortName ( taint . Key ), node .Name )
217
+ klog .V (1 ).Infof ("Successfully added %v on node %v" , strings . Join ( taintKeys ( taints ), "," ), node .Name )
222
218
return nil
223
219
}
224
220
}
225
221
226
- func addTaintToSpec (node * apiv1.Node , taint apiv1.Taint , cordonNode bool ) bool {
227
- for _ , t := range node .Spec .Taints {
228
- if t .Key == taint .Key {
229
- klog .V (2 ).Infof ("%v already present on node %v, t: %v" , taint .Key , node .Name , t )
230
- return false
222
+ func addTaintsToSpec (node * apiv1.Node , taints []apiv1.Taint , cordonNode bool ) bool {
223
+ taintsAdded := false
224
+ for _ , taint := range taints {
225
+ if HasTaint (node , taint .Key ) {
226
+ klog .V (2 ).Infof ("%v already present on node %v" , taint .Key , node .Name )
227
+ continue
231
228
}
229
+ taintsAdded = true
230
+ node .Spec .Taints = append (node .Spec .Taints , taint )
231
+ }
232
+ if ! taintsAdded {
233
+ return false
232
234
}
233
- node .Spec .Taints = append (node .Spec .Taints , taint )
234
235
if cordonNode {
235
236
klog .V (1 ).Infof ("Marking node %v to be cordoned by Cluster Autoscaler" , node .Name )
236
237
node .Spec .Unschedulable = true
@@ -285,16 +286,16 @@ func GetTaintTime(node *apiv1.Node, taintKey string) (*time.Time, error) {
285
286
286
287
// CleanToBeDeleted cleans CA's NoSchedule taint from a node.
287
288
func CleanToBeDeleted (node * apiv1.Node , client kube_client.Interface , cordonNode bool ) (bool , error ) {
288
- return CleanTaint (node , client , ToBeDeletedTaint , cordonNode )
289
+ return CleanTaints (node , client , [] string { ToBeDeletedTaint } , cordonNode )
289
290
}
290
291
291
292
// CleanDeletionCandidate cleans CA's soft NoSchedule taint from a node.
292
293
func CleanDeletionCandidate (node * apiv1.Node , client kube_client.Interface ) (bool , error ) {
293
- return CleanTaint (node , client , DeletionCandidateTaint , false )
294
+ return CleanTaints (node , client , [] string { DeletionCandidateTaint } , false )
294
295
}
295
296
296
- // CleanTaint cleans the specified taint from a node.
297
- func CleanTaint (node * apiv1.Node , client kube_client.Interface , taintKey string , cordonNode bool ) (bool , error ) {
297
+ // CleanTaints cleans the specified taints from a node.
298
+ func CleanTaints (node * apiv1.Node , client kube_client.Interface , taintKeys [] string , cordonNode bool ) (bool , error ) {
298
299
retryDeadline := time .Now ().Add (maxRetryDeadline )
299
300
freshNode := node .DeepCopy ()
300
301
var err error
@@ -304,15 +305,21 @@ func CleanTaint(node *apiv1.Node, client kube_client.Interface, taintKey string,
304
305
// Get the newest version of the node.
305
306
freshNode , err = client .CoreV1 ().Nodes ().Get (context .TODO (), node .Name , metav1.GetOptions {})
306
307
if err != nil || freshNode == nil {
307
- klog .Warningf ("Error while adding %v taint on node %v: %v" , getKeyShortName ( taintKey ), node .Name , err )
308
+ klog .Warningf ("Error while removing %v taints from node %v: %v" , strings . Join ( taintKeys , "," ), node .Name , err )
308
309
return false , fmt .Errorf ("failed to get node %v: %v" , node .Name , err )
309
310
}
310
311
}
311
312
newTaints := make ([]apiv1.Taint , 0 )
312
313
for _ , taint := range freshNode .Spec .Taints {
313
- if taint .Key == taintKey {
314
- klog .V (1 ).Infof ("Releasing taint %+v on node %v" , taint , node .Name )
315
- } else {
314
+ keepTaint := true
315
+ for _ , taintKey := range taintKeys {
316
+ if taint .Key == taintKey {
317
+ klog .V (1 ).Infof ("Releasing taint %+v on node %v" , taint , node .Name )
318
+ keepTaint = false
319
+ break
320
+ }
321
+ }
322
+ if keepTaint {
316
323
newTaints = append (newTaints , taint )
317
324
}
318
325
}
@@ -339,37 +346,41 @@ func CleanTaint(node *apiv1.Node, client kube_client.Interface, taintKey string,
339
346
}
340
347
341
348
if err != nil {
342
- klog .Warningf ("Error while releasing %v taint on node %v: %v" , getKeyShortName ( taintKey ), node .Name , err )
349
+ klog .Warningf ("Error while releasing %v taints on node %v: %v" , strings . Join ( taintKeys , "," ), node .Name , err )
343
350
return false , err
344
351
}
345
- klog .V (1 ).Infof ("Successfully released %v on node %v" , getKeyShortName ( taintKey ), node .Name )
352
+ klog .V (1 ).Infof ("Successfully released %v on node %v" , strings . Join ( taintKeys , "," ), node .Name )
346
353
return true , nil
347
354
}
348
355
}
349
356
350
357
// CleanAllToBeDeleted cleans ToBeDeleted taints from given nodes.
351
358
func CleanAllToBeDeleted (nodes []* apiv1.Node , client kube_client.Interface , recorder kube_record.EventRecorder , cordonNode bool ) {
352
- CleanAllTaints (nodes , client , recorder , ToBeDeletedTaint , cordonNode )
359
+ CleanAllTaints (nodes , client , recorder , [] string { ToBeDeletedTaint } , cordonNode )
353
360
}
354
361
355
362
// CleanAllDeletionCandidates cleans DeletionCandidate taints from given nodes.
356
363
func CleanAllDeletionCandidates (nodes []* apiv1.Node , client kube_client.Interface , recorder kube_record.EventRecorder ) {
357
- CleanAllTaints (nodes , client , recorder , DeletionCandidateTaint , false )
364
+ CleanAllTaints (nodes , client , recorder , [] string { DeletionCandidateTaint } , false )
358
365
}
359
366
360
367
// CleanAllTaints cleans all specified taints from given nodes.
361
- func CleanAllTaints (nodes []* apiv1.Node , client kube_client.Interface , recorder kube_record.EventRecorder , taintKey string , cordonNode bool ) {
368
+ func CleanAllTaints (nodes []* apiv1.Node , client kube_client.Interface , recorder kube_record.EventRecorder , taintKeys [] string , cordonNode bool ) {
362
369
for _ , node := range nodes {
363
- if ! HasTaint (node , taintKey ) {
370
+ taintsPresent := false
371
+ for _ , taintKey := range taintKeys {
372
+ taintsPresent = taintsPresent || HasTaint (node , taintKey )
373
+ }
374
+ if ! taintsPresent {
364
375
continue
365
376
}
366
- cleaned , err := CleanTaint (node , client , taintKey , cordonNode )
377
+ cleaned , err := CleanTaints (node , client , taintKeys , cordonNode )
367
378
if err != nil {
368
379
recorder .Eventf (node , apiv1 .EventTypeWarning , "ClusterAutoscalerCleanup" ,
369
- "failed to clean %v on node %v: %v" , getKeyShortName ( taintKey ), node .Name , err )
380
+ "failed to clean %v on node %v: %v" , strings . Join ( taintKeys , "," ), node .Name , err )
370
381
} else if cleaned {
371
382
recorder .Eventf (node , apiv1 .EventTypeNormal , "ClusterAutoscalerCleanup" ,
372
- "removed %v taint from node %v" , getKeyShortName ( taintKey ), node .Name )
383
+ "removed %v taints from node %v" , strings . Join ( taintKeys , "," ), node .Name )
373
384
}
374
385
}
375
386
}
0 commit comments