Skip to content

Commit b3741f3

Browse files
committed
The Pod is eligible to preempt when previous nominanted node is UnschedulableAndUnresolvable
If the Pod's previous nominated node is UnschedulableAndUnresolvable from previous filtering, it should be considered for preemption again.
1 parent 6cedc08 commit b3741f3

File tree

3 files changed

+69
-2
lines changed

3 files changed

+69
-2
lines changed

pkg/scheduler/framework/plugins/defaultpreemption/default_preemption.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ func preempt(ctx context.Context, fh framework.FrameworkHandle, state *framework
106106
return "", err
107107
}
108108

109-
if !podEligibleToPreemptOthers(pod, fh.SnapshotSharedLister().NodeInfos()) {
109+
if !podEligibleToPreemptOthers(pod, fh.SnapshotSharedLister().NodeInfos(), m[pod.Status.NominatedNodeName]) {
110110
klog.V(5).Infof("Pod %v/%v is not eligible for more preemption.", pod.Namespace, pod.Name)
111111
return "", nil
112112
}
@@ -189,13 +189,19 @@ func preempt(ctx context.Context, fh framework.FrameworkHandle, state *framework
189189
// considered for preemption.
190190
// We look at the node that is nominated for this pod and as long as there are
191191
// terminating pods on the node, we don't consider this for preempting more pods.
192-
func podEligibleToPreemptOthers(pod *v1.Pod, nodeInfos framework.NodeInfoLister) bool {
192+
func podEligibleToPreemptOthers(pod *v1.Pod, nodeInfos framework.NodeInfoLister, nominatedNodeStatus *framework.Status) bool {
193193
if pod.Spec.PreemptionPolicy != nil && *pod.Spec.PreemptionPolicy == v1.PreemptNever {
194194
klog.V(5).Infof("Pod %v/%v is not eligible for preemption because it has a preemptionPolicy of %v", pod.Namespace, pod.Name, v1.PreemptNever)
195195
return false
196196
}
197197
nomNodeName := pod.Status.NominatedNodeName
198198
if len(nomNodeName) > 0 {
199+
// If the pod's nominated node is considered as UnschedulableAndUnresolvable by the filters,
200+
// then the pod should be considered for preempting again.
201+
if nominatedNodeStatus.Code() == framework.UnschedulableAndUnresolvable {
202+
return true
203+
}
204+
199205
if nodeInfo, _ := nodeInfos.Get(nomNodeName); nodeInfo != nil {
200206
podPriority := podutil.GetPodPriority(pod)
201207
for _, p := range nodeInfo.Pods {

pkg/scheduler/framework/plugins/defaultpreemption/default_preemption_test.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -889,6 +889,61 @@ func TestPickOneNodeForPreemption(t *testing.T) {
889889
}
890890
}
891891

892+
func TestPodEligibleToPreemptOthers(t *testing.T) {
893+
tests := []struct {
894+
name string
895+
pod *v1.Pod
896+
pods []*v1.Pod
897+
nodes []string
898+
nominatedNodeStatus *framework.Status
899+
expected bool
900+
}{
901+
{
902+
name: "Pod with nominated node",
903+
pod: st.MakePod().Name("p_with_nominated_node").UID("p").Priority(highPriority).NominatedNodeName("node1").Obj(),
904+
pods: []*v1.Pod{st.MakePod().Name("p1").UID("p1").Priority(lowPriority).Node("node1").Terminating().Obj()},
905+
nodes: []string{"node1"},
906+
nominatedNodeStatus: framework.NewStatus(framework.UnschedulableAndUnresolvable, tainttoleration.ErrReasonNotMatch),
907+
expected: true,
908+
},
909+
{
910+
name: "Pod with nominated node, but without nominated node status",
911+
pod: st.MakePod().Name("p_without_status").UID("p").Priority(highPriority).NominatedNodeName("node1").Obj(),
912+
pods: []*v1.Pod{st.MakePod().Name("p1").UID("p1").Priority(lowPriority).Node("node1").Terminating().Obj()},
913+
nodes: []string{"node1"},
914+
nominatedNodeStatus: nil,
915+
expected: false,
916+
},
917+
{
918+
name: "Pod without nominated node",
919+
pod: st.MakePod().Name("p_without_nominated_node").UID("p").Priority(highPriority).Obj(),
920+
pods: []*v1.Pod{},
921+
nodes: []string{},
922+
nominatedNodeStatus: nil,
923+
expected: true,
924+
},
925+
{
926+
name: "Pod with 'PreemptNever' preemption policy",
927+
pod: st.MakePod().Name("p_with_preempt_never_policy").UID("p").Priority(highPriority).PreemptionPolicy(v1.PreemptNever).Obj(),
928+
pods: []*v1.Pod{},
929+
nodes: []string{},
930+
nominatedNodeStatus: nil,
931+
expected: false,
932+
},
933+
}
934+
935+
for _, test := range tests {
936+
var nodes []*v1.Node
937+
for _, n := range test.nodes {
938+
nodes = append(nodes, st.MakeNode().Name(n).Obj())
939+
}
940+
snapshot := internalcache.NewSnapshot(test.pods, nodes)
941+
if got := podEligibleToPreemptOthers(test.pod, snapshot.NodeInfos(), test.nominatedNodeStatus); got != test.expected {
942+
t.Errorf("expected %t, got %t for pod: %s", test.expected, got, test.pod.Name)
943+
}
944+
}
945+
}
946+
892947
func TestNodesWherePreemptionMightHelp(t *testing.T) {
893948
// Prepare 4 nodes names.
894949
nodeNames := []string{"node1", "node2", "node3", "node4"}

pkg/scheduler/testing/wrappers.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,12 @@ func (p *PodWrapper) StartTime(t metav1.Time) *PodWrapper {
244244
return p
245245
}
246246

247+
// NominatedNodeName sets `n` as the .Status.NominatedNodeName of the inner pod.
248+
func (p *PodWrapper) NominatedNodeName(n string) *PodWrapper {
249+
p.Status.NominatedNodeName = n
250+
return p
251+
}
252+
247253
// PodAffinityKind represents different kinds of PodAffinity.
248254
type PodAffinityKind int
249255

0 commit comments

Comments
 (0)