diff --git a/plugin/pkg/scheduler/algorithm/predicates/predicates.go b/plugin/pkg/scheduler/algorithm/predicates/predicates.go index 06f5605f505..61438fe262e 100644 --- a/plugin/pkg/scheduler/algorithm/predicates/predicates.go +++ b/plugin/pkg/scheduler/algorithm/predicates/predicates.go @@ -925,7 +925,7 @@ func (checker *PodAffinityChecker) NodeMatchesHardPodAffinity(pod *api.Pod, allP // break any existing pods' anti-affinity rules, then return true. func (checker *PodAffinityChecker) NodeMatchesHardPodAntiAffinity(pod *api.Pod, allPods []*api.Pod, node *api.Node, podAntiAffinity *api.PodAntiAffinity) bool { var podAntiAffinityTerms []api.PodAffinityTerm - if len(podAntiAffinity.RequiredDuringSchedulingIgnoredDuringExecution) != 0 { + if podAntiAffinity != nil && len(podAntiAffinity.RequiredDuringSchedulingIgnoredDuringExecution) != 0 { podAntiAffinityTerms = podAntiAffinity.RequiredDuringSchedulingIgnoredDuringExecution } // TODO: Uncomment this block when implement RequiredDuringSchedulingRequiredDuringExecution. @@ -999,19 +999,15 @@ func (checker *PodAffinityChecker) NodeMatchPodAffinityAntiAffinity(pod *api.Pod } // check if the current node match the inter-pod affinity scheduling rules. + // hard inter-pod affinity is not symmetric, check only when affinity.PodAffinity is not nil. if affinity.PodAffinity != nil { if !checker.NodeMatchesHardPodAffinity(pod, allPods, node, affinity.PodAffinity) { return false } } - // check if the current node match the inter-pod anti-affinity scheduling rules. - if affinity.PodAntiAffinity != nil { - if !checker.NodeMatchesHardPodAntiAffinity(pod, allPods, node, affinity.PodAntiAffinity) { - return false - } - } - return true + // hard inter-pod anti-affinity is symmetric, check both when affinity.PodAntiAffinity is nil and not nil. + return checker.NodeMatchesHardPodAntiAffinity(pod, allPods, node, affinity.PodAntiAffinity) } func PodToleratesNodeTaints(pod *api.Pod, meta interface{}, nodeInfo *schedulercache.NodeInfo) (bool, error) { diff --git a/plugin/pkg/scheduler/algorithm/predicates/predicates_test.go b/plugin/pkg/scheduler/algorithm/predicates/predicates_test.go index eb472e7f51e..9c0e1da0c26 100755 --- a/plugin/pkg/scheduler/algorithm/predicates/predicates_test.go +++ b/plugin/pkg/scheduler/algorithm/predicates/predicates_test.go @@ -2254,6 +2254,62 @@ func TestInterPodAffinity(t *testing.T) { fits: false, test: "pod matches its own Label in PodAffinity and that matches the existing pod Labels", }, + { + pod: &api.Pod{ + ObjectMeta: api.ObjectMeta{ + Labels: podLabel, + }, + }, + pods: []*api.Pod{{Spec: api.PodSpec{NodeName: "machine1"}, + ObjectMeta: api.ObjectMeta{Labels: podLabel, + Annotations: map[string]string{ + api.AffinityAnnotationKey: ` + {"PodAntiAffinity": { + "requiredDuringSchedulingIgnoredDuringExecution": [{ + "labelSelector": { + "matchExpressions": [{ + "key": "service", + "operator": "In", + "values": ["securityscan", "value2"] + }] + }, + "topologyKey": "zone" + }] + }}`, + }}, + }}, + node: &node1, + fits: false, + test: "verify that PodAntiAffinity from existing pod is respected when pod has no AntiAffinity constraints. doesn't satisfy PodAntiAffinity symmetry with the existing pod", + }, + { + pod: &api.Pod{ + ObjectMeta: api.ObjectMeta{ + Labels: podLabel, + }, + }, + pods: []*api.Pod{{Spec: api.PodSpec{NodeName: "machine1"}, + ObjectMeta: api.ObjectMeta{Labels: podLabel, + Annotations: map[string]string{ + api.AffinityAnnotationKey: ` + {"PodAntiAffinity": { + "requiredDuringSchedulingIgnoredDuringExecution": [{ + "labelSelector": { + "matchExpressions": [{ + "key": "service", + "operator": "NotIn", + "values": ["securityscan", "value2"] + }] + }, + "topologyKey": "zone" + }] + }}`, + }}, + }}, + node: &node1, + fits: true, + test: "verify that PodAntiAffinity from existing pod is respected when pod has no AntiAffinity constraints. satisfy PodAntiAffinity symmetry with the existing pod", + }, } for _, test := range tests { node := test.node