Skip to main content
RunBook Academy

KubernetesXIII · Kubernetes QoS ClassesKubernetes QoS classes

Guaranteed class — matching requests and limits for predictability

Advanced⏱ ~14 minkubectl

What you'll learn

  • Design a Guaranteed Pod (every container has matching requests and limits)
  • Reason about the trade-offs of Guaranteed (no bursting, predictable)
  • Identify when Guaranteed is the right choice for production
  • Recognise the limits of Guaranteed (still subject to cgroup OOMKill)

Prerequisites

Verified against Kubernetes 1.34.x · kubeadm 1.34.x · kubectl 1.34.x · etcd 3.6.x · CoreDNS 1.11.x · containerd 1.7.x / 2.x · 2026-08-16

Not yet marked complete on this device.

Guaranteed is the strictest QoS class: every container has matching requests and limits for both CPU and memory. This lesson covers the rules for Guaranteed, the trade-offs, and when it’s the right choice.

The Guaranteed rule

For a Pod to be Guaranteed:

  • Every container in the Pod has a resources block.
  • For every container, for both CPU and memory:
    • requests.cpu is set, AND
    • limits.cpu is set, AND
    • requests.cpu == limits.cpu
    • requests.memory is set, AND
    • limits.memory is set, AND
    • requests.memory == limits.memory

If any container fails these conditions, the Pod is not Guaranteed (it’s Burstable or BestEffort).

flowchart TD
    Container[Container] --> Q1{resources defined?}
    Q1 -- no --> BE[BestEffort]
    Q1 -- yes --> Q2{cpu: requests AND limits?}
    Q2 -- no --> B[Burstable]
    Q2 -- yes --> Q3{cpu: requests == limits?}
    Q3 -- no --> B
    Q3 -- yes --> Q4{memory: requests AND limits?}
    Q4 -- no --> B
    Q4 -- yes --> Q5{memory: requests == limits?}
    Q5 -- no --> B
    Q5 -- yes --> G[Guaranteed]

Special case: if a container sets only limits (no requests), the kubelet treats requests as equal to limits (this is the defaulting rule). So a container with only limits.cpu: 500m becomes effectively Guaranteed (for that container).

containers:
- name: app
  resources:
    limits: {cpu: 500m, memory: 512Mi}
    # no requests — defaulted to limits

This Pod is Guaranteed.

Why Guaranteed matters

Guaranteed Pods are evicted last under node pressure:

flowchart LR
    Pressure[Node pressure] --> Q{Pod QoS?}
    Q -- BestEffort --> E1[Evicted first]
    Q -- Burstable --> E2[Evicted second]
    Q -- Guaranteed --> E3[Evicted last]

When memory is low, the kubelet:

  1. Evicts BestEffort Pods first.
  2. If still under pressure, evicts Burstable Pods (sorted by usage vs request).
  3. If still under pressure, evicts Guaranteed Pods (sorted by usage vs request).

Guaranteed Pods survive longer in a pressure scenario. For stateful workloads (databases, queues), this matters: a database eviction causes data inconsistency; a stateless Pod eviction just causes a brief unavailability.

The trade-off: no bursting

A Guaranteed Pod cannot burst. The CPU limit equals the CPU request; the memory limit equals the memory request. If the workload needs more CPU than the limit, it is throttled. If it needs more memory than the limit, it is OOMKilled.

For workloads with bursty traffic (HTTP servers, batch processors), this is a problem:

# Guaranteed: predictable but no burst
containers:
- name: api
  resources:
    requests: {cpu: 500m, memory: 512Mi}
    limits:   {cpu: 500m, memory: 512Mi}
# Burst traffic hits 800m CPU — throttled to 500m
# Burstable: allows burst
containers:
- name: api
  resources:
    requests: {cpu: 100m, memory: 128Mi}
    limits:   {cpu: 800m, memory: 1Gi}
# Burst traffic can use up to 800m CPU

For latency-sensitive services that cannot tolerate throttling, Burstable is more practical.

When Guaranteed is the right choice

Guaranteed is the right choice for:

  • Databases: PostgreSQL, MySQL, MongoDB. Predictable resource usage; data integrity requires not being killed.
  • Message queues: Kafka, RabbitMQ. Broker state survives eviction only if the broker was flushed; better to be evicted last.
  • Distributed consensus: ZooKeeper, etcd. Eviction can cause quorum loss; better to be evicted last.
  • Workloads with predictable resource usage: the workload’s CPU and memory usage are stable; no need to burst.

Guaranteed is the wrong choice for:

  • HTTP servers with bursty traffic: throttling at peak causes tail latency spikes.
  • Batch processors: long-running jobs that need to use whatever CPU is available; Burstable allows bursting.
  • Workloads with variable memory usage: in-memory caches that grow under load; Burstable’s higher limit allows growth.

Sizing Guaranteed Pods

The discipline for sizing:

  • CPU: set to the actual peak usage. The Guaranteed Pod is throttled at this value; setting too low causes throttling at peak.
  • Memory: set to the actual peak usage plus headroom. OOMKill at peak loses state; better to over-provision.

For a PostgreSQL database with predictable workload:

containers:
- name: postgres
  resources:
    requests: {cpu: 2, memory: 4Gi}
    limits:   {cpu: 2, memory: 4Gi}

The Pod is Guaranteed. The scheduler reserves 2 CPU and 4Gi memory; the cgroup enforces the limit. PostgreSQL has predictable resource usage; this sizing is safe.

Production patterns

Database with Guaranteed QoS:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: postgres
spec:
  replicas: 3
  template:
    spec:
      containers:
      - name: postgres
        image: postgres:16
        resources:
          requests: {cpu: 2, memory: 4Gi}
          limits:   {cpu: 2, memory: 4Gi}
        volumeMounts:
        - name: data
          mountPath: /var/lib/postgresql/data
  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes: [ReadWriteOnce]
      resources:
        requests: {storage: 100Gi}

The StatefulSet’s Pods are Guaranteed. The PVCs provide durable storage. Under node pressure, the database Pods are evicted last.

Latency-sensitive service with Burstable:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  template:
    spec:
      containers:
      - name: nginx
        image: nginx:1.27.2
        resources:
          requests: {cpu: 200m, memory: 256Mi}
          limits:   {cpu: 2, memory: 1Gi}

The web server is Burstable; it can burst to 2 CPU during traffic spikes. Under node pressure, it is evicted before Guaranteed Pods but after BestEffort Pods.

Diagnosing QoS at runtime

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

Output:

NAMESPACE    NAME              QOS
team-a-prod  web-7c8           Burstable
team-a-prod  postgres-0        Guaranteed
team-a-prod  debug-tool        BestEffort

The cluster’s QoS distribution is visible. Production discipline: review this regularly; BestEffort Pods in production namespaces indicate misconfigured resources.

Cross-course references

  • The Linux course part XXXVII-Linux-Resources covers cgroup OOM and CPU throttling; Guaranteed is the cluster-level equivalent.
  • The Ansible course part XXXV-Ansible-Scripting covers service priority; Guaranteed is the cluster-level equivalent.
  • The Observability course part LXXXVII-Kubernetes-MetricsServer covers kubectl top; use it to verify sizing.

Quiz

Knowledge check · 4 questions

  1. Q1. A Pod has one container with `requests: {cpu: 1, memory: 1Gi}, limits: {cpu: 2, memory: 1Gi}`. What is its QoS class?

  2. Q2. A Guaranteed Pod can burst above its CPU limit briefly (e.g., for a 100ms spike) without being throttled.

  3. Q3. A team runs a PostgreSQL database as a Burstable Pod. Under node memory pressure, the database Pod is evicted; this causes data inconsistency. Walk through why and the fix.

    PostgreSQL Deployment with `requests: {cpu: 1, memory: 4Gi}, limits: {cpu: 2, memory: 8Gi}` (Burstable). Node runs out of memory; kubelet evicts Burstable Pods (sorted by usage vs request). The PostgreSQL Pod is using 7Gi, well above its 4Gi request. The kubelet evicts it. PostgreSQL loses connection mid-write; data inconsistency results.

  4. Q4. When is Guaranteed the right choice for a workload, and when is Burstable better?

Passing score: 75%. Answers are checked in this browser.

Production discipline

  • Make databases Guaranteed. Predictable resources; evicted last; data integrity.
  • Make latency-sensitive HTTP services Burstable. Allow bursting; tolerate throttling at extreme peak.
  • Audit QoS regularly. BestEffort Pods in production indicate misconfigured resources.
  • Verify Guaranteed at admission. A single container with mismatched values pulls the whole Pod down.
  • Document the QoS policy. Each workload type should have a documented QoS class and rationale.