Without an explicit priority, a critical payment pod and a batch cleanup job carry exactly the same weight in the scheduler’s eyes: on a saturated node, whoever arrives first gets the spot, regardless of actual business importance. PriorityClass fixes that gap by giving the scheduler an explicit criterion to decide.

A numeric priority, compared globally

A PriorityClass maps a name to a numeric value; the higher the number, the higher the priority.

apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: critical-payment
value: 1000000
globalDefault: false
description: "Reserved for payment services, never preempted first."

That value compares globally across every pod on the cluster, not just within one team or namespace: without collective discipline over who’s allowed to create high-value PriorityClass objects, a team can accidentally (or deliberately) grant itself a priority that outranks everything else. kubectl get priorityclass lists what already exists before creating a new one without thinking about overlap.

What priority actually changes about scheduling order

A higher-priority pod jumps ahead of lower-priority pods in the scheduler’s queue, without waiting its natural turn. On a cluster with available capacity, this effect stays invisible: everyone gets scheduled anyway. Priority only shows up under real capacity constraints.

Preemption: evicting to make room

When no node has available capacity for a pending pod, the scheduler can evict one or more lower-priority pods on a given node, if that eviction frees up enough room for the priority pod. It’s not a silent mechanism: the event shows up in the evicted pod’s description.

# The evicted pod shows exactly why
kubectl describe pod low-priority-batch-job
# Events: Preempted by a higher priority pod

Preemption respects, as much as possible, constraints already set elsewhere: a PodDisruptionBudget on candidate pods for eviction is taken into account, the scheduler tries to violate as few PDBs as possible before picking its victims. That’s not an absolute guarantee of PDB compliance under heavy contention, but a priority in the selection.

preemptionPolicy: Never, for priority without eviction rights

Not every high priority should carry the right to evict. A pod can have a high priority to jump the queue, without ever being allowed to preempt other pods:

apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: high-priority-no-preempt
value: 100000
preemptionPolicy: Never

This setting fits genuinely important but wait-tolerant workloads (a priority batch job that should go ahead of other batch jobs, without ever interrupting a production service to do it).

The trap of a poorly set globalDefault

Only one PriorityClass can carry globalDefault: true, applied automatically to any pod that specifies none. Setting that default too high silently raises the priority of everything that doesn’t explicitly opt in, which dilutes the mechanism’s whole purpose: if almost everything is a priority, nothing really is.

Takeaway

PriorityClass gives the scheduler an explicit criterion to arbitrate between competing pods under capacity pressure, and preemption is its consequence under real strain, not an always-active mechanism. preemptionPolicy: Never separates jumping-the-queue from eviction-rights, a distinction that matters for high-but-non-destructive priorities. Reserving the highest priorities for genuinely critical workloads, and watching globalDefault, keeps a protection mechanism from becoming background noise nobody respects anymore, part of what tells apart a production-ready cluster from a plain default install from the earliest steps of a Kubernetes migration.