// Module included in the following assemblies:
//
// * nodes/nodes-scheduler-pod-affinity.adoc

:_mod-docs-content-type: CONCEPT
[id="nodes-scheduler-pod-affinity-about_{context}"]
= Understanding pod affinity

[role="_abstract"]
You can use _pod affinity_ and _pod anti-affinity_ to constrain which nodes your pod is eligible to be scheduled on based on the key/value labels on other pods.

* Pod affinity can tell the scheduler to locate a new pod on the same node as other pods if the label selector on the new pod matches the label on the current pod.
* Pod anti-affinity can prevent the scheduler from locating a new pod on the same node as pods with the same labels if the label selector on the new pod matches the label on the current pod.

For example, using affinity rules, you could spread or pack pods within a service or relative to pods in other services. Anti-affinity rules allow you to prevent pods of a particular service  from scheduling  on the same nodes as pods of another service that are known to interfere with the performance of the pods of the first service. Or, you could spread the pods of a service across nodes, availability zones, or availability sets to reduce correlated failures.

[NOTE]
====
A label selector might match pods with multiple pod deployments. Use unique combinations of labels when configuring anti-affinity rules to avoid matching pods.
====

There are two types of pod affinity rules: _required_ and _preferred_.

Required rules *must* be met before a pod can be scheduled on a node. Preferred rules specify that, if the rule is met, the scheduler tries to enforce the rules, but does not guarantee enforcement.

[NOTE]
====
Depending on your pod priority and preemption settings, the scheduler might not be able to find an appropriate node for a pod without violating affinity
requirements. If so, a pod might not be scheduled.

To prevent this situation, carefully configure pod affinity with equal-priority pods.
====

You configure pod affinity/anti-affinity through the `Pod` spec files. You can specify a required rule, a preferred rule, or both. If you specify both, the node must first meet the required rule, then attempts to meet the preferred rule.

The following example shows a `Pod` spec configured for pod affinity and anti-affinity.

In this example, the pod affinity rule indicates that the pod can schedule onto a node only if that node has at least one already-running pod with a label that has the key `security` and value `S1`. The pod anti-affinity rule says that the pod prefers to not schedule onto a node if that node is already running a pod with label having key `security` and value `S2`.

.Sample `Pod` config file with pod affinity
[source,yaml]
----
apiVersion: v1
kind: Pod
metadata:
  name: with-pod-affinity
spec:
  securityContext:
    runAsNonRoot: true
    seccompProfile:
      type: RuntimeDefault
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: security
            operator: In
            values:
            - S1
        topologyKey: topology.kubernetes.io/zone
  containers:
  - name: with-pod-affinity
    image: docker.io/ocpqe/hello-pod
    securityContext:
      allowPrivilegeEscalation: false
      capabilities:
        drop: [ALL]
----
where:

`spec.affinity.podAffinity`:: Specifies a stanza to configure pod affinity.
`spec.affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution`:: Specifies the parameters for a _required_ rule. Configure the following `labelSelector.matchExpressions.key` parameters:
+
--
`key`:: Specifies the key of the key/value pair (label) that must be matched to apply the rule.
`values`:: Specifies the value of the key/value pair (label) that must be matched to apply the rule.
`operator`:: Specifies the relationship between the label on the existing pod and the set of values in the `matchExpression` parameters in the specification for the new pod. Can be `In`, `NotIn`, `Exists`, or `DoesNotExist`.
--

.Sample `Pod` config file with pod anti-affinity
[source,yaml]
----
apiVersion: v1
kind: Pod
metadata:
  name: with-pod-antiaffinity
spec:
  securityContext:
    runAsNonRoot: true
    seccompProfile:
      type: RuntimeDefault
  affinity:
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: security
              operator: In
              values:
              - S2
          topologyKey: kubernetes.io/hostname
  containers:
  - name: with-pod-affinity
    image: docker.io/ocpqe/hello-pod
    securityContext:
      allowPrivilegeEscalation: false
      capabilities:
        drop: [ALL]
----
where:

`spec.affinity.podAffinity`:: Specifies a stanza to configure pod affinity.
`spec.affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution`:: Specifies the parameters for a _preferred_ rule. Configure a weight and the following `podAffinityTerm.labelSelector.matchExpressions` parameters:
+
--
`weight`:: Specifies the weight for a preferred rule. The node with the highest weight is preferred.
`key`:: Specifies the key of the key/value pair (label) that must be matched to apply the rule.
`values`:: Specifies the value of the key/value pair (label) that must be matched to apply the rule.
`operator`:: Specifies the relationship between the label on the existing pod and the set of values in the `matchExpression` parameters in the specification for the new pod. Can be `In`, `NotIn`, `Exists`, or `DoesNotExist`.
--

[NOTE]
====
If labels on a node change at runtime such that the affinity rules on a pod are no longer met, the pod continues to run on the node.
====
