Clear plugins at handleSchedulingFailure and preserve both at Pop

This commit is contained in:
Mohammad Varmazyar
2025-11-24 20:32:41 +01:00
parent ec05bcf186
commit d64e09c697
3 changed files with 18 additions and 12 deletions

View File

@@ -323,14 +323,13 @@ func (aq *activeQueue) unlockedPop(logger klog.Logger) (*framework.QueuedPodInfo
}
aq.schedCycle++
// Update metrics and reset the set of pending plugins for the next attempt.
// Note: We don't clear UnschedulablePlugins here because:
// 1. If the pod schedules successfully, we need UnschedulablePlugins for logging/debugging
// 2. If the pod fails to schedule again, UnschedulablePlugins will be overwritten anyway
// Update metrics for unschedulable plugins.
// Note: We don't clear UnschedulablePlugins and PendingPlugins here because:
// 1. If the pod schedules successfully, we need them for logging/debugging
// 2. If the pod fails to schedule, they will be cleared and repopulated in handleSchedulingFailure
for plugin := range pInfo.UnschedulablePlugins.Union(pInfo.PendingPlugins) {
metrics.UnschedulableReason(plugin, pInfo.Pod.Spec.SchedulerName).Dec()
}
pInfo.PendingPlugins.Clear()
pInfo.GatingPlugin = ""
pInfo.GatingPluginEvents = nil

View File

@@ -649,7 +649,7 @@ func Test_InFlightPods(t *testing.T) {
},
},
{
name: "popped pod preserves UnschedulablePlugins but clears PendingPlugins",
name: "popped pod preserves UnschedulablePlugins and PendingPlugins",
isSchedulingQueueHintEnabled: true,
initialPods: []*v1.Pod{pod1},
actions: []action{
@@ -670,9 +670,9 @@ func Test_InFlightPods(t *testing.T) {
if !poppedPod.UnschedulablePlugins.Equal(sets.New("fooPlugin2")) {
t.Errorf("QueuedPodInfo from Pop should preserve UnschedulablePlugins, expected fooPlugin2, got: %+v", poppedPod.UnschedulablePlugins)
}
// PendingPlugins should still be cleared
if len(poppedPod.PendingPlugins) > 0 {
t.Errorf("QueuedPodInfo from Pop should have empty PendingPlugins, got instead: %+v", poppedPod.PendingPlugins)
// PendingPlugins are preserved after Pop() for logging
if !poppedPod.PendingPlugins.Equal(sets.New("fooPlugin1")) {
t.Errorf("QueuedPodInfo from Pop should preserve PendingPlugins, expected fooPlugin1, got: %+v", poppedPod.PendingPlugins)
}
}},
{callback: func(t *testing.T, q *PriorityQueue) {
@@ -940,8 +940,10 @@ func TestPop(t *testing.T) {
// Now check result of Pop.
poppedPod = popPod(t, logger, q, pod)
if len(poppedPod.PendingPlugins) > 0 {
t.Errorf("QueuedPodInfo from Pop should have empty PendingPlugins, got instead: %+v", poppedPod)
// PendingPlugins are preserved after Pop() so they can be logged if scheduling
// succeeds, or cleared in handleSchedulingFailure() if it fails.
if len(poppedPod.PendingPlugins) != 1 || !poppedPod.PendingPlugins.Has("fooPlugin1") {
t.Errorf("QueuedPodInfo from Pop should preserve PendingPlugins, expected fooPlugin1, got instead: %+v", poppedPod)
}
})
}

View File

@@ -342,7 +342,7 @@ func (sched *Scheduler) bindingCycle(
}
// Count pods scheduled after being flushed from unschedulablePods
if assumedPodInfo.WasFlushedFromUnschedulable {
logger.Info("Pod scheduled after flush from unschedulablePods", "pod", klog.KObj(assumedPodInfo.Pod), "unschedulablePlugins", assumedPodInfo.UnschedulablePlugins)
logger.Info("Pod scheduled after flush from unschedulablePods", "pod", klog.KObj(assumedPodInfo.Pod), "unschedulablePlugins", assumedPodInfo.UnschedulablePlugins, "pendingPlugins", assumedPodInfo.PendingPlugins)
metrics.PodScheduledAfterFlush.Inc()
}
// Run "postbind" plugins.
@@ -1063,6 +1063,11 @@ func (sched *Scheduler) handleSchedulingFailure(ctx context.Context, fwk framewo
err := status.AsError()
errMsg := status.Message()
// Clear plugin sets to avoid stale data from previous scheduling attempts.
// They will be repopulated below for FitError cases.
podInfo.UnschedulablePlugins.Clear()
podInfo.PendingPlugins.Clear()
if err == ErrNoNodesAvailable {
logger.V(2).Info("Unable to schedule pod; no nodes are registered to the cluster; waiting", "pod", klog.KObj(pod))
} else if fitError, ok := err.(*framework.FitError); ok { // Inject UnschedulablePlugins to PodInfo, which will be used later for moving Pods between queues efficiently.