Fatskills
Practice. Master. Repeat.
Study Guide: TECH **Docker & Kubernetes: Resource Requests, Limits, and QoS Classes**
Source: https://www.fatskills.com/kubernetes/chapter/tech-docker-kubernetes-resource-requests-limits-and-qos-classes

TECH **Docker & Kubernetes: Resource Requests, Limits, and QoS Classes**

By Fatskills Exam Guides Team — the exam nerds behind 28,500+ quizzes and 2.1M practice questions across 500+ global exams.

⏱️ ~7 min read

Docker & Kubernetes: Resource Requests, Limits, and QoS Classes

A hyper-practical, zero-fluff guide for engineers who need to deploy stable, cost-efficient workloads in production.


1. What This Is & Why It Matters

You’re running a Kubernetes cluster in production. One night, a misconfigured pod starts consuming all available CPU on a node, starving other critical services. Your monitoring alerts fire, but by the time you SSH in, the node is unresponsive. You force-drain it, but the outage has already cost thousands in lost transactions.

This is what happens when you ignore resource requests, limits, and QoS classes.

In Kubernetes, requests and limits define how much CPU and memory a container needs and can use, respectively. QoS classes (Guaranteed, Burstable, BestEffort) determine how Kubernetes prioritizes pods when resources run low. Together, they: - Prevent noisy neighbors from crashing your cluster.
- Ensure critical workloads get the resources they need.
- Help Kubernetes make smart scheduling decisions.
- Optimize cloud costs by right-sizing pods.

Real-world scenario:
You’re migrating a monolithic app to Kubernetes. The app has: - A high-priority API (must always have CPU/memory).
- A batch job (can run when resources are available).
- A low-priority logging sidecar (can be killed if needed).

Without proper resource management, the batch job could starve the API, or the logging sidecar could get evicted unnecessarily. This guide shows you how to configure these settings correctly.


2. Core Concepts & Components


1. Resource Requests

  • Definition: The minimum amount of CPU/memory a container needs to run.
  • Production insight: If a node doesn’t have enough resources to satisfy a pod’s requests, Kubernetes won’t schedule it (pod stays in Pending state).
  • Example: requests: { cpu: "500m", memory: "256Mi" } (500 millicores, 256 mebibytes).

2. Resource Limits

  • Definition: The maximum amount of CPU/memory a container can use.
  • Production insight: If a container exceeds its memory limit, Kubernetes kills it (OOMKilled). If it exceeds CPU, it gets throttled.
  • Example: limits: { cpu: "1", memory: "512Mi" } (1 vCPU, 512 mebibytes).

3. CPU Units

  • Definition:
  • 1 = 1 vCPU (AWS: 1 vCPU, GCP: 1 core, Azure: 1 core).
  • 500m = 0.5 vCPU (500 millicores).
  • Production insight: CPU is compressible (throttled if exceeded), while memory is incompressible (killed if exceeded).

4. Memory Units

  • Definition:
  • 1Gi = 1 gibibyte (1024 mebibytes).
  • 1G = 1 gigabyte (1000 megabytes).
  • Production insight: Always use Gi/Mi (binary units) in Kubernetes to avoid confusion with cloud provider billing (which often uses decimal units).

5. Quality of Service (QoS) Classes

  • Definition: Kubernetes assigns a QoS class to every pod based on its requests/limits. Determines eviction priority.
  • Guaranteed: Requests == Limits (highest priority, least likely to be killed).
  • Burstable: Requests < Limits (medium priority, killed if node is under pressure).
  • BestEffort: No requests/limits (lowest priority, killed first).
  • Production insight: Critical workloads (e.g., databases, APIs) should be Guaranteed. Batch jobs can be Burstable.

6. Eviction Thresholds

  • Definition: Kubernetes evicts pods when a node runs low on memory or disk. QoS classes determine the order.
  • Production insight: If a node hits memory pressure, BestEffort pods are killed first, then Burstable, then Guaranteed.

7. Node Allocatable Resources

  • Definition: The amount of CPU/memory available for pods after accounting for system daemons (kubelet, OS, etc.).
  • Production insight: If you don’t account for allocatable resources, Kubernetes may schedule pods on a node that’s already overcommitted.

8. Vertical Pod Autoscaler (VPA)

  • Definition: Automatically adjusts requests/limits based on usage (not covered in depth here, but useful for dynamic workloads).
  • Production insight: VPA is great for stateful apps but can cause instability if misconfigured.


3. Step-by-Step Hands-On: Configuring Requests, Limits, and QoS


Prerequisites

  • A running Kubernetes cluster (Minikube, Kind, or cloud-based).
  • kubectl installed and configured.
  • A sample app (we’ll use an Nginx deployment).

Step 1: Deploy a Pod Without Requests/Limits (BestEffort QoS)

kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: nginx-besteffort
spec:
  containers:
  - name: nginx
image: nginx:latest EOF

Verify:


kubectl get pod nginx-besteffort -o json | jq '.status.qosClass'
# Output: "BestEffort"

Step 2: Deploy a Pod With Requests Only (Burstable QoS)

kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: nginx-burstable
spec:
  containers:
  - name: nginx
image: nginx:latest
resources:
requests:
cpu: "100m"
memory: "128Mi" EOF

Verify:


kubectl get pod nginx-burstable -o json | jq '.status.qosClass'
# Output: "Burstable"

Step 3: Deploy a Pod With Requests == Limits (Guaranteed QoS)

kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: nginx-guaranteed
spec:
  containers:
  - name: nginx
image: nginx:latest
resources:
requests:
cpu: "500m"
memory: "256Mi"
limits:
cpu: "500m"
memory: "256Mi" EOF

Verify:


kubectl get pod nginx-guaranteed -o json | jq '.status.qosClass'
# Output: "Guaranteed"

Step 4: Simulate Memory Pressure and Observe Evictions

  1. Deploy a memory-hog pod (BestEffort QoS):
    ```bash
    kubectl apply -f - <<EOF
    apiVersion: v1
    kind: Pod
    metadata:
    name: memory-hog
    spec:
    containers:
    • name: stress
      image: polinux/stress
      command: ["stress"]
      args: ["--vm", "1", "--vm-bytes", "500M", "--vm-hang", "1"]
      EOF
      ```
  2. Check node memory usage:
    bash
    kubectl top node
  3. Force eviction by filling up memory:
    ```bash
    kubectl apply -f - <<EOF
    apiVersion: v1
    kind: Pod
    metadata:
    name: memory-crash
    spec:
    containers:
    • name: stress
      image: polinux/stress
      command: ["stress"]
      args: ["--vm", "1", "--vm-bytes", "2G", "--vm-hang", "1"]
      EOF
      ```
  4. Check which pods were killed:
    bash
    kubectl get pods
    kubectl describe pod memory-hog | grep -i "oomkilled"

    Expected: The memory-hog (BestEffort) pod is killed first, while nginx-guaranteed (Guaranteed) survives.

4. ? Production-Ready Best Practices


Security

  • Never run pods without requests/limits (BestEffort QoS is dangerous in production).
  • Use LimitRanges to enforce default requests/limits per namespace: ```yaml apiVersion: v1 kind: LimitRange metadata:
    name: mem-limit-range spec:
    limits:
    • default:
      memory: 512Mi defaultRequest:
      memory: 256Mi type: Container ```

Cost Optimization

  • Right-size requests/limits using historical metrics (e.g., Prometheus + Grafana).
  • Use Vertical Pod Autoscaler (VPA) for dynamic workloads (but test thoroughly).
  • Avoid over-provisioning (e.g., don’t set limits: 8Gi if the app only needs 1Gi).

Reliability & Maintainability

  • Label pods with QoS class for easier debugging: yaml metadata:
    labels:
    qos: guaranteed
  • Use ResourceQuotas to prevent teams from over-consuming resources: yaml apiVersion: v1 kind: ResourceQuota metadata:
    name: mem-cpu-quota spec:
    hard:
    requests.cpu: "10"
    requests.memory: 20Gi
    limits.cpu: "20"
    limits.memory: 40Gi

Observability

  • Monitor pod evictions with kubectl get events --sort-by='.metadata.creationTimestamp'.
  • Set up alerts for:
  • Pods in Pending state (insufficient resources).
  • Pods with OOMKilled status.
  • Nodes with high memory pressure.


5. ⚠️ Common Mistakes & Traps

Mistake Symptom Fix/Prevention
No requests/limits Pods get evicted randomly under memory pressure. Always set requests/limits (even for dev environments).
Requests > Limits Pod fails to start (Invalid value: must be less than or equal to cpu limit). Ensure requests <= limits.
Over-provisioning limits Cloud costs spiral (e.g., setting limits: 8Gi for a 100MB app). Use historical metrics to right-size.
Ignoring allocatable resources Pods scheduled on nodes that are already overcommitted. Check kubectl describe node for Allocatable.
Using decimal units (GB) instead of binary (Gi) Memory limits are 2.4% smaller than expected (1GB = 0.93Gi). Always use Gi/Mi in Kubernetes.


6. ? Exam/Certification Focus


Typical Question Patterns

  1. QoS Class Determination:
  2. "A pod has requests: { cpu: 500m, memory: 1Gi } and limits: { cpu: 1, memory: 2Gi }. What is its QoS class?"


    • Answer: Burstable (requests < limits).
  3. Eviction Order:

  4. "Under memory pressure, which pod is killed first: Guaranteed, Burstable, or BestEffort?"


    • Answer: BestEffort → Burstable → Guaranteed.
  5. CPU Throttling vs. Memory OOM:

  6. "A pod exceeds its CPU limit. What happens?"
    • Answer: It gets throttled (not killed).
  7. "A pod exceeds its memory limit. What happens?"


    • Answer: It gets OOMKilled.
  8. Scheduling Failures:

  9. "A pod is stuck in Pending state. What’s the most likely cause?"
    • Answer: Insufficient resources to satisfy requests.

Key ⚠️ Trap Distinctions

  • Requests vs. Limits:
  • Requests = "I need at least this much to run."
  • Limits = "I can’t use more than this."
  • CPU vs. Memory:
  • CPU is compressible (throttled).
  • Memory is incompressible (killed).
  • QoS Classes:
  • Guaranteed: requests == limits.
  • Burstable: requests < limits.
  • BestEffort: No requests/limits.


7. ? Hands-On Challenge (with Solution)


Challenge

Deploy a pod with: - Requests: cpu: 200m, memory: 256Mi.
- Limits: cpu: 500m, memory: 512Mi.
Verify its QoS class is Burstable.

Solution

kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: challenge-pod
spec:
  containers:
  - name: nginx
image: nginx:latest
resources:
requests:
cpu: "200m"
memory: "256Mi"
limits:
cpu: "500m"
memory: "512Mi" EOF

Verify:


kubectl get pod challenge-pod -o json | jq '.status.qosClass'
# Output: "Burstable"

Why it works: The pod has requests < limits, so Kubernetes assigns it the Burstable QoS class.


8. ? Rapid-Reference Crib Sheet

Command/Concept Usage
kubectl top pod Check CPU/memory usage of pods.
kubectl describe node <node> Check allocatable resources and pressure.
kubectl get events --sort-by='.metadata.creationTimestamp' View eviction events.
QoS Classes Guaranteed (requests == limits), Burstable (requests < limits), BestEffort (no requests/limits).
CPU Units 1 = 1 vCPU, 500m = 0.5 vCPU.
Memory Units Always use Gi/Mi (binary) in Kubernetes.
LimitRange Enforce default requests/limits per namespace.
ResourceQuota Limit total resources per namespace.
⚠️ OOMKilled Pod exceeded memory limit.
⚠️ Throttled Pod exceeded CPU limit (not killed).


9. ? Where to Go Next

  1. Kubernetes Official Docs: Resource Management
  2. Kubernetes Best Practices: Resource Requests and Limits
  3. Vertical Pod Autoscaler (VPA) Docs
  4. Kubernetes the Hard Way: Resource Management (Advanced)


ADVERTISEMENT