From 145adcd522b6962648a3f925a9c6d1a0fcf0369e Mon Sep 17 00:00:00 2001 From: Bartosz Date: Fri, 21 Nov 2025 14:51:49 +0000 Subject: [PATCH] Fix queue hint for interpodaffinity when target pod is updated --- .../plugins/interpodaffinity/plugin.go | 8 ++ .../plugins/interpodaffinity/plugin_test.go | 75 ++++++++++--------- 2 files changed, 49 insertions(+), 34 deletions(-) diff --git a/pkg/scheduler/framework/plugins/interpodaffinity/plugin.go b/pkg/scheduler/framework/plugins/interpodaffinity/plugin.go index e5d8463c724..952ef3398e1 100644 --- a/pkg/scheduler/framework/plugins/interpodaffinity/plugin.go +++ b/pkg/scheduler/framework/plugins/interpodaffinity/plugin.go @@ -173,6 +173,14 @@ func (pl *InterPodAffinity) isSchedulableAfterPodChange(logger klog.Logger, pod if err != nil { return fwk.Queue, err } + if modifiedPod != nil && originalPod != nil && pod.UID == modifiedPod.UID { + // The only update event we listen on is UpdatePodLabel, so we can assume the labels have changed. + // The pod can become schedulable after update to its labels because e.g. some other pod might have + // anti-affinity on the old labels but not on the new ones. + logger.V(5).Info("the target pod labels have changed and it may be schedulable now", + "pod", klog.KObj(pod)) + return fwk.Queue, nil + } if (modifiedPod != nil && modifiedPod.Spec.NodeName == "") || (originalPod != nil && originalPod.Spec.NodeName == "") { logger.V(5).Info("the added/updated/deleted pod is unscheduled, so it doesn't make the target pod schedulable", "pod", klog.KObj(pod), "originalPod", klog.KObj(originalPod), "modifiedPod", klog.KObj(modifiedPod)) diff --git a/pkg/scheduler/framework/plugins/interpodaffinity/plugin_test.go b/pkg/scheduler/framework/plugins/interpodaffinity/plugin_test.go index 7e7753a4b92..04231eac0a1 100644 --- a/pkg/scheduler/framework/plugins/interpodaffinity/plugin_test.go +++ b/pkg/scheduler/framework/plugins/interpodaffinity/plugin_test.go @@ -43,90 +43,97 @@ func Test_isSchedulableAfterPodChange(t *testing.T) { }{ { name: "add a pod which matches the pod affinity", - pod: st.MakePod().Name("p").PodAffinityIn("service", "region", []string{"securityscan", "value2"}, st.PodAffinityWithRequiredReq).Obj(), - newPod: st.MakePod().Node("fake-node").Label("service", "securityscan").Obj(), + pod: st.MakePod().UID("p").Name("p").PodAffinityIn("service", "region", []string{"securityscan", "value2"}, st.PodAffinityWithRequiredReq).Obj(), + newPod: st.MakePod().UID("other").Node("fake-node").Label("service", "securityscan").Obj(), expectedHint: fwk.Queue, }, { name: "add an un-scheduled pod", - pod: st.MakePod().Name("p").PodAffinityIn("service", "region", []string{"securityscan", "value2"}, st.PodAffinityWithRequiredReq).Obj(), - newPod: st.MakePod().Label("service", "securityscan").Obj(), + pod: st.MakePod().UID("p").Name("p").PodAffinityIn("service", "region", []string{"securityscan", "value2"}, st.PodAffinityWithRequiredReq).Obj(), + newPod: st.MakePod().UID("other").Label("service", "securityscan").Obj(), expectedHint: fwk.QueueSkip, }, { name: "add a pod which doesn't match the pod affinity", - pod: st.MakePod().Name("p").PodAffinityIn("service", "region", []string{"securityscan", "value2"}, st.PodAffinityWithRequiredReq).Obj(), - newPod: st.MakePod().Node("fake-node").Label("aaa", "a").Obj(), + pod: st.MakePod().UID("p").Name("p").PodAffinityIn("service", "region", []string{"securityscan", "value2"}, st.PodAffinityWithRequiredReq).Obj(), + newPod: st.MakePod().UID("other").Node("fake-node").Label("aaa", "a").Obj(), expectedHint: fwk.QueueSkip, }, { name: "update a pod from non-match to match pod affinity", - pod: st.MakePod().Name("p").PodAffinityIn("service", "region", []string{"securityscan", "value2"}, st.PodAffinityWithRequiredReq).Obj(), - newPod: st.MakePod().Node("fake-node").Label("service", "securityscan").Obj(), - oldPod: st.MakePod().Node("fake-node").Label("aaa", "a").Obj(), + pod: st.MakePod().UID("p").Name("p").PodAffinityIn("service", "region", []string{"securityscan", "value2"}, st.PodAffinityWithRequiredReq).Obj(), + newPod: st.MakePod().UID("other").Node("fake-node").Label("service", "securityscan").Obj(), + oldPod: st.MakePod().UID("other").Node("fake-node").Label("aaa", "a").Obj(), expectedHint: fwk.Queue, }, { name: "the updating pod matches target pod's affinity both before and after label changes", - pod: st.MakePod().Name("p").PodAffinityIn("service", "region", []string{"securityscan", "value2"}, st.PodAffinityWithRequiredReq).Obj(), - newPod: st.MakePod().Node("fake-node").Label("service", "securityscan").Obj(), - oldPod: st.MakePod().Node("fake-node").Label("service", "value2").Obj(), + pod: st.MakePod().UID("p").Name("p").PodAffinityIn("service", "region", []string{"securityscan", "value2"}, st.PodAffinityWithRequiredReq).Obj(), + newPod: st.MakePod().UID("other").Node("fake-node").Label("service", "securityscan").Obj(), + oldPod: st.MakePod().UID("other").Node("fake-node").Label("service", "value2").Obj(), expectedHint: fwk.QueueSkip, }, { name: "update an un-scheduled pod", - pod: st.MakePod().Name("p").PodAffinityIn("service", "region", []string{"securityscan", "value2"}, st.PodAffinityWithRequiredReq).Obj(), - newPod: st.MakePod().Label("service", "securityscan").Obj(), - oldPod: st.MakePod().Label("service", "securityscan").Obj(), + pod: st.MakePod().UID("p").Name("p").PodAffinityIn("service", "region", []string{"securityscan", "value2"}, st.PodAffinityWithRequiredReq).Obj(), + newPod: st.MakePod().UID("other").Label("service", "securityscan").Obj(), + oldPod: st.MakePod().UID("other").Label("aaa", "a").Obj(), expectedHint: fwk.QueueSkip, }, { name: "update a pod from match to non-match the pod affinity", - pod: st.MakePod().Name("p").PodAffinityIn("service", "region", []string{"securityscan", "value2"}, st.PodAffinityWithRequiredReq).Obj(), - newPod: st.MakePod().Node("fake-node").Label("aaa", "a").Obj(), - oldPod: st.MakePod().Node("fake-node").Label("service", "securityscan").Obj(), + pod: st.MakePod().UID("p").Name("p").PodAffinityIn("service", "region", []string{"securityscan", "value2"}, st.PodAffinityWithRequiredReq).Obj(), + newPod: st.MakePod().UID("other").Node("fake-node").Label("aaa", "a").Obj(), + oldPod: st.MakePod().UID("other").Node("fake-node").Label("service", "securityscan").Obj(), expectedHint: fwk.QueueSkip, }, { name: "update a pod from match to non-match pod's affinity - multiple terms case", - pod: st.MakePod().Name("p").PodAffinityExists("aaa", "hostname", st.PodAffinityWithRequiredReq). + pod: st.MakePod().UID("p").Name("p").PodAffinityExists("aaa", "hostname", st.PodAffinityWithRequiredReq). PodAffinityExists("bbb", "hostname", st.PodAffinityWithRequiredReq).Obj(), - newPod: st.MakePod().Node("fake-node").Label("service", "securityscan").Obj(), - oldPod: st.MakePod().Node("fake-node").Label("aaa", "a").Obj(), + newPod: st.MakePod().UID("other").Node("fake-node").Label("service", "securityscan").Obj(), + oldPod: st.MakePod().UID("other").Node("fake-node").Label("aaa", "a").Obj(), expectedHint: fwk.QueueSkip, }, { name: "update a pod from non-match to match pod's affinity - multiple terms case", - pod: st.MakePod().Name("p").PodAffinityExists("aaa", "hostname", st.PodAffinityWithRequiredReq). + pod: st.MakePod().UID("p").Name("p").PodAffinityExists("aaa", "hostname", st.PodAffinityWithRequiredReq). PodAffinityExists("bbb", "hostname", st.PodAffinityWithRequiredReq).Obj(), - newPod: st.MakePod().Node("fake-node").Label("aaa", "").Label("bbb", "").Obj(), - oldPod: st.MakePod().Node("fake-node").Label("aaa", "a").Obj(), + newPod: st.MakePod().UID("other").Node("fake-node").Label("aaa", "").Label("bbb", "").Obj(), + oldPod: st.MakePod().UID("other").Node("fake-node").Label("aaa", "a").Obj(), + expectedHint: fwk.Queue, + }, + { + name: "updated pod is the target pod", + pod: st.MakePod().UID("p").Name("p").Label("foo", "baz").Obj(), + newPod: st.MakePod().UID("p").Name("p").Label("foo", "baz").Obj(), + oldPod: st.MakePod().UID("p").Name("p").Label("foo", "bar").Obj(), expectedHint: fwk.Queue, }, { name: "modify pod label to change it from satisfying pod anti-affinity to not satisfying anti-affinity", - pod: st.MakePod().Name("p").PodAntiAffinityIn("service", "region", []string{"securityscan", "value2"}, st.PodAntiAffinityWithRequiredReq).Obj(), - newPod: st.MakePod().Node("fake-node").Label("service", "aaaa").Obj(), - oldPod: st.MakePod().Node("fake-node").Label("service", "securityscan").Obj(), + pod: st.MakePod().UID("p").Name("p").PodAntiAffinityIn("service", "region", []string{"securityscan", "value2"}, st.PodAntiAffinityWithRequiredReq).Obj(), + newPod: st.MakePod().UID("other").Node("fake-node").Label("service", "aaaa").Obj(), + oldPod: st.MakePod().UID("other").Node("fake-node").Label("service", "securityscan").Obj(), expectedHint: fwk.Queue, }, { name: "modify pod label to change it from not satisfying pod anti-affinity to satisfying anti-affinity", - pod: st.MakePod().Name("p").PodAntiAffinityIn("service", "region", []string{"securityscan", "value2"}, st.PodAntiAffinityWithRequiredReq).Obj(), - newPod: st.MakePod().Node("fake-node").Label("service", "securityscan").Obj(), - oldPod: st.MakePod().Node("fake-node").Label("service", "bbb").Obj(), + pod: st.MakePod().UID("p").Name("p").PodAntiAffinityIn("service", "region", []string{"securityscan", "value2"}, st.PodAntiAffinityWithRequiredReq).Obj(), + newPod: st.MakePod().UID("other").Node("fake-node").Label("service", "securityscan").Obj(), + oldPod: st.MakePod().UID("other").Node("fake-node").Label("service", "bbb").Obj(), expectedHint: fwk.QueueSkip, }, { name: "delete a pod which doesn't match pod's anti-affinity", - pod: st.MakePod().Name("p").PodAntiAffinityIn("service", "region", []string{"securityscan", "value2"}, st.PodAntiAffinityWithRequiredReq).Obj(), - oldPod: st.MakePod().Node("fake-node").Label("aaa", "a").Obj(), + pod: st.MakePod().UID("p").Name("p").PodAntiAffinityIn("service", "region", []string{"securityscan", "value2"}, st.PodAntiAffinityWithRequiredReq).Obj(), + oldPod: st.MakePod().UID("other").Node("fake-node").Label("aaa", "a").Obj(), expectedHint: fwk.QueueSkip, }, { name: "delete a pod which matches pod's anti-affinity", - pod: st.MakePod().Name("p").PodAntiAffinityIn("service", "region", []string{"securityscan", "value2"}, st.PodAntiAffinityWithRequiredReq).Obj(), - oldPod: st.MakePod().Node("fake-node").Label("service", "securityscan").Obj(), + pod: st.MakePod().UID("p").Name("p").PodAntiAffinityIn("service", "region", []string{"securityscan", "value2"}, st.PodAntiAffinityWithRequiredReq).Obj(), + oldPod: st.MakePod().UID("other").Node("fake-node").Label("service", "securityscan").Obj(), expectedHint: fwk.Queue, }, }