How to Use Kubernetes Pod Anti-Affinity to Spread Replicas Across Nodes
Three replicas running on one node is still a single point of failure. Pod anti-affinity tells the Kubernetes scheduler to prefer placing replicas on separate nodes - turning replica count into real availability.
The problem with replicas on one node
A Deployment with replicas: 3 looks highly available, but the scheduler
has no default preference about which nodes those pods land on. On a
small cluster under load, all three replicas can end up on the same node -
and a single node failure takes the whole service down at once.
podAntiAffinity fixes this by expressing a scheduling preference: don't
place this pod on a node that already runs a pod matching the same label.
Soft vs hard anti-affinity
Kubernetes offers two forms:
preferredDuringSchedulingIgnoredDuringExecution(soft) - the scheduler tries to spread pods but will still schedule them on the same node if no other option exists. Use this when availability is important but you still need pods to start on a small or under-resourced cluster.requiredDuringSchedulingIgnoredDuringExecution(hard) - the scheduler refuses to place the pod if no eligible node exists. Pods goPendinguntil a suitable node appears. Use this only when co-location is truly unacceptable.
For most workloads the soft form is the right default.
Adding pod anti-affinity to a Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
spec:
replicas: 3
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: api
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app: api
topologyKey: kubernetes.io/hostname
containers:
- name: api
image: my-api:latest
Key fields:
labelSelector.matchLabels- matches the pods' own label (app: api). The rule says "don't land next to another pod that also hasapp: api."topologyKey: kubernetes.io/hostname- defines a node as the unit of separation. Each unique hostname is one topology domain, so the scheduler tries to put each replica on a different physical or virtual node.weight: 100- on the soft form, higher weight means the scheduler scores this preference more heavily when choosing between candidates.
Verify placement after applying
kubectl apply -f deployment.yaml
kubectl get pods -o wide
The NODE column shows which node each pod landed on. On a multi-node
cluster, the three replicas should appear on different nodes. On a
single-node cluster (or a cluster with fewer nodes than replicas), the
soft form still schedules all pods - they just share a node.
When to use topology spread constraints instead
For more precise control over distribution - such as spreading evenly
across availability zones or limiting how many pods can share a node -
use topologySpreadConstraints. Anti-affinity is a preference rule;
topology spread constraints let you set a maxSkew (the max imbalance
allowed) and mix DoNotSchedule or ScheduleAnyway policies.
Want to try it hands-on? HeyDevJob gives you this exact setup in a live cloud workspace in your browser - edit it, run it, and see it work. Free, nothing to install.
Try it in a workspace →What you'll practice
- Adding a preferredDuringSchedulingIgnoredDuringExecution podAntiAffinity rule to a Deployment
- Choosing the right topologyKey (hostname vs zone) for the spreading requirement
- Verifying replica placement across nodes with kubectl get pods -o wide
FAQ
What does pod anti-affinity do in Kubernetes?
It tells the scheduler to avoid placing a pod on a node that already runs pods matching a given label selector. Used with topologyKey: kubernetes.io/hostname it spreads replicas across nodes so a node failure doesn't take all replicas down at once.
What's the difference between required and preferred pod anti-affinity?
Required (requiredDuringSchedulingIgnoredDuringExecution) blocks scheduling on an ineligible node - pods go Pending if no suitable node exists. Preferred (preferredDuringSchedulingIgnoredDuringExecution) is a soft hint - the scheduler tries to spread but still schedules on the same node if there's no alternative.
What topologyKey should I use for pod anti-affinity?
Use kubernetes.io/hostname to spread across nodes, or topology.kubernetes.io/zone to spread across availability zones. The topologyKey names the node label that defines one topology domain.
What is the difference between node affinity and pod anti-affinity?
Node affinity attracts pods to nodes with certain labels (where to run). Pod anti-affinity repels pods from each other based on the labels of pods already on a node (do not co-locate) - used to spread replicas across nodes for high availability.
Keep learning
Learn it by doing. Open this in a live cloud workspace, make the change yourself, and keep a record of the work you can share.
Open the workspace →