Pod Affinity and Anti-Affinity Guide
Configure pod affinity and anti-affinity rules for Kubernetes scheduling. Co-locate cache with app, spread replicas across nodes.
💡 Quick Answer: Use
podAffinityto co-locate pods (cache near app server) andpodAntiAffinityto spread replicas across nodes. PreferpreferredDuringSchedulingIgnoredDuringExecutionfor soft rules that don’t block scheduling.
The Problem
Your cache pods are on different nodes than the app servers that use them — adding 1-2ms network latency per request. Or all 3 replicas of a service landed on the same node — one node failure takes out the entire service.
The Solution
Co-Locate Cache with App
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-server
spec:
template:
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values: ["redis-cache"]
topologyKey: kubernetes.io/hostnameWeb server pods MUST schedule on nodes that already have redis-cache pods.
Spread Replicas Across Nodes
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-server
spec:
replicas: 3
template:
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app: api-server
topologyKey: kubernetes.io/hostnamePrefer different nodes for each replica. Soft rule — if only 2 nodes exist, 2 pods can share a node.
Hard Anti-Affinity (Strict Separation)
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: api-server
topologyKey: kubernetes.io/hostname⚠️ Hard anti-affinity with 3 replicas requires at least 3 nodes. Pods stay Pending if not enough nodes.
graph TD
subgraph Node 1
APP1[App Pod] --- CACHE1[Redis Cache]
end
subgraph Node 2
APP2[App Pod] --- CACHE2[Redis Cache]
end
subgraph Node 3
APP3[App Pod] --- CACHE3[Redis Cache]
end
AFFINITY[podAffinity:<br/>app near cache] --> APP1
ANTI[podAntiAffinity:<br/>replicas on different nodes] --> APP1 & APP2 & APP3Node Affinity (Placement by Node Properties, Not Other Pods)
Pod affinity/anti-affinity places pods relative to other pods; node affinity places them relative to node labels — use it for hardware requirements like GPU type:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- {key: gpu-type, operator: In, values: [nvidia-a100, nvidia-v100]}
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 80
preference:
matchExpressions: [{key: gpu-type, operator: In, values: [nvidia-a100]}]Cross-Namespace Affinity
By default, podAffinity/podAntiAffinity only match pods in the same namespace as the pod being scheduled. Use namespaceSelector to match across namespaces (e.g., a monitoring agent that should co-locate with any production workload, regardless of which namespace it’s in):
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector: {matchLabels: {tier: backend}}
topologyKey: kubernetes.io/hostname
namespaceSelector: {matchLabels: {environment: production}}Reference: Topology Keys
kubernetes.io/hostname — per node
topology.kubernetes.io/zone — per availability zone
topology.kubernetes.io/region — per region
node.kubernetes.io/instance-type — per instance typeCommon Issues
Pods stuck Pending with hard anti-affinity
Not enough nodes to satisfy the rule. Switch to preferredDuringScheduling (soft) or add more nodes.
Affinity not working — pods on wrong nodes
Check label selectors match exactly. kubectl get pods --show-labels to verify pod labels match the affinity matchLabels.
Best Practices
- Soft anti-affinity for most services — prevents single-node concentration without blocking scheduling
- Hard affinity only for true co-location requirements — cache + app on same node
topologyKey: kubernetes.io/hostnamefor node-level separationtopologyKey: topology.kubernetes.io/zonefor zone-level separation- Prefer topology spread constraints for even distribution — more flexible than anti-affinity
Key Takeaways
- podAffinity co-locates pods (same node/zone); podAntiAffinity separates them
- Soft rules (
preferred) are scheduling preferences; hard rules (required) are mandatory - Hard anti-affinity requires enough topology domains — can cause Pending pods
- Use
topologyKeyto control scope: hostname (node), zone, rack - Topology spread constraints are often better than anti-affinity for even distribution

Recommended
Kubernetes Recipes — The Complete Book100+ production-ready patterns with detailed explanations, best practices, and copy-paste YAML. Everything in one place.
Get the Book →Learn by Doing
CopyPasteLearn — Hands-on Cloud & DevOps CoursesMaster Kubernetes, Ansible, Terraform, and MLOps with interactive, copy-paste-run lessons. Start free.
Browse Courses →🎓 Deepen Your Skills — Hands-on Courses
Courses by CopyPasteLearn.com — Learn IT by Doing
