CKA — Taints & Tolerations
CKA Exam Domain
| Domain | Weight |
|---|---|
| Workloads & Scheduling | 15% |
Taints and tolerations are heavily tested on the CKA. You’ll need to add/remove taints and write tolerations under time pressure.
What Are Taints?
A taint is applied to a node and tells the scheduler: “Don’t place Pods here unless they explicitly tolerate this taint.”
Think of it as a “keep out” sign on a node. Only Pods with a matching toleration can be scheduled there.
A taint has three parts:
| Part | Example |
|---|---|
| Key | env |
| Value | prod |
| Effect | NoSchedule |
Written as: env=prod:NoSchedule
Taint Effects
| Effect | Description |
|---|---|
NoSchedule |
New Pods without a matching toleration will not be scheduled on this node. Existing Pods are unaffected. |
PreferNoSchedule |
Scheduler tries to avoid this node, but will use it if no other option exists. Soft version of NoSchedule. |
NoExecute |
New Pods without a toleration are not scheduled, and existing Pods without a toleration are evicted. |
Key Difference:
NoScheduleonly affects new Pods.NoExecutealso evicts running Pods.
Adding and Removing Taints
Add a taint:
kubectl taint nodes worker-1 env=prod:NoSchedule
Verify the taint:
kubectl describe node worker-1 | grep Taints
Expected output:
Taints: env=prod:NoSchedule
Remove a taint (trailing minus):
kubectl taint nodes worker-1 env=prod:NoSchedule-
Add multiple taints:
kubectl taint nodes worker-1 env=prod:NoSchedule gpu=true:NoExecute
Exam Tip: The trailing
-to remove a taint is identical to the syntax for removing a label. Muscle memory!
Tolerations in Pod Spec
A toleration is added to a Pod and says: “I can handle this taint.”
Using the Equal Operator
Matches a taint with a specific key, value, and effect:
apiVersion: v1
kind: Pod
metadata:
name: prod-pod
spec:
containers:
- name: nginx
image: nginx:1.27
tolerations:
- key: "env"
operator: "Equal"
value: "prod"
effect: "NoSchedule"
Using the Exists Operator
Matches a taint by key only — value is ignored:
tolerations:
- key: "env"
operator: "Exists"
effect: "NoSchedule"
This tolerates any taint with the key env and effect NoSchedule, regardless of value.
Tolerate All Taints
An empty toleration matches everything:
tolerations:
- operator: "Exists"
This Pod can be scheduled on any node, no matter what taints it has. Use with caution.
NoExecute with tolerationSeconds
When a NoExecute taint is added to a node, you can control how long a Pod stays before being evicted:
tolerations:
- key: "env"
operator: "Equal"
value: "prod"
effect: "NoExecute"
tolerationSeconds: 300
The Pod will be evicted after 300 seconds (5 minutes) if the taint is applied.
Control Plane Taints
By default, Kubernetes taints the control plane node so that user workloads don’t run there:
node-role.kubernetes.io/control-plane:NoSchedule
View the taint:
kubectl describe node <control-plane-node> | grep Taints
Schedule a Pod on the control plane by adding a toleration:
tolerations:
- key: "node-role.kubernetes.io/control-plane"
operator: "Exists"
effect: "NoSchedule"
Remove the control plane taint (not recommended in production):
kubectl taint nodes <control-plane-node> node-role.kubernetes.io/control-plane:NoSchedule-
Taints + nodeSelector Together
Taints and nodeSelector serve complementary purposes:
| Mechanism | What It Does |
|---|---|
| Taint | Repels Pods from a node (node says “keep out”) |
| nodeSelector | Attracts a Pod to specific nodes (Pod says “put me here”) |
Using both together gives you fine-grained control:
- Taint the dedicated node → keeps unwanted Pods away.
- nodeSelector on the Pod → ensures it targets the correct node.
- Toleration on the Pod → allows it to land despite the taint.
apiVersion: v1
kind: Pod
metadata:
name: dedicated-pod
spec:
containers:
- name: nginx
image: nginx:1.27
nodeSelector:
dedicated: ml-workload
tolerations:
- key: "dedicated"
operator: "Equal"
value: "ml-workload"
effect: "NoSchedule"
Remember: A toleration allows a Pod onto a tainted node, but it doesn’t guarantee it. Use nodeSelector or affinity to ensure placement.
Common CKA Scenarios
Dedicated Node Pools
Reserve nodes for specific workloads:
# Taint the node
kubectl taint nodes gpu-node-1 workload=gpu:NoSchedule
# Label the node
kubectl label nodes gpu-node-1 workload=gpu
Then in the Pod spec:
nodeSelector:
workload: gpu
tolerations:
- key: "workload"
operator: "Equal"
value: "gpu"
effect: "NoSchedule"
GPU Nodes
Cloud providers often auto-taint GPU nodes with nvidia.com/gpu:NoSchedule. Your GPU workloads need a matching toleration.
Drain and Cordon
When you kubectl drain a node, Kubernetes applies a NoExecute taint, evicting all Pods that don’t tolerate it.
kubectl drain worker-1 --ignore-daemonsets --delete-emptydir-data
kubectl Commands
# Add a taint
kubectl taint nodes <node-name> <key>=<value>:<effect>
# Remove a taint
kubectl taint nodes <node-name> <key>=<value>:<effect>-
# View taints on a node
kubectl describe node <node-name> | grep Taints
# View tolerations on a Pod
kubectl describe pod <pod-name> | grep -A 5 Tolerations
# Drain a node (applies NoExecute taint)
kubectl drain <node-name> --ignore-daemonsets
# Uncordon a node
kubectl uncordon <node-name>
Practice Questions
Q1. Taint node worker-2 with env=staging:NoSchedule. Then create a Pod that tolerates this taint.
Show Answer
kubectl taint nodes worker-2 env=staging:NoSchedule
apiVersion: v1
kind: Pod
metadata:
name: staging-pod
spec:
containers:
- name: nginx
image: nginx:1.27
tolerations:
- key: "env"
operator: "Equal"
value: "staging"
effect: "NoSchedule"
Q2. What is the difference between NoSchedule and NoExecute?
Show Answer
- NoSchedule — Prevents new Pods without a toleration from being scheduled. Existing running Pods are not evicted.
- NoExecute — Prevents new Pods and evicts existing Pods that don’t have a matching toleration.
Q3. Remove the taint env=staging:NoSchedule from node worker-2.
Show Answer
kubectl taint nodes worker-2 env=staging:NoSchedule-
Q4. A Pod needs to run on the control plane node. What toleration do you add?
Show Answer
tolerations:
- key: "node-role.kubernetes.io/control-plane"
operator: "Exists"
effect: "NoSchedule"
Q5. You want a Pod to tolerate all taints on a node. How do you configure the toleration?
Show Answer
Use an empty toleration with the Exists operator:
tolerations:
- operator: "Exists"
This matches all taints regardless of key, value, or effect.