Change:
This is a bug found in The scheduler fails to schedule the pod on the first try due to PV is out of sync. This may happen because the PV/PVC may be modified before the scheduler binder assumes them. However, the scheduler skips the pod update event and never try to scheduler the pod again: This is because when the reserve plugins fails, we didn't try to forget the pod. After the is called, the pod is in the state.
/sig scheduling /sig storage /assign /priority critical-urgent
The label(s) cannot be applied, because the repository doesn't have them <detailsIn response to : /sig scheduling /sig storage /assign /priority critical-urgent Instructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details

Discussion:
} if err != nil { klog.V(1).Infof("Failed to bind pod: %v/%v", assumed.Namespace, assumed.Name) <del> if err := sched.SchedulerCache.ForgetPod(assumed); err != nil { klog.Errorf("scheduler cache ForgetPod failed: %v", err) } </del> return }

// assume modifies `assumedPod` by setting NodeName=scheduleResult.SuggestedHost err = sched.assume(assumedPod, scheduleResult.SuggestedHost) if err != nil { <ins> metrics.PodScheduleError(prof.Name, metrics.SinceInSeconds(start)) </ins> // This is most probably result of a BUG in retrying logic. // We report an error here so that pod scheduling can be retried. // This relies on the fact that Error will check if the pod has been bound // to a node and if so will not add it back to the unscheduled pods queue // (otherwise this would cause an infinite loop). sched.recordSchedulingFailure(prof, assumedPodInfo, err, SchedulerError, "") <del> metrics.PodScheduleError(prof.Name, metrics.SinceInSeconds(start)) </del> return } // Run the Reserve method of reserve plugins. if sts := prof.RunReservePluginsReserve(schedulingCycleCtx, state, assumedPod, scheduleResult.SuggestedHost); !sts.IsSuccess() { <del> sched.recordSchedulingFailure(prof, assumedPodInfo, sts.AsError(), SchedulerError, "") </del> metrics.PodScheduleError(prof.Name, metrics.SinceInSeconds(start)) // trigger un-reserve to clean up state associated with the reserved Pod prof.RunReservePluginsUnreserve(schedulingCycleCtx, state, assumedPod, scheduleResult.SuggestedHost) <ins> if forgetErr := sched.Cache().ForgetPod(assumedPod); forgetErr != nil { klog.Errorf("scheduler cache ForgetPod failed: %v", forgetErr) } sched.recordSchedulingFailure(prof, assumedPodInfo, sts.AsError(), SchedulerError, "") </ins> return }

metrics.PodScheduleError(prof.Name, metrics.SinceInSeconds(start)) // trigger un-reserve plugins to clean up state associated with the reserved Pod prof.RunReservePluginsUnreserve(bindingCycleCtx, state, assumedPod, scheduleResult.SuggestedHost) <ins> if err := sched.SchedulerCache.ForgetPod(assumedPod); err != nil { klog.Errorf("scheduler cache ForgetPod failed: %v", err) } </ins> sched.recordSchedulingFailure(prof, assumedPodInfo, fmt.Errorf("Binding rejected: %v", err), SchedulerError, "") } else { // Calculating nodeResourceString can be heavy. Avoid it if klog verbosity is below 2.

errB := errors.New("binder") table := []struct { <del> name             string injectBindError  error sendPod          *v1.Pod algo             core.ScheduleAlgorithm expectErrorPod   *v1.Pod expectForgetPod  *v1.Pod expectAssumedPod *v1.Pod expectError      error expectBind       *v1.Binding eventReason      string </del> <ins> name                string injectBindError     error sendPod             *v1.Pod algo                core.ScheduleAlgorithm registerPluginFuncs []st.RegisterPluginFunc expectErrorPod      *v1.Pod expectForgetPod     *v1.Pod expectAssumedPod    *v1.Pod expectError         error expectBind          *v1.Binding eventReason         string </ins> }{ { <ins> name:    "error reserve pod", sendPod: podWithID("foo", ""), algo:    mockScheduler{core.ScheduleResult{SuggestedHost: testNode.Name, EvaluatedNodes: 1, FeasibleNodes: 1}, nil}, registerPluginFuncs: []st.RegisterPluginFunc{ st.RegisterReservePlugin("FakeReserve", st.NewFakeReservePlugin(framework.NewStatus(framework.Error, "reserve error"))), }, expectErrorPod:   podWithID("foo", testNode.Name), expectForgetPod:  podWithID("foo", testNode.Name), expectAssumedPod: podWithID("foo", testNode.Name), expectError:      errors.New(`error while running Reserve in "FakeReserve" reserve plugin for pod "foo": reserve error`), eventReason:      "FailedScheduling", }, { name:    "error permit pod", sendPod: podWithID("foo", ""), algo:    mockScheduler{core.ScheduleResult{SuggestedHost: testNode.Name, EvaluatedNodes: 1, FeasibleNodes: 1}, nil}, registerPluginFuncs: []st.RegisterPluginFunc{ st.RegisterPermitPlugin("FakePermit", st.NewFakePermitPlugin(framework.NewStatus(framework.Error, "permit error"), time.Minute)), }, expectErrorPod:   podWithID("foo", testNode.Name), expectForgetPod:  podWithID("foo", testNode.Name), expectAssumedPod: podWithID("foo", testNode.Name), expectError:      errors.New(`error while running "FakePermit" permit plugin for pod "foo": permit error`), eventReason:      "FailedScheduling", }, { name:    "error prebind pod", sendPod: podWithID("foo", ""), algo:    mockScheduler{core.ScheduleResult{SuggestedHost: testNode.Name, EvaluatedNodes: 1, FeasibleNodes: 1}, nil}, registerPluginFuncs: []st.RegisterPluginFunc{ st.RegisterPreBindPlugin("FakePreBind", st.NewFakePreBindPlugin(framework.NewStatus(framework.Error, "prebind error"))), }, expectErrorPod:   podWithID("foo", testNode.Name), expectForgetPod:  podWithID("foo", testNode.Name), expectAssumedPod: podWithID("foo", testNode.Name), expectError:      errors.New(`error while running "FakePreBind" prebind plugin for pod "foo": prebind error`), eventReason:      "FailedScheduling", }, { </ins> name:             "bind assumed pod scheduled", sendPod:          podWithID("foo", ""), algo:             mockScheduler{core.ScheduleResult{SuggestedHost: testNode.Name, EvaluatedNodes: 1, FeasibleNodes: 1}, nil},

expectErrorPod:   podWithID("foo", testNode.Name), expectForgetPod:  podWithID("foo", testNode.Name), eventReason:      "FailedScheduling", <del> }, { </del> <ins> }, { </ins> name:        "deleting pod", sendPod:     deletingPod("foo"), algo:        mockScheduler{core.ScheduleResult{}, nil},

gotBinding = action.(clienttesting.CreateAction).GetObject().(*v1.Binding) return true, gotBinding, item.injectBindError }) <del> fwk, err := st.NewFramework([]st.RegisterPluginFunc{ </del> <ins> registerPluginFuncs := append(item.registerPluginFuncs, </ins> st.RegisterQueueSortPlugin(queuesort.Name, queuesort.New), st.RegisterBindPlugin(defaultbinder.Name, defaultbinder.New), <del> }, frameworkruntime.WithClientSet(client)) </del> <ins> ) fwk, err := st.NewFramework(registerPluginFuncs, frameworkruntime.WithClientSet(client)) </ins> if err != nil { t.Fatal(err) }

"context" "fmt" "sync/atomic" <ins> "time" </ins> v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime"

}, nil } } <ins> // FakeReservePlugin is a test reserve plugin. type FakeReservePlugin struct { Status *framework.Status } // Name returns name of the plugin. func (pl *FakeReservePlugin) Name() string { return "FakeReserve" } // Reserve invoked at the Reserve extension point. func (pl *FakeReservePlugin) Reserve(_ context.Context, _ *framework.CycleState, _ *v1.Pod, _ string) *framework.Status { return pl.Status } // Unreserve invoked at the Unreserve extension point. func (pl *FakeReservePlugin) Unreserve(_ context.Context, _ *framework.CycleState, _ *v1.Pod, _ string) { } // NewFakeReservePlugin initializes a fakeReservePlugin and returns it. func NewFakeReservePlugin(status *framework.Status) frameworkruntime.PluginFactory { return func(_ runtime.Object, _ framework.FrameworkHandle) (framework.Plugin, error) { return &FakeReservePlugin{ Status: status, }, nil } } // FakePreBindPlugin is a test prebind plugin. type FakePreBindPlugin struct { Status *framework.Status } // Name returns name of the plugin. func (pl *FakePreBindPlugin) Name() string { return "FakePreBind" } // PreBind invoked at the PreBind extension point. func (pl *FakePreBindPlugin) PreBind(_ context.Context, _ *framework.CycleState, _ *v1.Pod, _ string) *framework.Status { return pl.Status } // NewFakePreBindPlugin initializes a fakePreBindPlugin and returns it. func NewFakePreBindPlugin(status *framework.Status) frameworkruntime.PluginFactory { return func(_ runtime.Object, _ framework.FrameworkHandle) (framework.Plugin, error) { return &FakePreBindPlugin{ Status: status, }, nil } } // FakePermitPlugin is a test permit plugin. type FakePermitPlugin struct { Status  *framework.Status Timeout time.Duration } // Name returns name of the plugin. func (pl *FakePermitPlugin) Name() string { return "FakePermit" } // Permit invoked at the Permit extension point. func (pl *FakePermitPlugin) Permit(_ context.Context, _ *framework.CycleState, _ *v1.Pod, _ string) (*framework.Status, time.Duration) { return pl.Status, pl.Timeout } // NewFakePermitPlugin initializes a fakePermitPlugin and returns it. func NewFakePermitPlugin(status *framework.Status, timeout time.Duration) frameworkruntime.PluginFactory { return func(_ runtime.Object, _ framework.FrameworkHandle) (framework.Plugin, error) { return &FakePermitPlugin{ Status:  status, Timeout: timeout, }, nil } } </ins>

return RegisterPluginAsExtensions(pluginName, pluginNewFunc, "Filter") } <ins> // RegisterReservePlugin returns a function to register a Reserve Plugin to a given registry. func RegisterReservePlugin(pluginName string, pluginNewFunc runtime.PluginFactory) RegisterPluginFunc { return RegisterPluginAsExtensions(pluginName, pluginNewFunc, "Reserve") } // RegisterPermitPlugin returns a function to register a Permit Plugin to a given registry. func RegisterPermitPlugin(pluginName string, pluginNewFunc runtime.PluginFactory) RegisterPluginFunc { return RegisterPluginAsExtensions(pluginName, pluginNewFunc, "Permit") } // RegisterPreBindPlugin returns a function to register a PreBind Plugin to a given registry. func RegisterPreBindPlugin(pluginName string, pluginNewFunc runtime.PluginFactory) RegisterPluginFunc { return RegisterPluginAsExtensions(pluginName, pluginNewFunc, "PreBind") } </ins> // RegisterScorePlugin returns a function to register a Score Plugin to a given registry. func RegisterScorePlugin(pluginName string, pluginNewFunc runtime.PluginFactory, weight int32) RegisterPluginFunc { return RegisterPluginAsExtensionsWithWeight(pluginName, weight, pluginNewFunc, "Score")