CKA — Taints & Tolerations

4 minute read

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: NoSchedule only affects new Pods. NoExecute also 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:

  1. Taint the dedicated node → keeps unwanted Pods away.
  2. nodeSelector on the Pod → ensures it targets the correct node.
  3. 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.

Updated: