Skip to content

Commit 4168923

Browse files
authored
Merge pull request kubernetes#120334 from pohly/scheduler-clear-unschedulable-plugins
scheduler: avoid false "unschedulable" pod state
2 parents 817488e + 4e73634 commit 4168923

File tree

2 files changed

+96
-11
lines changed

2 files changed

+96
-11
lines changed

pkg/scheduler/internal/queue/scheduling_queue.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -840,9 +840,11 @@ func (p *PriorityQueue) Pop() (*framework.QueuedPodInfo, error) {
840840
p.inFlightPods[pInfo.Pod.UID] = p.inFlightEvents.PushBack(pInfo.Pod)
841841
}
842842

843+
// Update metrics and reset the set of unschedulable plugins for the next attempt.
843844
for plugin := range pInfo.UnschedulablePlugins {
844845
metrics.UnschedulableReason(plugin, pInfo.Pod.Spec.SchedulerName).Dec()
845846
}
847+
pInfo.UnschedulablePlugins.Clear()
846848

847849
return pInfo, nil
848850
}

pkg/scheduler/internal/queue/scheduling_queue_test.go

Lines changed: 94 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -201,17 +201,6 @@ func Test_InFlightPods(t *testing.T) {
201201
callback func(t *testing.T, q *PriorityQueue)
202202
}
203203

204-
popPod := func(t *testing.T, q *PriorityQueue, pod *v1.Pod) *framework.QueuedPodInfo {
205-
p, err := q.Pop()
206-
if err != nil {
207-
t.Fatalf("Pop failed: %v", err)
208-
}
209-
if p.Pod.UID != pod.UID {
210-
t.Errorf("Unexpected popped pod: %v", p)
211-
}
212-
return p
213-
}
214-
215204
tests := []struct {
216205
name string
217206
queueingHintMap QueueingHintMapPerProfile
@@ -542,6 +531,47 @@ func Test_InFlightPods(t *testing.T) {
542531
},
543532
},
544533
},
534+
{
535+
name: "popped pod must have empty UnschedulablePlugins",
536+
isSchedulingQueueHintEnabled: true,
537+
initialPods: []*v1.Pod{pod},
538+
actions: []action{
539+
{callback: func(t *testing.T, q *PriorityQueue) { poppedPod = popPod(t, q, pod) }},
540+
{callback: func(t *testing.T, q *PriorityQueue) {
541+
logger, _ := ktesting.NewTestContext(t)
542+
// Unschedulable.
543+
poppedPod.UnschedulablePlugins = sets.New("fooPlugin1")
544+
if err := q.AddUnschedulableIfNotPresent(logger, poppedPod, q.SchedulingCycle()); err != nil {
545+
t.Errorf("Unexpected error from AddUnschedulableIfNotPresent: %v", err)
546+
}
547+
}},
548+
{eventHappens: &PvAdd}, // Active again.
549+
{callback: func(t *testing.T, q *PriorityQueue) {
550+
poppedPod = popPod(t, q, pod)
551+
if len(poppedPod.UnschedulablePlugins) > 0 {
552+
t.Errorf("QueuedPodInfo from Pop should have empty UnschedulablePlugins, got instead: %+v", poppedPod)
553+
}
554+
}},
555+
{callback: func(t *testing.T, q *PriorityQueue) {
556+
logger, _ := ktesting.NewTestContext(t)
557+
// Failed (i.e. no UnschedulablePlugins). Should go to backoff.
558+
if err := q.AddUnschedulableIfNotPresent(logger, poppedPod, q.SchedulingCycle()); err != nil {
559+
t.Errorf("Unexpected error from AddUnschedulableIfNotPresent: %v", err)
560+
}
561+
}},
562+
},
563+
queueingHintMap: QueueingHintMapPerProfile{
564+
"": {
565+
PvAdd: {
566+
{
567+
// The hint fn tells that this event makes a Pod scheudlable immediately.
568+
PluginName: "fooPlugin1",
569+
QueueingHintFn: queueHintReturnQueueImmediately,
570+
},
571+
},
572+
},
573+
},
574+
},
545575
}
546576

547577
for _, test := range tests {
@@ -642,6 +672,59 @@ func Test_InFlightPods(t *testing.T) {
642672
}
643673
}
644674

675+
func popPod(t *testing.T, q *PriorityQueue, pod *v1.Pod) *framework.QueuedPodInfo {
676+
p, err := q.Pop()
677+
if err != nil {
678+
t.Fatalf("Pop failed: %v", err)
679+
}
680+
if p.Pod.UID != pod.UID {
681+
t.Errorf("Unexpected popped pod: %v", p)
682+
}
683+
return p
684+
}
685+
686+
func TestPop(t *testing.T) {
687+
pod := st.MakePod().Name("targetpod").UID("pod1").Obj()
688+
queueingHintMap := QueueingHintMapPerProfile{
689+
"": {
690+
PvAdd: {
691+
{
692+
// The hint fn tells that this event makes a Pod scheudlable immediately.
693+
PluginName: "fooPlugin1",
694+
QueueingHintFn: queueHintReturnQueueImmediately,
695+
},
696+
},
697+
},
698+
}
699+
700+
for name, isSchedulingQueueHintEnabled := range map[string]bool{"with-hints": true, "without-hints": false} {
701+
t.Run(name, func(t *testing.T) {
702+
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SchedulerQueueingHints, isSchedulingQueueHintEnabled)()
703+
logger, ctx := ktesting.NewTestContext(t)
704+
ctx, cancel := context.WithCancel(ctx)
705+
defer cancel()
706+
q := NewTestQueueWithObjects(ctx, newDefaultQueueSort(), []runtime.Object{pod}, WithQueueingHintMapPerProfile(queueingHintMap))
707+
q.Add(logger, pod)
708+
709+
// Simulate failed attempt that makes the pod unschedulable.
710+
poppedPod := popPod(t, q, pod)
711+
poppedPod.UnschedulablePlugins = sets.New("fooPlugin1")
712+
if err := q.AddUnschedulableIfNotPresent(logger, poppedPod, q.SchedulingCycle()); err != nil {
713+
t.Errorf("Unexpected error from AddUnschedulableIfNotPresent: %v", err)
714+
}
715+
716+
// Activate it again.
717+
q.MoveAllToActiveOrBackoffQueue(logger, PvAdd, nil, nil, nil)
718+
719+
// Now check result of Pop.
720+
poppedPod = popPod(t, q, pod)
721+
if len(poppedPod.UnschedulablePlugins) > 0 {
722+
t.Errorf("QueuedPodInfo from Pop should have empty UnschedulablePlugins, got instead: %+v", poppedPod)
723+
}
724+
})
725+
}
726+
}
727+
645728
func TestPriorityQueue_AddUnschedulableIfNotPresent(t *testing.T) {
646729
objs := []runtime.Object{highPriNominatedPodInfo.Pod, unschedulablePodInfo.Pod}
647730
logger, ctx := ktesting.NewTestContext(t)

0 commit comments

Comments
 (0)