DEV Community

janak0ff
janak0ff

Posted on

Day 50: Set Resource Limits in Kubernetes Pods

The Nautilus DevOps team has noticed performance issues in some Kubernetes-hosted applications due to resource constraints. To address this, they plan to set limits on resource utilization. Here are the details:
Create a pod named httpd-pod with a container named httpd-container. Use the httpd image with the latest tag (specify as httpd:latest). Configure the following container-level resource requests and limits for the container:

Requests: Memory: 15Mi, CPU: 100m
Limits: Memory: 20Mi, CPU: 100m


Introduction

Welcome to Day 50 of my 100 Days of DevOps journey! Today, we're learning about a crucial Kubernetes concept: Resource Limits.

Why Resource Limits Matter

Imagine you're in a shared kitchen with 10 people. If one person takes all the ingredients, nobody else can cook. Similarly, in Kubernetes, if one container uses all available CPU and memory, other containers suffer.

Resource limits prevent one container from starving others!


📋 What We'll Build Today

We'll create a Pod with specific CPU and memory requests and limits:

Resource Request Limit
CPU 100 millicores (0.1 CPU) 100 millicores (0.1 CPU)
Memory 15 MiB 20 MiB

Our Pod:

  • Name: httpd-pod
  • Container: httpd-container
  • Image: httpd:latest (Apache HTTP Server)

📖 Understanding Resource Units

CPU Units

Think of CPU like a highway with lanes:

Unit Value Analogy
1 1000m Full CPU core (like a 4-lane highway)
500m 500 millicores Half a CPU core (like 2 lanes)
100m 100 millicores 1/10 of a CPU core (like a single lane)

The m stands for "millicores" – 1000m = 1 CPU core.

Memory Units

Think of memory like a measuring cup:

Unit Bytes Analogy
1Ki 1024 bytes A small spoonful
1Mi 1,048,576 bytes (1 MB) A medium cup
1Gi 1,073,741,824 bytes (1 GB) A large pitcher

🔧 Step-by-Step Guide

Step 1: Check Your Cluster

First, let's make sure our cluster is ready:

kubectl cluster-info
kubectl get nodes
Enter fullscreen mode Exit fullscreen mode

Expected Output:

Kubernetes control plane is running at https://127.0.0.1:6443

NAME        STATUS   ROLES           AGE   VERSION
jump-host   Ready    control-plane   21m   v1.34.1+k3s1
Enter fullscreen mode Exit fullscreen mode

Step 2: Create the YAML Manifest

Let's create a file that describes our Pod:

vi httpd-pod.yaml
Enter fullscreen mode Exit fullscreen mode

Here's the full YAML:

apiVersion: v1
kind: Pod
metadata:
  name: httpd-pod
  labels:
    app: httpd
spec:
  containers:
  - name: httpd-container
    image: httpd:latest
    ports:
    - containerPort: 80
    resources:
      requests:
        memory: "15Mi"
        cpu: "100m"
      limits:
        memory: "20Mi"
        cpu: "100m"
Enter fullscreen mode Exit fullscreen mode

📖 Breaking Down the YAML

┌─────────────────────────────────────────────────────────────┐
│                    Pod: httpd-pod                          │
│  ┌───────────────────────────────────────────────────────┐ │
│  │  Container: httpd-container                           │ │
│  │  Image: httpd:latest                                 │ │
│  │  Port: 80                                            │ │
│  │                                                      │ │
│  │  ┌────────────────────────────────────────────────┐  │ │
│  │  │  Resources                                     │  │ │
│  │  │  Requests:   CPU: 100m   Memory: 15Mi        │  │ │
│  │  │  Limits:     CPU: 100m   Memory: 20Mi        │  │ │
│  │  └────────────────────────────────────────────────┘  │ │
│  └───────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

What each section means:

  • apiVersion: v1 – Using the stable Kubernetes API
  • kind: Pod – We're creating a Pod
  • metadata.name – The Pod's name
  • spec.containers – Our container definition
  • resources.requests – Minimum resources guaranteed
  • resources.limits – Maximum resources allowed

Step 3: Create the Pod

Now let's create our Pod using the YAML file:

kubectl apply -f httpd-pod.yaml
Enter fullscreen mode Exit fullscreen mode

Output:

pod/httpd-pod created
Enter fullscreen mode Exit fullscreen mode

Step 4: Verify the Pod

kubectl get pods
Enter fullscreen mode Exit fullscreen mode

Output:

NAME         READY   STATUS    RESTARTS   AGE
httpd-pod    1/1     Running   0          30s
Enter fullscreen mode Exit fullscreen mode
kubectl describe pod httpd-pod
Enter fullscreen mode Exit fullscreen mode

Key output showing resource limits:

Containers:
  httpd-container:
    ...
    Limits:
      cpu:     100m
      memory:  20Mi
    Requests:
      cpu:     100m
      memory:  15Mi
Enter fullscreen mode Exit fullscreen mode

Step 5: Verify Resource Usage (Optional)

If you have kubectl top installed:

kubectl top pod httpd-pod
Enter fullscreen mode Exit fullscreen mode

Output:

NAME         CPU(cores)   MEMORY(bytes)
httpd-pod    1m           8Mi
Enter fullscreen mode Exit fullscreen mode

📝 Complete Commands Summary

# 1. Create the YAML file
cat > httpd-pod.yaml << 'EOF'
apiVersion: v1
kind: Pod
metadata:
  name: httpd-pod
  labels:
    app: httpd
spec:
  containers:
  - name: httpd-container
    image: httpd:latest
    ports:
    - containerPort: 80
    resources:
      requests:
        memory: "15Mi"
        cpu: "100m"
      limits:
        memory: "20Mi"
        cpu: "100m"
EOF

# 2. Create the Pod
kubectl apply -f httpd-pod.yaml

# 3. Verify the Pod
kubectl get pods
kubectl describe pod httpd-pod

# 4. Check resource usage (if available)
kubectl top pod httpd-pod
Enter fullscreen mode Exit fullscreen mode

🎯 Understanding Resource Requests vs Limits

The Two Types of Resource Settings

Setting What It Does Analogy
Request Minimum resources guaranteed A reserved seat on a train
Limit Maximum resources allowed The maximum speed the train can go

Three QoS (Quality of Service) Classes

Kubernetes assigns a QoS class based on how you set requests and limits:

QoS Class How to Get It Priority
Guaranteed Requests = Limits for all resources Highest 🥇
Burstable Requests < Limits Medium 🥈
BestEffort No requests or limits set Lowest 🥉

Our Pod has requests = limits for both CPU and memory, so it gets Guaranteed QoS – the highest priority!

┌─────────────────────────────────────────────────────────────┐
│  QoS Class: Guaranteed (Highest Priority)                  │
│                                                             │
│  ┌─────────────┐  ┌─────────────┐                          │
│  │   CPU       │  │   Memory    │                          │
│  │ Request:100m│  │ Request:15Mi│                          │
│  │ Limit: 100m │  │ Limit: 20Mi │                          │
│  │  (Equal)    │  │  (Equal)    │                          │
│  └─────────────┘  └─────────────┘                          │
│                                                             │
│  Result: The pod is never evicted due to resource pressure │
└─────────────────────────────────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

🛠️ What Happens When Resources Are Exceeded?

CPU Exceeded

  • Container throttled (slowed down)
  • Not killed, just limited

Memory Exceeded

  • Container terminated (killed)
  • Restarts if restartPolicy allows
Memory Usage
    ▲
    │    ┌─────────┐
    │    │  Limit  │  ← OOM Killer activates here
    │    │ (20Mi)  │
    │    ├─────────┤
    │    │         │
    │    │  Pod    │  ← Normal operation
    │    │         │
    │    ├─────────┤
    │    │ Request │  ← Minimum guaranteed
    │    │ (15Mi)  │
    │    └─────────┘
    │
    └──────────────────────▶
Enter fullscreen mode Exit fullscreen mode

📊 Comparison: Without vs With Resource Limits

Feature No Resource Limits With Resource Limits
Scheduling Scheduler places anywhere Scheduler places on nodes with enough resources
Node Overload Can overload nodes Prevents overload
Pod Eviction Can be evicted first Higher priority
Resource Guarantee None Guaranteed minimum
Stability Unpredictable ✅ Predictable
Best Practice ❌ No ✅ Yes

🎯 Key Takeaways

Why You Should Always Set Resource Limits

  1. Prevent Resource Starvation – No container takes everything
  2. Better Scheduling – Scheduler knows resource needs
  3. Cluster Stability – Prevents cascading failures
  4. Cost Optimization – Better resource utilization
  5. Predictable Performance – Know your application's footprint

Best Practices

  1. Always set both requests and limits
  2. Keep requests and limits equal for Guaranteed QoS
  3. Monitor resource usage with kubectl top
  4. Adjust based on actual usage
  5. Use Horizontal Pod Autoscaling for dynamic scaling

🔧 Troubleshooting Common Issues

Issue 1: Pod Stuck in Pending

# Check why
kubectl describe pod httpd-pod

# Common reason: Not enough resources on any node
Enter fullscreen mode Exit fullscreen mode

Issue 2: Pod Gets Killed (OOM)

# Check pod status
kubectl get pods

# Check if it was OOM killed
kubectl describe pod httpd-pod | grep -i "oom"
Enter fullscreen mode Exit fullscreen mode

Issue 3: Pod Constantly Restarting

# Check logs
kubectl logs httpd-pod

# Check previous logs
kubectl logs httpd-pod --previous
Enter fullscreen mode Exit fullscreen mode

📊 Quick Reference

Resource Units Cheat Sheet

CPU Memory
100m = 0.1 CPU 1Mi = 1 MB
500m = 0.5 CPU 10Mi = 10 MB
1000m = 1 CPU 1Gi = 1 GB

Useful Commands

# Get pod resource limits
kubectl describe pod httpd-pod | grep -A 10 "Limits"

# Get resource usage
kubectl top pod httpd-pod

# Get node resource allocation
kubectl describe nodes | grep -A 5 "Allocated resources"
Enter fullscreen mode Exit fullscreen mode

🎉 You Did It!

You've successfully created a Kubernetes Pod with resource requests and limits. This is a crucial skill for:

  • Production deployments – Ensure stability
  • Multi-tenant clusters – Prevent noisy neighbors
  • Cost optimization – Efficient resource usage
  • Performance tuning – Predictable application behavior

Top comments (0)