Estimated reading time: 4 minutes
In this post, I’ll explain key concepts of Kubernetes Pod Scheduling, such as taints, tolerations, and node affinity, and how Kubernetes decides where to place your pods.
Table of contents
What is Kubernetes Pod Scheduling?
Kubernetes pod scheduling is the process of assigning pods to nodes in a Kubernetes cluster. The scheduler places your pods on the most appropriate nodes based on resource requirements, constraints, and policies. Effective pod scheduling helps maximize resource utilization and maintain application performance.
Understanding Taints and Tolerations
Taints and tolerations control pod placement in Kubernetes. They allow you to set restrictions on nodes and define which pods can run on them.
Taints
You apply Taints to nodes to mark them as unsuitable for certain pods. For example, you can taint a node to reserve it for high-priority workloads or to keep out less critical pods. You do this using a key-value pair along with an effect, which can be NoSchedule, PreferNoSchedule, or NoExecute.
To add a taint to a node, use the following command:
kubectl taint nodes <node-name> key=value:NoSchedule
For example, to taint a node with the key special
and value true
with the effect NoSchedule
, you would use:
kubectl taint nodes node1 special=true:NoSchedule
Tolerations
Tolerations are applied to pods, allowing them to be scheduled on nodes with matching taints. By adding a toleration
to a pod, you tell Kubernetes that the pod can tolerate the taint and should be considered for scheduling on that node.
To configure a pod to tolerate a taint, you add a tolerations
section to the pod’s YAML definition. Here’s an example:
apiVersion: v1
kind: Pod
metadata:
name: my-tolerating-pod
spec:
tolerations:
- key: "special"
operator: "Equal"
value: "true"
effect: "NoSchedule"
containers:
- name: my-container
image: my-image
This pod will tolerate nodes with the taint special=true:NoSchedule
.
I once had to ensure that our database pods were only placed on high-performance nodes. I could easily achieve this by using taints and tolerations.
Node Affinity and Anti-Affinity
Node affinity allows you to control pod placement based on node labels. It is similar to taints and tolerations but works in a more positive way by specifying preferences rather than restrictions.
Node Affinity
Node Affinity allows you to define rules determining which nodes should or should not host your pods based on the labels assigned to the nodes. There are two types of node affinity rules:
RequiredDuringSchedulingIgnoredDuringExecution: The pod scheduler will schedule the pod on a node with the specified labels. Here’s an example:
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values:
- ssd
containers:
- name: my-container
image: my-image
This pod will only be scheduled on nodes that have the label disktype=ssd
.
PreferredDuringSchedulingIgnoredDuringExecution: Kubernetes attempts to place the pod on a node that matches the specified labels but will still schedule it on a non-matching node if necessary.Example:
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: zone
operator: In
values:
- us-central1-a
containers:
- name: my-container
image: my-image
This pod prefers to be scheduled on nodes with the label zone=us-central1-a
, but it can be scheduled on other nodes if necessary.
Anti-Affinity
You can use Anti-Affinity to specify that certain pods must not be placed on some nodes. Spreading pods across multiple nodes ensures high availability and reduces the risk of failure.
To use pod anti-affinity, you add a podAffinity
section to the pod’s YAML definition. Here’s an example:
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- frontend
topologyKey: "kubernetes.io/hostname"
containers:
- name: my-container
image: my-image
This pod will not be scheduled on the same node as other pods with the label app=frontend
.
I used node affinity to ensure that Kubernetes always placed my web server pods on nodes with SSD storage for faster performance. By setting the appropriate labels and affinity rules, Kubernetes handles the placement automatically.
Examples from SocketDaddy.com
At SocketDaddy.com, we’ve leveraged Kubernetes pod scheduling to optimize our infrastructure. For example, we used taints to reserve certain nodes exclusively for our most resource-intensive analytics jobs. This ensured that we always provided the resources our analytics pods needed without impacting other workloads.
Additionally, we implemented Node Affinity to place our front-end and back-end services on different nodes. This separation helped us achieve better performance and stability because frontend crashes didn’t affect the backend services and vice versa.
Conclusion
In this post, we demonstrated how to configure taints, tolerations, node affinity, and anti-affinity in Kubernetes. Implement these Kubernetes Pod Scheduling Techniques to achieve greater control over where your workloads run.