Kubernetes Priority Classes: Why `Never` Pods Wait for SREs
Learn how Kubernetes priority classes affect scheduling, preemption, QoS, and eviction, with kubectl checks, copyable YAML, and pitfalls for SREs.
Kubernetes priority classes map a name to an integer, and the scheduler orders pending pods by that value, the highest first. A higher-value pod can also preempt lower-value pods unless its preemptionPolicy is Never. When scheduling surprises you, run kubectl get priorityclass and check priorityClassName on the pods involved before touching anything else.
TL;DR:
- PriorityClass changes queue order and preemption rights, but it reserves no capacity; pods must still meet node resource and affinity constraints.
- With preemptionPolicy set to Never, a pod can jump the queue without evicting others, but an unschedulable pod may back off as lower priority pods schedule.
- Only one PriorityClass can be globalDefault; it applies to new pods without a named class, while existing pods retain their resolved priority.
- QoS comes from resource requests and limits, not PriorityClass; the kubelet uses QoS during node pressure, while scheduler preemption ignores it.
- Repeated preemption signals capacity or resilience problems; check pod events and compare controller priorityClassName values with available classes before adding another tier.
Table of Contents
- How PriorityClass works: values, scope, and built-in classes
- Preemption behavior and preemptionPolicy
- How PriorityClass relates to QoS classes and kubelet eviction
- Create PriorityClass: kubectl commands and YAML you can copy
- Best practices and common pitfalls
- Debugging and troubleshooting preemption and pending pods
- When more priorities are the wrong fix
- A Kubernetes Health Check that fixes priority and preemption problems
- FAQ
- Sources
How PriorityClass works: values, scope, and built-in classes
A PriorityClass is a cluster-scoped API object that maps a name to an integer. Pods reference that name through priorityClassName in their template, and the value gets resolved onto the pod at creation. The official docs describe the effect: a higher value puts the pod earlier in the scheduler queue and can trigger preemption when the cluster runs short on resources.
A few facts decide whether your values behave:
- Built-in classes:
system-node-criticalis 2000001000 andsystem-cluster-criticalis 2000000000. Both are reserved for Kubernetes internals. - Reserved prefix: names starting with
system-are off limits for your own classes. - globalDefault: when set to true, new pods that omit
priorityClassNameget that class. Only one class can be the default, and existing pods keep the priority they already resolved. - Pods with no class: if no default exists, they run at priority zero.
Priority never overrides resource fit. Preemption runs in the scheduler’s PostFilter phase, so a high-priority pod still has to satisfy node affinity and capacity constraints. For deeper operational examples, see our PriorityClass and preemption explainer.
Preemption behavior and preemptionPolicy
Preemption is a last resort. The scheduler first tries to place a pod normally, and only when filtering finds no feasible node does it look for a node where evicting lower-priority pods would free enough room. Here is the sequence in practice:
- The pending pod fails the filter phase on every node.
- The scheduler searches for a node where removing lower-priority pods makes the pod fit.
- It picks victims, respecting PodDisruptionBudgets where it can.
- The victims terminate gracefully, and the preemptor is retried against the freed node.
preemptionPolicy defaults to PreemptLowerPriority. Setting it to Never gives you a pod that still jumps the queue but never forces anyone out. Per the Kubernetes docs, an unschedulable Never pod sits in the queue and is retried with back-off, which can let lower-priority pods schedule ahead of it.
The cost is pod churn. Maintainers advise using preemption sparingly because repeated eviction of lower-priority pods destabilizes clusters. PDBs can also collide with it, which is the territory of our guide to the disruption budget eviction error.
Pro Tip: Give batch and background jobs a non-preempting class with preemptionPolicy: Never, so they keep their queue position without ever evicting a serving pod.

How PriorityClass relates to QoS classes and kubelet eviction
These two mechanisms get conflated constantly, and they answer different questions. PriorityClass decides who schedules first and who may displace whom. QoS classes, derived from requests and limits, influence what the kubelet evicts when a node comes under pressure, as the scheduling and eviction docs lay out.
- QoS classes: Guaranteed, Burstable, and BestEffort come from your requests and limits, not from any priority setting.
- Scheduler preemption: victim selection follows priority values and PDBs, and QoS plays no part in it.
- Kubelet eviction: node-pressure eviction is a separate path that runs on the node, with its own ordering.
- No reservation: a PriorityClass reserves nothing. It changes queue order and eviction rights, never guaranteed capacity.
So a high-priority BestEffort pod is entirely possible, and it will be among the first the kubelet considers under memory pressure.
Create PriorityClass: kubectl commands and YAML you can copy
The kubectl reference covers --value, --global-default, --description, and --preemption-policy. Start with the imperative form:
kubectl create priorityclass high-priority --value=10000 --description="Customer-facing services"
kubectl create priorityclass batch-low --value=1000 --preemption-policy=Never
The declarative equivalent, plus a Deployment that uses it:
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority
value: 10000
globalDefault: false
description: "Customer-facing services"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
spec:
# Omit replicas to use the default
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: api
spec:
priorityClassName: high-priority
containers:
- name: api
image: example/api:latest
- Updating a class: pods already running keep their resolved priority. Only new pods pick up changes.
- Deleting a class: existing pods are unaffected, but new pods naming it will be rejected.
- Verification:
kubectl get pod <name> -o jsonpath='{.spec.priority}'shows the resolved integer.
Pro Tip: Space your values far apart, such as 1000 and 10000, so you can slot in a new tier later without renumbering anything.
Best practices and common pitfalls
Priority is a blunt tool. Reach for capacity planning, node pools, and sane requests and limits first, and use priority to express genuine ordering, not to protect workloads from a cluster that is too small.
- Skip the
system-prefix. It is reserved for Kubernetes components. - Remember the scope. PriorityClass is cluster-scoped, so a class created for one team is visible and usable by every namespace.
- Treat globalDefault as a cluster-wide change. Audit existing workload templates before enabling it.
- Keep tiers few. A few classes are easier to reason about than many.
Frequent preemption signals a problem: Kubernetes maintainers advise using preemption sparingly, because repeated eviction of lower-priority pods leads to pod churn and cluster instability.
Debugging and troubleshooting preemption and pending pods
When pods vanish or sit pending, work through this order:
- Run
kubectl describe pod <name>and read the Events section for preemption or scheduling failure messages. - Run
kubectl get events --sort-by=.lastTimestampto see preemption and eviction events across the namespace. - Compare
kubectl get priorityclassagainstpriorityClassNameon your controllers to find unintended high-priority workloads. - Check PodDisruptionBudgets and node pressure conditions, then scheduler and kubelet logs if the cause is still unclear.
- If the same pods keep getting displaced, lower or remove the class causing it.
Our quick check for evicted pods covers the eviction side, and the scheduler deep dive explains the phases behind these messages. If you inspect pods all day, a desktop tool like the Kubezilla pod shell workflow speeds up the loop.
When more priorities are the wrong fix
In my experience, clusters that preempt constantly are short on capacity or resilience, and adding another priority tier only moves the pain around. If preemption, repeated evictions, or recurring incident pages persist after you have tidied your classes, that is the point to get a Kubernetes Health Check instead of tuning further.
— James
A Kubernetes Health Check that fixes priority and preemption problems
We built our Kubernetes Health Check for exactly this situation: a cluster where scheduling and eviction behave in ways nobody can fully explain. It costs $300 as a fixed-price engagement, and you can start on our work with us page.

- What we review: PriorityClass usage, scheduler configuration, PDBs, and the sources of evictions.
- What you get: details are on our work with us page.
Send us your cluster details and we will tell you where the churn is coming from.
FAQ
What is a PriorityClass in Kubernetes?
A PriorityClass is a cluster-scoped object that maps a name to an integer value. The scheduler uses that value to order pending pods and decide which pods may preempt others.
Does PriorityClass guarantee resources for a pod?
No. It only changes scheduling order and the ability to displace other pods under resource pressure. Capacity guarantees come from requests, limits, and node sizing, as the Kubernetes docs make clear.
How do I stop a pod from preempting others?
Set preemptionPolicy: Never on its PriorityClass. The pod keeps its queue position but will not evict running pods.
Is PriorityClass the same as QoS class?
No. QoS is derived from requests and limits and mainly guides kubelet eviction, while PriorityClass governs scheduling order and preemption.
Recommended
- Kubernetes PriorityClass and Preemption: Who Gets Evicted
- Kubernetes Error Guide: Pod Status ‘SchedulingGated’
- Kubernetes Error Guide: ‘No preemption victims found
Get 500 Battle-Tested DevOps AI Prompts — Free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.