KCNA — Kubernetes and Cloud Native Associate
Three Nodes, and Nowhere for the Pod to Go
Goal
You apply taints/tolerations, nodeSelector, and node affinity yourself to see how each changes a Pod's placement, and observe that even for the same Pending, the causes differ (cannot tolerate the taint / the label does not match / there is no matching zone).
Why it matters
In Kubernetes, "which node is this Pod running on" is not chance but the result of the scheduler's calculation. kube-scheduler watches unassigned Pods, weighs the taints, labels, resources, and affinity of each node, picks a node that passes, and fills in spec.nodeName. If you cannot read why this decision came out as it did, you will flounder over a single Pending, asking "is it out of resources?" or "is a node dead?"
A taint is a node declaring "I don't accept just anyone," and a toleration is a Pod answering "I can put up with that." nodeSelector and node affinity are the opposite: the Pod demands "I prefer / I require this kind of node." The two point in opposite directions and are often applied together, so looking at only one cannot explain the placement.
Steps
- Create the namespace
kcna-schedand extract the node names and zone labels to a file. - Apply the
tier=reserved:NoScheduletaint to all three nodes. - Confirm that the Pod
plain, which has no toleration, stays stuck in Pending. - Confirm that the Pod
tolerant, which has a toleration for the taint, gets assigned. - On
lab-node-0, put the labeldisktype=ssd, and usenodeSelectorto create a Pod that sits only on that node. - With node affinity, create a Pod that sits only on the
zone-1andzone-2nodes. - Create a Pod that requires a label that does not exist (
disktype=nvme) and so stays stuck in Pending. - Record the result of each Pod in
/root/kcna-sched/report.txtas a ledger.
Notes
- In
kubectl describe pod <이름> -n kcna-sched, the Events and the reason of thePodScheduledcondition tell you "why it could not go." - Being blocked because it cannot tolerate a taint and being blocked because the selector does not match have the same symptom, so tell the cause apart with describe.
- Official docs: Taints and tolerations · Assigning Pods to nodes · kube-scheduler.
Create a working namespace and a node map
Create the namespace kcna-sched, and save each node's name and its topology.kubernetes.io/zone label, one per line in 이름=존 (name=zone) format, to /root/kcna-sched/nodes.txt.
The only world the scheduler can see is the node objects. You can extract the name and the zone label together with kubectl get nodes -L <라벨키> or -o jsonpath. If you create the namespace with create --dry-run=client and apply it, it is safe to run several times.
Lock all three nodes with a reserved mark
Apply the tier=reserved:NoSchedule taint to all three nodes, so that a Pod without a toleration cannot enter anywhere.
A NoSchedule taint keeps out Pods that have not declared a toleration for that taint. Apply kubectl taint node <이름> key=value:NoSchedule to the three nodes. Add --overwrite so you can apply it again even if it is already in place.
A Pod with nowhere to go stays stuck in Pending
In the namespace kcna-sched, create a Pod plain (image nginx:1.27-alpine) with no toleration or selector at all. This Pod must fail to be scheduled and stay in Pending.
All three nodes are locked by the NoSchedule taint, so an ordinary Pod with no toleration cannot be assigned to any node. Check the reason of the PodScheduled condition with kubectl get pod plain -o wide and describe.
A Pod that tolerates the reserved mark gets in
In the namespace kcna-sched, create a Pod tolerant (image nginx:1.27-alpine), declaring a toleration for the tier=reserved NoSchedule taint so that it is actually assigned to a node.
A toleration is paired with a taint by key, operator, value, and effect. For the operator, you can give the value explicitly with Equal, or match only the key with Exists. Once it is assigned, spec.nodeName is filled in and kwok turns it into Running.
Place it only on the SSD node
On the node lab-node-0, add the label disktype=ssd, and in the namespace kcna-sched create a Pod pinned-ssd (image nginx:1.27-alpine). This Pod must tolerate the reserved taint while sitting, through nodeSelector, only on a node with disktype=ssd, so that it ends up assigned to lab-node-0.
nodeSelector narrows the candidates to nodes that have that label. The taint is still in place, so you need a toleration as well. If you attach the label to only one node, nodeSelector steers the assignment to that one node.
Node affinity that sends it only to certain zones
In the namespace kcna-sched, create a Pod zoned (image nginx:1.27-alpine). While tolerating the reserved taint, use requiredDuringSchedulingIgnoredDuringExecution node affinity to make it sit only on nodes whose topology.kubernetes.io/zone is zone-1 or zone-2. The resulting node must be lab-node-1 or lab-node-2.
Node affinity is more expressive than nodeSelector. If you give the In operator a list of values, matching any one of them is enough. Look at the zone labels you extracted in step 1 to check in advance which nodes are candidates. A required rule leaves the Pod Pending if there is no matching node.
A requirement that no node can satisfy
In the namespace kcna-sched, create a Pod nowhere (image nginx:1.27-alpine). Make it tolerate the reserved taint but, through nodeSelector, require disktype=nvme. No such node exists, so this Pod must stay in Pending.
Even with a toleration, the Pod is not scheduled if the selector cannot find a matching node. Being blocked because it cannot tolerate a taint and being blocked because the label does not match have different causes but the same symptom, Pending. Read from the Events in describe what is lacking.
Leave a ledger of what decided the placement
In /root/kcna-sched/report.txt, write what happened to each Pod in four lines: plain=pending, tolerant=scheduled, pinned-ssd=lab-node-0, and nowhere=pending. The values must match the actual cluster state (pending for a Pod that is Pending, and the node name for an assigned Pod).
The grader checks the four lines of this file against the actual cluster state. For an assigned Pod, write spec.nodeName, and for a Pod that is Pending, write pending. Do not write by guessing; copy the values you confirmed with kubectl get pods -n kcna-sched -o wide.