When you're running a Kubernetes cluster, it's critical to ensure your Pods are evenly distributed across different parts of your infrastructure, especially for high availability and fault tolerance. You don’t want all your Pods landing on a single node or in one availability zone. If that resource fails, your application could go down. This is where Pod Topology Spread Constraints come into play.
In this guide, we'll walk through what Pod Topology Spread Constraints are, how they work, and we'll explore a real-world example with a maxSkew of 2.
What Are Pod Topology Spread Constraints?
Pod Topology Spread Constraints allow you to control how Pods are distributed across various topology domains within your cluster. A topology domain could be anything from nodes to zones or regions, depending on your cluster setup. These constraints help ensure that Pods are not overly concentrated in a single domain, which would expose you to higher risk in case of a failure.
Essentially, it’s a way of telling Kubernetes: "Don't put all my Pods in one place. Spread them out!" By doing so, you improve the resiliency of your application.
Key Parameters Explained
topologyKey: This parameter defines what domain you want your Pods to be spread across. It could be zones (topology.kubernetes.io/zone), nodes, or even custom labels, depending on your infrastructure needs.
maxSkew: This parameter controls the allowed imbalance between topology domains. For instance, if you set maxSkew: 2, the difference in the number of Pods between any two domains should not be more than 2. It gives you some flexibility in distribution while still ensuring a reasonable balance.
whenUnsatisfiable: Defines what Kubernetes should do when it can’t satisfy the Pod distribution rules. There are two options:
labelSelector: Specifies which Pods the constraint applies to. Usually, you'll want this to match specific labels like app: my-app so that only a subset of Pods is affected.
Practical Example:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app-deployment
spec:
replicas: 12
selector:
matchLabels:
app: web-app
template:
metadata:
labels:
app: web-app
spec:
containers:
- name: web-app
image: nginx:1.21.1
topologySpreadConstraints:
- maxSkew: 2
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: web-app
What’s Going On Here?
maxSkew: 2: This ensures that the difference in the number of Pods between any two zones will be at most 2. For example, if there are 5 Pods in zone-a, the other zones can have anywhere from 3 to 5 Pods.
topology.kubernetes.io/zone: This tells Kubernetes to distribute the Pods across different availability zones (e.g., zone-a, zone-b, zone-c).
whenUnsatisfiable: DoNotSchedule: If Kubernetes can’t maintain the desired balance, it will stop scheduling Pods in the zones that would exceed the skew constraint. This prevents overloading any one zone at the expense of others.
How Kubernetes Distributes Pods
Let’s assume your cluster has three zones with enough capacity to run your Pods. Given 12 replicas and a maxSkew of 2, Kubernetes will attempt to distribute the Pods evenly. An ideal distribution would look something like:
zone-a: 4 Pods
zone-b: 4 Pods
zone-c: 4 Pods
and it also could be something like this :
zone-a: 6 Pods
zone-b: 4 Pods
zone-c: 2 Pods
This is a perfectly balanced scenario. But, with maxSkew: 2, Kubernetes has some leeway if things aren't perfect. For example:
zone-a: 5 Pods
zone-b: 4 Pods
zone-c: 3 Pods
Here, the difference between any two zones doesn’t exceed 2 Pods, so the constraint is still respected.
Handling Failures or Imbalances
Let’s say zone-a has no available capacity. In this case, Kubernetes will still try to adhere to the maxSkew: 2 constraint. If you have 12 Pods to distribute and zone-a is unavailable, Kubernetes might distribute them like this:
zone-a: 0 Pods
zone-b: 6 Pods
zone-c: 6 Pods
This scenario breaks the maxSkew: 2 rule because the difference between zone-a (0 Pods) and zone-b/zone-c (6 Pods) is 6, which exceeds the allowed imbalance. Since we set whenUnsatisfiable: DoNotSchedule, Kubernetes will refuse to schedule new Pods in zone-b or zone-c until capacity becomes available in zone-a. This way, the constraint is respected, and your application maintains resilience by avoiding overloading a single zone.
Why Use Pod Topology Spread Constraints?
Here are a few reasons you should consider using Pod Topology Spread Constraints:
Improved Availability: By spreading Pods across zones or nodes, you reduce the risk of downtime if one part of your infrastructure fails.
Fault Tolerance: Even in the event of a failure in one zone or node, your application can continue running in other zones.
Custom Control with maxSkew: You can fine-tune the balance between flexibility and strictness. A smaller maxSkew ensures tighter distribution control, while a larger value gives Kubernetes more room to optimize placement.
Conclusion
Pod Topology Spread Constraints are a powerful way to control how your Pods are distributed in a Kubernetes cluster. By spreading your Pods across zones or nodes and setting a reasonable maxSkew, you can ensure higher availability and fault tolerance.
In our example, a maxSkew of 2 allowed for a slight imbalance while still ensuring that no zone had an overloaded number of Pods. This approach ensures that your application stays resilient, even in less-than-perfect infrastructure conditions.
Improve Your Kubernetes Knowledge with my CKA Git repo :
Don't Forget to Give me a Star :)
https://github.com/farshadnick/Mastering-Kubernetes/
About Author :
Hi 👋, I’m Farshad Nick (Farshad nickfetrat)
📝 I regularly write articles on packops.dev and packops.ir
💬 Ask me about Devops , Cloud , Kubernetes , Linux
📫 How to reach me on my linkedin
Here is my Github repo