From c339eafb7610853051b99703a58c07ebde44fb5b Mon Sep 17 00:00:00 2001 From: Patrick Ohly Date: Thu, 6 Jun 2024 15:28:08 +0200 Subject: [PATCH] scheduler: allow PreBind to return "Pending" and "Unschedulable" Any error result from PreBind was treated as a pod scheduling failure. This was overlooked when moving blocking API calls in the DRA plugin into a PreBind implementation, leading to: E0604 15:45:50.980929 306340 schedule_one.go:1048] "Error scheduling pod; retrying" err="waiting for resource driver" pod="test/test-draqld28" That's because DRA's PreBind does some updates in the apiserver, then returns Pending to wait for the outcome. The fix is to allow PreBind to return the same special status codes as other extension points. --- pkg/scheduler/framework/types.go | 2 +- pkg/scheduler/schedule_one.go | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/pkg/scheduler/framework/types.go b/pkg/scheduler/framework/types.go index 687143e520a..9b4c0b874c4 100644 --- a/pkg/scheduler/framework/types.go +++ b/pkg/scheduler/framework/types.go @@ -208,7 +208,7 @@ type QueuedPodInfo struct { // latency for a pod. InitialAttemptTimestamp *time.Time // UnschedulablePlugins records the plugin names that the Pod failed with Unschedulable or UnschedulableAndUnresolvable status. - // It's registered only when the Pod is rejected in PreFilter, Filter, Reserve, or Permit (WaitOnPermit). + // It's registered only when the Pod is rejected in PreFilter, Filter, Reserve, PreBind or Permit (WaitOnPermit). UnschedulablePlugins sets.Set[string] // PendingPlugins records the plugin names that the Pod failed with Pending status. PendingPlugins sets.Set[string] diff --git a/pkg/scheduler/schedule_one.go b/pkg/scheduler/schedule_one.go index 33f68468d2c..9324a7f1e12 100644 --- a/pkg/scheduler/schedule_one.go +++ b/pkg/scheduler/schedule_one.go @@ -292,6 +292,17 @@ func (sched *Scheduler) bindingCycle( // Run "prebind" plugins. if status := fwk.RunPreBindPlugins(ctx, state, assumedPod, scheduleResult.SuggestedHost); !status.IsSuccess() { + if status.IsRejected() { + fitErr := &framework.FitError{ + NumAllNodes: 1, + Pod: assumedPodInfo.Pod, + Diagnosis: framework.Diagnosis{ + NodeToStatusMap: framework.NodeToStatusMap{scheduleResult.SuggestedHost: status}, + UnschedulablePlugins: sets.New(status.Plugin()), + }, + } + return framework.NewStatus(status.Code()).WithError(fitErr) + } return status }