CKA Workloads and Scheduling — the knob that does not place
Four knobs. One owner. HPA multiplies a no. PriorityClass cannot invent leftover.
<!-- hal:authoritative:yaml -->
§I — Frame
CKA on this arc is 75% closed. Cluster Architecture 25%, Services and Networking 20%, Troubleshooting 30%. Storage 10% was taken on the 08-10 Ops slot. The last unopened domain is Workloads and Scheduling at 15%.
The exam will not ask you to explain AKS. It will hand you a Pending Pod and four knobs: a request, a taint, a PriorityClass, and an HPA. Only one of them places the Pod. The other three change what the scheduler sees, or how many copies exist, or which running Pod dies so this one can live.
Call the failure the knob that does not place. You scale the HPA. The replica count rises. Every replica is Pending. The scheduler already said no. More copies of a no are still a no.
§II — Requests and limits
A request is the number kube-scheduler reserves. A limit is the number the kubelet enforces after bind (K8sUR3, pp. 86-88). Q4 and Q19 are the drill: write both, then watch which one the Pending event names. The event names the request. Insufficient cpu means the request does not fit allocatable leftover. Raising the limit does not create leftover.
CPU over the request is throttled. Memory over the request can be killed when the node is tight, because pages cannot be stolen the way idle CPU can (K8sUR3, p. 88). A limit below the request is invalid and the API rejects it. A request of zero is valid and is how a burst eats the node.
On the exam, kubectl describe node is the packing sheet. Allocatable minus the requests already bound is the leftover. DaemonSets are already bound. Forgetting them is the usual wrong leftover.
§III — Taints and tolerations
Q10: taint node01 PERMISSION=granted:NoSchedule. Schedule a Pod that names the matching toleration. A Pod without it stays Pending with untolerated taint.
Three effects, three verbs.
| Effect | New Pods | Running Pods |
|---|---|---|
NoSchedule | Refused if no match | Untouched |
PreferNoSchedule | Avoided if possible | Untouched |
NoExecute | Refused if no match | Evicted if no match |
The exam loves NoSchedule and a candidate who types NoExecute and deletes a running workload. Match is key, value, and effect. operator: Exists with no key is the add-on escape. Do not put it on the app Pod unless the question asked you to land on a tainted node and named no key.
The day's Ops lesson is Q10 at cluster scale: AKS already tainted the system pool CriticalAddonsOnly=true:NoSchedule. Your user Pod should fail that predicate. That is success.
§IV — PriorityClass and preemption
Q7 is the knob you reach when no node fits and a lower-priority Pod is sitting on the leftover you need. A PriorityClass is an integer. Higher wins. The scheduler, if preemption is enabled, deletes the lower Pod so the higher one can bind.
Priority does not create capacity. A 2 CPU Pod on a cluster whose largest allocatable leftover is 1 CPU stays Pending at any priority. Preemption needs a victim whose request, once gone, makes the leftover large enough.
Priority also does not bypass taints. A system-cluster-critical Pod still needs the toleration the system pool requires. The add-on Pods have both.
On the exam: create the PriorityClass, set spec.priorityClassName on the Pod, do not invent spec.priority as a raw integer unless the question shows that form. The class is the object the integer lives on.
§V — HPA is not a scheduler
Q5: an HPA adds or removes replicas from a Deployment (or a scale subresource). The new replica is a new Pod. That Pod goes through the same predicates. If the Deployment's template does not fit, the HPA's currentReplicas climbs and readyReplicas does not.
HPA answers "how many." The scheduler answers "where." Requests, taints, and affinity answer "where" first. Scaling a refused template is the knob that does not place.
A question that says "the app is slow, CPU is 90%, Pods are Pending" has two clocks. HPA is the 90%. The Pending is the scheduler. Fix the template (request, taint, pool) before you raise maxReplicas.
§VI — Workloads that change the count, not the fit
Deployments, ReplicaSets, Jobs, CronJobs, and DaemonSets are the rest of the 15%. They change how many Pods exist and which controller owns the restart. They do not change the predicate list.
A DaemonSet is the exception that looks like a bypass: it places one Pod per eligible node, and it often carries the tolerations that land on the system pool. That is why CNI and kube-proxy run there. A DaemonSet without those tolerations still skips tainted nodes. It is not a second scheduler. It is a controller that asks the scheduler once per node.
A Job with parallelism: 10 is ten scheduler decisions. One failed predicate times ten is ten Pendings. backoffLimit does not retry placement. It retries the container after a bind.
§VII — Exam traps
Describe the Pod, then the node. 08-10 Troubleshooting already taught this order for disks. Same order for scheduling. The Pod event names the predicate. The node allocatable confirms it.
**Do not tolerate CriticalAddonsOnly to "make it schedule" unless the question is about add-ons.** That is the AKS fence and the Q10 fence. Opening it is a running app on the wrong node.
HPA vs scheduler. Count vs place. If readyReplicas is 0 and replicas is 5, you do not have an HPA problem.
Priority vs request. Priority picks a victim. The request still has to fit after the victim is gone.
Affinity vs taint. Labels invite. Taints refuse. A node can match your selector and still refuse on a taint. Both predicates run.
§VIII — Practice
0/3 nodes are available: 3 node(s) had untolerated taint {PERMISSION: granted}. What is the smallest fix that lands them on node01 only if the question asked for that node?PERMISSION=granted:NoSchedule. If the question also requires that node, add the nodeName or a selector. The toleration alone makes every node with that taint legal.Insufficient cpu. HPA maxReplicas is 10. What do you change first?kubectl describe node shows 500m leftover and the Pod requests 1 CPU. What will preemption not do?NoExecute. What happens to a running Pod on that node that has no toleration?NoSchedule would have left it. The type is the question.CriticalAddonsOnly. The user Deployment should fail that predicate.had volume node affinity conflict?§IX — Close
Workloads and Scheduling is the last CKA domain this arc had not opened. The domain is four knobs and one owner. The owner is kube-scheduler. Requests feed it. Taints restrict it. PriorityClass lets it evict. HPA multiplies the question. The day's Ops lesson is the AKS topology those knobs sit on. The day's Dev lesson is a Python function that prints the no without binding.
CKA blueprint on this arc is now 90% if you count the 08-10 Ops storage fire, 75% on the Cert slot alone. The remaining 10% Storage can wait for a Cert revisit. Next K8s day 2026-08-19 returns to CKS (counter 9, odd): Cluster Hardening 15% or System Hardening 15%.
Related
- Archmagus-Stack/01-Earth-DevOps/Synthesis-Lessons/2026-08-16-kubernetes-scheduling-on-aks-node-pools-taints-the-system-pool-and-the-pending-that-is-not-storage/lesson
- Archmagus-Stack/Polyglot-Dev/Python/2026-08-16-python-and-the-kubernetes-scheduler-surface-node-taints-tolerations-and-a-fit-checker-that-does-not-bind/lesson
- Archmagus-Stack/Cert-Prep/CNCF/2026-08-10-cka-troubleshooting-the-static-pod-control-plane-node-notready-and-reading-a-failing-pod-from-events-through-logs/lesson