@@ -492,10 +492,11 @@ func (ev *Evaluator) prepareCandidateAsync(c Candidate, pod *v1.Pod, pluginName
492
492
defer metrics .PreemptionGoroutinesDuration .WithLabelValues (result ).Observe (metrics .SinceInSeconds (startTime ))
493
493
defer metrics .PreemptionGoroutinesExecutionTotal .WithLabelValues (result ).Inc ()
494
494
defer func () {
495
- ev .mu .Lock ()
496
- ev .preempting .Delete (pod .UID )
497
- ev .mu .Unlock ()
498
- ev .Handler .Activate (logger , map [string ]* v1.Pod {pod .Name : pod })
495
+ if result == metrics .GoroutineResultError {
496
+ // When API call isn't successful, the Pod may get stuck in the unschedulable pod pool in the worst case.
497
+ // So, we should move the Pod to the activeQ.
498
+ ev .Handler .Activate (logger , map [string ]* v1.Pod {pod .Name : pod })
499
+ }
499
500
}()
500
501
defer cancel ()
501
502
logger .V (2 ).Info ("Start the preemption asynchronously" , "preemptor" , klog .KObj (pod ), "node" , c .Name (), "numVictims" , len (c .Victims ().Pods ))
@@ -512,15 +513,34 @@ func (ev *Evaluator) prepareCandidateAsync(c Candidate, pod *v1.Pod, pluginName
512
513
}
513
514
514
515
if len (c .Victims ().Pods ) == 0 {
516
+ ev .mu .Lock ()
517
+ delete (ev .preempting , pod .UID )
518
+ ev .mu .Unlock ()
519
+
515
520
return
516
521
}
517
522
518
- ev .Handler .Parallelizer ().Until (ctx , len (c .Victims ().Pods ), preemptPod , ev .PluginName )
523
+ // We can evict all victims in parallel, but the last one.
524
+ // We have to remove the pod from the preempting map before the last one is evicted
525
+ // because, otherwise, the pod removal might be notified to the scheduling queue before
526
+ // we remove this pod from the preempting map,
527
+ // and the pod could end up stucking at the unschedulable pod pool
528
+ // by all the pod removal events being ignored.
529
+ ev .Handler .Parallelizer ().Until (ctx , len (c .Victims ().Pods )- 1 , preemptPod , ev .PluginName )
519
530
if err := errCh .ReceiveError (); err != nil {
520
531
logger .Error (err , "Error occurred during async preemption" )
521
532
result = metrics .GoroutineResultError
522
533
}
523
534
535
+ ev .mu .Lock ()
536
+ delete (ev .preempting , pod .UID )
537
+ ev .mu .Unlock ()
538
+
539
+ if err := ev .PreemptPod (ctx , c , pod , c .Victims ().Pods [len (c .Victims ().Pods )- 1 ], pluginName ); err != nil {
540
+ logger .Error (err , "Error occurred during async preemption" )
541
+ result = metrics .GoroutineResultError
542
+ }
543
+
524
544
logger .V (2 ).Info ("Async Preemption finished completely" , "preemptor" , klog .KObj (pod ), "node" , c .Name (), "result" , result )
525
545
}()
526
546
}
0 commit comments