Skip to content

Commit 19883b5

Browse files
authored
Merge pull request kubernetes#92604 from soulxu/fix_preemption_with_nominated_node
The Pod is eligible to preempt when previous nominanted node is UnschedulableAndUnresolvable
2 parents a2aaae2 + b3741f3 commit 19883b5

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)