✦ For everyone, free.

Practical knowledge for real and everyday life

Home

Kubernetes Quality of Service Management

Kubernetes Quality of Service Management ensures predictable workloads by prioritizing resource allocation and scheduling based on predefined QoS classes.

Kubernetes Quality of Service Management is the classification system that assigns every Pod to one of three QoS classes — Guaranteed, Burstable, or BestEffort — derived automatically and exclusively from the relationship between its containers' resource requests and limits, without any dedicated field an operator sets directly. This classification is the primary mechanism connecting a Pod's resource declarations to how it is treated under node-level resource pressure: which Pods are evicted first when a node runs low on memory, and, to a lesser extent, how CPU contention is resolved when a node is oversubscribed.

Because QoS class is computed rather than explicitly assigned, managing it in practice means understanding precisely how requests and limits combine to produce each classification, and deliberately shaping resource declarations to land a workload in the QoS class its criticality warrants.


The Three Classes

Guaranteed

A Pod qualifies as Guaranteed only if every container (including init containers) specifies both a CPU and a memory limit, and each container's request for both resources exactly equals its limit — this is the strictest classification, requiring complete uniformity across every container in the Pod, not just the primary application container.

resources:
  requests:
    cpu: "500m"
    memory: "512Mi"
  limits:
    cpu: "500m"
    memory: "512Mi"

Burstable

A Pod qualifies as Burstable if at least one container specifies a CPU or memory request or limit, but the Pod does not meet the full criteria for Guaranteed — this is the most common classification in practice, covering the typical case where requests are set below limits to allow some burst capacity.

resources:
  requests:
    cpu: "250m"
    memory: "256Mi"
  limits:
    cpu: "1"
    memory: "512Mi"

BestEffort

A Pod qualifies as BestEffort only if no container specifies any request or limit at all, for any resource — this is an all-or-nothing classification; a Pod with even a single resource declaration on a single container is Burstable, not BestEffort.

resources: {}

Eviction Priority Under Node Pressure

The Ordering

Under memory pressure, the kubelet evicts Pods in the order BestEffort first, then Burstable (ranked by how far current usage exceeds request, proportionally), and Guaranteed last — this ordering directly reflects the strength of resource commitment each class represents, with Guaranteed Pods receiving the strongest protection precisely because they declared the strictest, most predictable resource footprint.

Within-Class Ranking for Burstable Pods

Among Burstable Pods competing for eviction priority, those whose actual memory usage most exceeds their declared request (proportionally) are evicted first — a Burstable Pod using memory close to or below its request is comparatively protected relative to one bursting significantly above its baseline, even within the same QoS tier.

kubectl get pod codartium-app -o jsonpath='{.status.qosClass}'

Managing QoS Deliberately

Choosing Guaranteed for Critical Workloads

Workloads whose continued operation is critical — core infrastructure components, latency-sensitive services with strict SLAs — benefit from deliberately setting requests equal to limits to secure Guaranteed classification, accepting the tradeoff of losing burst capacity in exchange for the strongest eviction protection available.

Accepting Burstable for Typical Applications

Most ordinary application workloads are well-served by Burstable classification, balancing reasonable eviction protection against the flexibility of absorbing occasional load spikes without needing every container's limit set exactly equal to its request.

Avoiding Unintentional BestEffort

A container that omits resource declarations entirely — often simply an oversight during initial authoring rather than a deliberate choice — lands in BestEffort by default, receiving the weakest possible protection under node pressure; a LimitRange with defaultRequest values is a common safeguard against this happening unintentionally.

apiVersion: v1
kind: LimitRange
metadata:
  name: codartium-qos-safeguard
spec:
  limits:
    - defaultRequest:
        cpu: "100m"
        memory: "128Mi"
      type: Container

Verifying QoS Class Across a Cluster

kubectl get pods -A -o custom-columns=NAMESPACE:.metadata.namespace,NAME:.metadata.name,QOS:.status.qosClass

Auditing QoS class distribution across a namespace or cluster is a useful check to confirm critical workloads are actually landing in the intended class, and to surface any workloads unintentionally left at BestEffort due to missing resource declarations.


Example

apiVersion: v1
kind: Pod
metadata:
  name: codartium-qos-example
spec:
  containers:
    - name: app
      image: codartium/app:latest
      resources:
        requests:
          cpu: "500m"
          memory: "512Mi"
        limits:
          cpu: "500m"
          memory: "512Mi"
kubectl get pod codartium-qos-example -o jsonpath='{.status.qosClass}'