Back to Blog

Kubernetes Workloads & Scheduling for the CKA Exam: Deployments, DaemonSets, Taints, Tolerations & Affinity

A practitioner's deep dive into the CKA Workloads & Scheduling domain. Master Deployments, ReplicaSets, DaemonSets, static pods, manual scheduling, node selectors, node/pod affinity, and taints & tolerations — with kubectl commands, YAML, and exam-day speed tips.

By Sailor Team , June 16, 2026

The CKA exam doesn’t test whether you can recite the Kubernetes scheduler’s source code — it tests whether you can get the right pod onto the right node under time pressure, and recover when one won’t schedule. The Workloads & Scheduling domain is roughly 15% of the Certified Kubernetes Administrator exam, but its concepts bleed into Troubleshooting and Cluster Architecture too. A pod stuck in Pending is almost always a scheduling problem, and that exact scenario shows up again and again.

This guide is written from a practitioner’s perspective. We’ll walk through the workload controllers you must know cold — Deployments, ReplicaSets, DaemonSets, and static pods — then move into the scheduling machinery: manual scheduling, labels and selectors, node selectors, node and pod affinity, and the taints-and-tolerations model. Every section includes the kubectl you’d actually type and the exam-day shortcuts that save you minutes you don’t have.

If you want the full exam picture first, start with the CKA Exam Guide 2026 and the CKA domains breakdown, then come back here to go deep on workloads and scheduling.

How the Kubernetes Scheduler Actually Works

Before the YAML, get the mental model. When you create a pod, it lands with no nodeName set — it’s unscheduled. The kube-scheduler watches for these and runs a two-phase process for each one:

  1. Filtering (predicates): eliminate nodes that can’t run the pod. A node is filtered out if it lacks the requested CPU/memory, doesn’t match a required node selector or affinity rule, or carries a taint the pod doesn’t tolerate.
  2. Scoring (priorities): rank the remaining feasible nodes and pick the best one. Spreading, resource balance, and preferred affinity all feed the score.

The scheduler then binds the pod by writing nodeName into the pod spec. The kubelet on that node sees the assignment and starts the containers.

This is why a Pending pod is a scheduling story: no node passed the filter phase. The fastest diagnostic on the exam:

kubectl describe pod <pod> | grep -A10 Events
# Look for: "0/3 nodes are available: 3 Insufficient cpu" or
#           "node(s) had untolerated taint" or "didn't match node selector"

That one line tells you whether you’re fighting resources, taints, or affinity.

Deployments and ReplicaSets

A ReplicaSet keeps N identical pods running. A Deployment manages ReplicaSets and gives you declarative rollouts and rollbacks. On the exam you almost never create a bare ReplicaSet — you create Deployments and let them own the ReplicaSets.

Generate one imperatively (always faster than writing YAML from scratch):

kubectl create deployment web --image=nginx:1.25 --replicas=3

Scale and update without editing files:

kubectl scale deployment web --replicas=5
kubectl set image deployment/web nginx=nginx:1.26 --record

The rollout and rollback commands are pure exam gold:

kubectl rollout status deployment/web
kubectl rollout history deployment/web
kubectl rollout undo deployment/web              # back to previous revision
kubectl rollout undo deployment/web --to-revision=2

Two rollout strategies appear in questions:

StrategyBehaviorUse when
RollingUpdate (default)Gradually replace old pods, controlled by maxSurge / maxUnavailableZero-downtime updates
RecreateKill all old pods, then create new onesApp can’t run two versions at once

For a deeper treatment of rolling updates and revision control, the CKAD deployments & rolling updates guide covers the same controller from the developer angle.

DaemonSets

A DaemonSet runs exactly one copy of a pod on every node (or every node matching a selector). It’s the right answer whenever a scenario describes a per-node agent: log collectors, monitoring agents, CNI plugins, or storage daemons.

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-logger
spec:
  selector:
    matchLabels:
      app: node-logger
  template:
    metadata:
      labels:
        app: node-logger
    spec:
      tolerations:
        - key: node-role.kubernetes.io/control-plane
          operator: Exists
          effect: NoSchedule
      containers:
        - name: logger
          image: fluent/fluent-bit:2.2

Two exam-critical facts:

  • The DaemonSet controller, not the default scheduler, used to place these pods; modern Kubernetes uses the scheduler with node affinity, but the effect is the same — one pod per eligible node, and new nodes automatically get one.
  • To run on control-plane nodes, the DaemonSet must tolerate the control-plane taint (shown above). This is a classic “why isn’t my agent on the master?” question.

Static Pods

A static pod is managed directly by the kubelet on a node, not by the API server. The kubelet watches a directory — usually /etc/kubernetes/manifests — and runs any pod manifest it finds there. The control-plane components on a kubeadm cluster (kube-apiserver, etcd, controller-manager, scheduler) are themselves static pods.

This is heavily tested because it ties Workloads to Cluster Architecture. Key points:

  • Find the manifest path: grep staticPodPath /var/lib/kubelet/config.yaml (default /etc/kubernetes/manifests).
  • Create a static pod by dropping a manifest file into that directory — no kubectl apply needed.
  • The API server shows a read-only mirror pod named <pod>-<nodeName>. You can see it with kubectl get pods, but you can’t delete it via the API — you must remove the manifest file.
# On the node:
ls /etc/kubernetes/manifests/
# Generate a manifest to drop in:
kubectl run nginx --image=nginx --dry-run=client -o yaml > /etc/kubernetes/manifests/nginx.yaml

Labels, Selectors, and Manual Scheduling

Everything in scheduling is built on labels (key/value tags on objects) and selectors (queries over labels).

kubectl label node node01 disktype=ssd
kubectl get nodes -l disktype=ssd
kubectl get pods --show-labels

The bluntest scheduling tool is manual scheduling — setting nodeName directly in the pod spec. This bypasses the scheduler entirely and is the fallback when the scheduler is down (a real exam scenario):

apiVersion: v1
kind: Pod
metadata:
  name: pinned
spec:
  nodeName: node02       # scheduler is skipped; kubelet on node02 runs it
  containers:
    - name: nginx
      image: nginx

If nodeName points at a node that can’t fit the pod, it stays Pending forever — no rescheduling happens.

nodeSelector and Node Affinity

nodeSelector is the simplest declarative constraint: schedule only onto nodes carrying a matching label.

spec:
  nodeSelector:
    disktype: ssd

Node affinity is the richer, more expressive form. It supports two rule types you must distinguish on the exam:

Rule typeMeaning
requiredDuringSchedulingIgnoredDuringExecutionHard rule. Pod won’t schedule unless it’s satisfied.
preferredDuringSchedulingIgnoredDuringExecutionSoft rule. Scheduler tries, but will place the pod elsewhere if needed.

IgnoredDuringExecution means the rule is only checked at scheduling time — if a node’s labels change later, a running pod is not evicted.

spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
          - matchExpressions:
              - key: disktype
                operator: In
                values: ["ssd"]
      preferredDuringSchedulingIgnoredDuringExecution:
        - weight: 1
          preference:
            matchExpressions:
              - key: zone
                operator: In
                values: ["us-east-1a"]

Useful operators: In, NotIn, Exists, DoesNotExist, Gt, Lt. NotIn and DoesNotExist give you node anti-affinity behavior.

Pod Affinity and Anti-Affinity

Where node affinity attracts pods to nodes, pod affinity/anti-affinity places pods relative to other pods. The topologyKey defines the domain (“same node,” “same zone”) over which the rule applies.

  • Pod affinity: co-locate pods (e.g., a cache near its web app).
  • Pod anti-affinity: spread pods apart (e.g., never two replicas on the same node).
spec:
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        - labelSelector:
            matchLabels:
              app: web
          topologyKey: kubernetes.io/hostname   # one web pod per node

Taints and Tolerations: The Mirror Image of Affinity

This is the single most-tested scheduling concept, and the most misunderstood. Reverse the direction of thinking:

  • Affinity is a property of the pod that says “I want this kind of node.”
  • A taint is a property of the node that says “keep pods off me unless they tolerate this.”
  • A toleration is a property of the pod that says “I’m allowed onto a node with this taint.”

Crucially, a toleration does not force a pod onto a tainted node — it only permits it. To both attract and permit, you pair a toleration with a node affinity/selector. This pairing is a favorite trick question.

Apply and remove taints:

kubectl taint nodes node01 key=value:NoSchedule
kubectl taint nodes node01 key=value:NoSchedule-     # the trailing - removes it

The three taint effects:

EffectWhat it does
NoScheduleNew pods without a matching toleration won’t schedule here. Existing pods stay.
PreferNoScheduleSoft version — scheduler avoids the node but may still use it.
NoExecuteNew pods need a toleration and existing pods without one are evicted.

A matching toleration on the pod:

spec:
  tolerations:
    - key: "key"
      operator: "Equal"
      value: "value"
      effect: "NoSchedule"

This is exactly why a fresh control-plane node runs no normal workloads: kubeadm taints it node-role.kubernetes.io/control-plane:NoSchedule. To let user pods run there (a single-node cluster, for example), you remove the taint:

kubectl taint nodes <control-plane-node> node-role.kubernetes.io/control-plane:NoSchedule-

Resource Requests and Scheduling

The scheduler’s filter phase uses requests, not limits, to decide if a pod fits. A pod requesting 2 CPU won’t schedule on a node with 1 CPU of allocatable capacity left — even if the node is otherwise idle, because requests reserve capacity.

resources:
  requests:
    cpu: "500m"
    memory: "256Mi"
  limits:
    cpu: "1"
    memory: "512Mi"

If every node lacks enough requestable room, the pod sits Pending with Insufficient cpu/memory. The fix is usually lowering requests or freeing a node — a frequent troubleshooting overlap. For the full requests-vs-limits model, see the CKAD resource management guide.

Decision Cheat Sheet

When a question describes a placement need, map it fast:

ScenarioReach for
Run one pod on every nodeDaemonSet
Run a pod only on SSD nodesnodeSelector or node affinity (required)
Prefer a zone but don’t require itnode affinity (preferred)
Never put two replicas on one nodepod anti-affinity
Reserve a node for specific workloadstaint the node + matching toleration
Force a pod onto a node, scheduler downnodeName (manual scheduling)
Run a pod the kubelet manages directlystatic pod in the manifests dir

Exam-Day Speed Tips

  • Generate, don’t type. Use kubectl create/run with --dry-run=client -o yaml > file.yaml, then edit. Hand-writing manifests wastes minutes.
  • Set your context first for every question: kubectl config use-context <ctx>. Skipping this is the most common avoidable mistake — see Kubernetes exam mistakes to avoid.
  • Alias k=kubectl and use --show-labels and -o wide liberally to see node assignments.
  • For taints, remember the trailing dash removes: taint ... NoSchedule-.
  • Read kubectl describe Events before changing anything — it usually names the exact reason a pod is Pending.

The CKA kubectl cheat sheet collects these commands in one place for last-minute review.

Practice Under Real Exam Conditions

Reading about scheduling and doing it under a ticking clock are different skills. The CKA is hands-on and time-boxed, so the only reliable way to build speed is repetition on realistic tasks: tainting a node, watching a pod go Pending, adding the toleration, and confirming it schedules.

Sailor.sh’s Certified Kubernetes Administrator (CKA) Mock Exam Bundle gives you exam-style performance tasks on a real cluster that mirror the format and difficulty of the actual exam, including the workloads and scheduling scenarios covered here. Pair the hands-on practice with a structured plan like the 30-day CKA study plan, and shore up the adjacent domains with the CKA troubleshooting guide and CKA networking deep dive. If you’re building a home lab to practice for free, the Kubernetes lab setup for CKA walks you through it.

Frequently Asked Questions

What’s the difference between node affinity and taints/tolerations?

Node affinity is a pod-side attraction rule (“I want SSD nodes”). Taints are a node-side repulsion rule (“keep pods off unless they tolerate me”). A toleration only permits scheduling onto a tainted node — it doesn’t attract the pod there. To both attract and permit, combine a toleration with a node selector or affinity rule.

Why is my pod stuck in Pending?

Almost always a failed scheduler filter. Run kubectl describe pod <pod> and read the Events: common causes are insufficient CPU/memory requests, an untolerated taint, or a node selector/affinity rule that no node satisfies. Fix the specific cause the event names.

How do I run a pod on a control-plane node?

Either remove the control-plane taint (kubectl taint nodes <node> node-role.kubernetes.io/control-plane:NoSchedule-) or add a matching toleration to the pod. DaemonSets that must run everywhere include this toleration in their spec.

What’s the difference between a static pod and a DaemonSet?

A static pod is managed by a single node’s kubelet via the manifests directory and isn’t controlled by the API server (you delete it by removing the file). A DaemonSet is an API object managed cluster-wide that ensures one pod per eligible node and is controlled with normal kubectl commands.

Does the scheduler use requests or limits to place pods?

Requests. The filter phase reserves capacity based on a pod’s CPU and memory requests. Limits cap runtime usage but don’t affect scheduling decisions.

Is Workloads & Scheduling a big part of the CKA exam?

It’s about 15% of the exam by weight, but it overlaps heavily with Troubleshooting (30%) and Cluster Architecture (25%) — a Pending pod or a control-plane taint question can appear under any of them. See the CKA domains breakdown for the full weighting.

Limited Time Offer: Get 80% off all Mock Exam Bundles | Sale ends in 7 days. Start learning today.

Claim Now