Affinity — Telling the Scheduler Where Your Pods Belong
The Full Picture: Taints vs Affinity
These two mechanisms are often confused because they both influence scheduling. Here is the distinction:
| Taints (on Nodes) | Affinity (on Pods) |
|---|---|
| Node says: "Stay away unless you tolerate me" | Pod says: "I want to be near X" or "I must be on Y" |
| Push-based repulsion | Pull-based attraction |
They work together. Taints keep unwanted pods off nodes. Affinity rules pull the right pods to the right nodes.
Node Affinity — Pod Wants a Specific Node Type
Use case: Zerodha's market-data processing pods need GPU nodes. Regular pods should not land there.
1spec:2 affinity:3 nodeAffinity:4 requiredDuringSchedulingIgnoredDuringExecution: # HARD rule — must match5 nodeSelectorTerms:6 - matchExpressions:7 - key: node.kubernetes.io/instance-type8 operator: In9 values:10 - p3.2xlarge # GPU instance type11 - p3.8xlarge12 preferredDuringSchedulingIgnoredDuringExecution: # SOFT rule — try to match13 - weight: 80 # 0-100, higher = stronger preference14 preference:15 matchExpressions:16 - key: topology.kubernetes.io/zone17 operator: In18 values:19 - ap-south-1a # Prefer Mumbai AZ-AThe two scheduling modes:
| Mode | Behavior |
|---|---|
requiredDuringSchedulingIgnoredDuringExecution |
Pod will NOT schedule if no matching node found (hard requirement) |
preferredDuringSchedulingIgnoredDuringExecution |
Pod tries to schedule on matching node, but falls back if none available |
📌 Remember: The IgnoredDuringExecution part means if a node's labels change after a pod is already running, the pod is NOT evicted. The rule only applies at scheduling time.Pod Anti-Affinity — Spread Pods Across Nodes/Zones
Use case: Swiggy's order-service runs 6 replicas. If all 6 land on one node and that node dies, the entire service goes down. Anti-affinity forces the scheduler to spread them out.
1spec:2 affinity:3 podAntiAffinity:4 requiredDuringSchedulingIgnoredDuringExecution:5 - labelSelector:6 matchLabels:7 app: order-service # Don't place me near other order-service pods8 topologyKey: kubernetes.io/hostname # "near" means "on the same node"This guarantees no two order-service pods share a node. For zone-level HA, change topologyKey to topology.kubernetes.io/zone.
Pod Affinity — Keep Pods Together
Use case: A data-processing pod and its Redis sidecar should always land on the same node to minimize latency.
1spec:2 affinity:3 podAffinity:4 preferredDuringSchedulingIgnoredDuringExecution:5 - weight: 1006 podAffinityTerm:7 labelSelector:8 matchLabels:9 app: redis-cache10 topologyKey: kubernetes.io/hostname # "with" means "on the same node"Quick Decision Tree
+------------------------------------------------------+| Do you need to control where a pod lands? |+------------------------------------------------------+ | | v v+---------------------+ +------------------------+| Based on node | | Based on other pods? || hardware/labels? | +------------------------+| -> Node Affinity | | |+---------------------+ v v | +------------+ +------------+ v | Stay AWAY | | Stay NEAR | +-------+-------+ | from pods | | a pod | | | | -> Anti- | | -> Pod | v v | Affinity | | Affinity |+--------+ +---------+ +------------+ +------------+| Hard | | Soft | | Spread replicas across || must | | prefer | | nodes/zones for HA || land | | to land | +----------------------------+| required preferred |+--------+ +---------+🔴 Common Mistake: Usingrequiredanti-affinity with more replicas than nodes. If you have 3 nodes and 4 replicas withrequiredanti-affinity, the 4th pod will be stuck inPendingforever — there is no node without an existing pod to satisfy the constraint. Usepreferredunless you are certain about your node count.