DEV Community

The Cyber Sidekick
The Cyber Sidekick

Posted on

Create a PriorityClass, patch the Deployment, let the scheduler evict the neighbors (CKA)

Patch a Deployment with a new PriorityClass (and watch preemption evict the neighbors)

Kubernetes is about to evict a perfectly healthy, running pod, and that is the correct answer to this exam question. Today's CKA task: create a new PriorityClass, patch a Deployment to use it, and roll it out on a node that has no room left. The question even warns you that pods from other deployments will be evicted. Most people read that sentence twice. By the end of this video you will know exactly why it happens, and why you should leave the victims alone. Let's run it.

This is a CKA Workloads & Scheduling walkthrough. Every command below is real output from a live cluster, and you can reproduce the whole thing yourself (scripts at the end).

The scenario

Here is the question. Create a new PriorityClass named high-priority for user workloads, with a value that is one less than the highest existing user-defined priority class. Then patch the busybox-logger Deployment, running in the priority namespace, to use that new class, and ensure the Deployment rolls out successfully. Two warnings come with it. First: it is expected that pods from other Deployments in the priority namespace get evicted. Second: do not modify those other Deployments, or you lose points. So the deliverables are one PriorityClass, one patch, one healthy rollout, and the discipline to not touch anything else.

  • Create PriorityClass 'high-priority': value = highest USER-DEFINED class minus one
  • Patch Deployment 'busybox-logger' in ns 'priority' to use it, then roll out
  • EXPECTED: pods from other Deployments in the namespace get evicted
  • Do NOT modify the other Deployments (you lose points if you do)

How priority and preemption work

Two mechanisms drive this question. First, priority. A PriorityClass is a tiny cluster-scoped object: a name and an integer. When a pod's spec names it, the pod is admitted with that integer as its priority; bigger means more important, and the default is zero. Second, preemption. When the scheduler cannot find a node with room for a pending pod, it looks for nodes where evicting pods of LOWER priority would make room, evicts them, and schedules the pending pod in the freed space. Now connect that to the task: patching the Deployment's pod template triggers a rolling update, the replacement pods carry the new high priority, and on a full node the scheduler has to preempt someone to place them. That is why the question can promise evictions in advance.

The existing classes

Step one: what already exists? kubectl get priorityclass. Read this table the way the question wants you to. The two classes starting with system, node critical and cluster critical, sit around two billion; they belong to Kubernetes itself and you never touch them or count them. The USER-DEFINED classes are the other two: low-priority at minus ten, yes, negative values are legal, and user-high-priority at one million. The highest user-defined value is therefore 1000000, and one less than that is 999999. That single subtraction is the entire trick of part one.

$ kubectl get priorityclass
NAME                      VALUE        GLOBAL-DEFAULT   AGE     PREEMPTIONPOLICY
low-priority              -10          false            6m31s   PreemptLowerPriority
system-cluster-critical   2000000000   false            6m37s   PreemptLowerPriority
system-node-critical      2000001000   false            6m37s   PreemptLowerPriority
user-high-priority        1000000      false            6m31s   PreemptLowerPriority
Enter fullscreen mode Exit fullscreen mode

Create high-priority

You do not need YAML for this. kubectl create priorityclass high-priority, value 999999, and a description, because the question says it is for user workloads. One line, done. If you prefer the declarative route, the docs page for Pod Priority and Preemption has a copy-paste example, but in an exam the imperative command is thirty seconds faster. Confirm it: high-priority now exists with exactly the value we derived, one less than the highest user-defined class.

$ kubectl create priorityclass high-priority --value=999999 --description="high priority for user workloads"
priorityclass.scheduling.k8s.io/high-priority created

$ kubectl get priorityclass high-priority
NAME            VALUE    GLOBAL-DEFAULT   AGE   PREEMPTIONPOLICY
high-priority   999999   false            0s    PreemptLowerPriority
Enter fullscreen mode Exit fullscreen mode

The full node

Before the patch, look at the namespace we are about to disturb. Three Deployments: busybox-logger, the one we are told to patch, plus queue-worker and metrics-agent, the other deployments the question warns about. Everything is Running. Now print each pod's actual priority. The busybox-logger pods run at zero, the default, because their template names no priority class. The neighbors run at minus ten, from the low-priority class. Keep this picture in mind: the node is nearly out of CPU, and every replacement pod we are about to create outranks everything else here by roughly a million.

$ kubectl get deployments -n priority
NAME             READY   UP-TO-DATE   AVAILABLE   AGE
busybox-logger   2/2     2            2           3s
metrics-agent    1/1     1            1           2s
queue-worker     2/2     2            2           2s

$ kubectl get pods -n priority -o custom-columns='NAME:.metadata.name,STATUS:.status.phase,PRIORITY:.spec.priority'
NAME                              STATUS    PRIORITY
busybox-logger-594f746ddf-dvfnj   Running   0
busybox-logger-594f746ddf-mnqkv   Running   0
metrics-agent-8c89d9895-g2ktn     Running   -10
queue-worker-76df598f64-vbrrj     Running   -10
queue-worker-76df598f64-w4mtl     Running   -10
Enter fullscreen mode Exit fullscreen mode

Patch the deployment

Part two: patch the Deployment. The field lives in the POD TEMPLATE: spec.template.spec.priorityClassName``, set to high-priority. kubectl patch with a small JSON snippet does it in one command; kubectl edit gets you to the same place if you prefer an editor, the docs show the exact field under the Pod spec. The moment this lands, the Deployment controller starts a rolling update: it must bring up new pods that carry priority 999999 on a node that has no space for them. Watch what the scheduler does about that.

`console
$ kubectl -n priority patch deployment busybox-logger -p '{"spec":{"template":{"spec":{"priorityClassName":"high-priority"}}}}'
deployment.apps/busybox-logger patched
`

The eviction

Here is the moment the question promised. The fresh busybox-logger pod went Pending, the scheduler compared priorities, and a low-priority neighbor is being terminated to make room; its replacement sits Pending because, at priority minus ten, it cannot evict anyone. Kubernetes writes this decision down: the events show Preempted, naming the victim, evicted by the scheduler on behalf of the higher-priority pod. This is not a failure and there is nothing to fix. The question told you it was expected; your only job is to let it happen.

`console
$ kubectl get pods -n priority
NAME READY STATUS RESTARTS AGE
busybox-logger-594f746ddf-dvfnj 1/1 Running 0 4s
busybox-logger-594f746ddf-mnqkv 1/1 Running 0 4s
busybox-logger-645b98678b-kfwmw 0/1 Pending 0 0s
metrics-agent-8c89d9895-68282 0/1 Pending 0 0s
metrics-agent-8c89d9895-g2ktn 1/1 Terminating 0 3s
queue-worker-76df598f64-vbrrj 1/1 Running 0 3s
queue-worker-76df598f64-w4mtl 1/1 Running 0 3s

$ kubectl get events -n priority | grep -i preempt
0s Warning FailedScheduling pod/metrics-agent-8c89d9895-68282 0/1 nodes are available: 1 Insufficient cpu. no new claims to deallocate, preemption: 0/1 nodes are available: 1 No preemption victims found for incoming pod.
0s Normal Preempted pod/metrics-agent-8c89d9895-g2ktn Preempted by pod 6a344267-de23-4005-b466-00fe7699cf20 on node cka-scenario11-control-plane
`

Rollout + verify

Part three: prove the rollout finished. rollout status reports the deployment successfully rolled out. Now verify like a grader: print the priorities again. Both busybox-logger pods now show priority 999999 with class high-priority, and the neighbors still hold their original spec, untouched. Notice the namespace healed itself: once the rolling update retired the old zero-priority pods, their CPU freed up and the evicted neighbor's replacement scheduled on its own. In the exam it may just as well stay Pending, and that is fine too; the question graded the PriorityClass, the patch, and the rollout, not the neighbors' comfort.

`console
$ kubectl -n priority rollout status deployment/busybox-logger
Waiting for deployment "busybox-logger" rollout to finish: 1 out of 2 new replicas have been updated...
Waiting for deployment "busybox-logger" rollout to finish: 1 out of 2 new replicas have been updated...
Waiting for deployment "busybox-logger" rollout to finish: 1 out of 2 new replicas have been updated...
Waiting for deployment "busybox-logger" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "busybox-logger" rollout to finish: 1 old replicas are pending termination...
deployment "busybox-logger" successfully rolled out

$ kubectl get pods -n priority -o custom-columns='NAME:.metadata.name,STATUS:.status.phase,PRIORITY:.spec.priority,CLASS:.spec.priorityClassName'
NAME STATUS PRIORITY CLASS
busybox-logger-645b98678b-bf5t5 Running 999999 high-priority
busybox-logger-645b98678b-kfwmw Running 999999 high-priority
metrics-agent-8c89d9895-68282 Running -10 low-priority
queue-worker-76df598f64-vbrrj Running -10 low-priority
queue-worker-76df598f64-w4mtl Running -10 low-priority

$ kubectl get pods -n priority
NAME READY STATUS RESTARTS AGE
busybox-logger-645b98678b-bf5t5 1/1 Running 0 7s
busybox-logger-645b98678b-kfwmw 1/1 Running 0 13s
metrics-agent-8c89d9895-68282 1/1 Running 0 13s
queue-worker-76df598f64-vbrrj 1/1 Running 0 16s
queue-worker-76df598f64-w4mtl 1/1 Running 0 16s
`

Exam tips

The traps in this question are all reading comprehension. Highest USER-DEFINED class means you skip everything that starts with system; counting the two billion system classes gives a wildly wrong value. One less means minus one, so from one million you write 999999; do not invent a round number. kubectl create priorityclass is the fastest correct answer, and the priorityClassName field goes in the pod template, not on the Deployment's own spec. When the neighbors get evicted, leave them alone: the question explicitly says modifying other deployments costs points, and preemption is the intended behavior, not an incident. And verify with the pods, not the deployment: custom-columns on .spec.priority shows exactly what the grader checks.

  • 'Highest user-defined' = ignore system-node-critical / system-cluster-critical
  • 'One less' = 1000000 - 1 = 999999; kubectl create priorityclass does it in one line
  • priorityClassName goes in spec.template.spec (the POD template)
  • Evicted neighbors are EXPECTED: do not 'fix' them, do not modify their Deployments
  • Verify like the grader: pods' .spec.priority + rollout status

Recap

  • Highest user-defined class 1000000 -> high-priority created at 999999
  • One patch: spec.template.spec.priorityClassName = high-priority
  • Full node -> scheduler PREEMPTS a low-priority pod (Preempted event), rollout completes
  • Neighbors evicted as promised, never modified; subscribe + dev.to writeup

Reproduce this yourself

The entire scenario is scripted on a throwaway kind cluster: https://github.com/The-Cyber-Sidekick/TCS_CKA_2026_Exam_Scenarios

`bash
git clone https://github.com/The-Cyber-Sidekick/TCS_CKA_2026_Exam_Scenarios.git
cd TCS_CKA_2026_Exam_Scenarios/learning/scenarios/scenario11-priorityclass-preemption
./setup.sh # creates the cluster AND arms the scenario

solve it by hand, or:

./solution.sh # apply the answer key and verify
`


If this helped, subscribe to The Cyber SideKick on YouTube for more CKA drills, and grab the newsletter at https://thecybersidekick.beehiiv.com.

Top comments (0)