Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 13

Managing Container Resources in Pods

Recommended resources

Hello! Welcome back to our journey through Kubernetes.

In the previous lesson, you learned the foundational skill of creating a Pod by writing a declarative YAML manifest. We defined the apiVersion, kind, metadata, and spec, and successfully deployed a single-container nginx Pod. However, we left out a crucial piece of the puzzle: we didn't tell Kubernetes how much CPU or memory our application needs.

This is a critical oversight in a real-world production environment. As a Platform Engineer, your responsibility is to ensure cluster stability and efficient resource utilization. A Pod without resource constraints is a liability—it could consume excessive resources, impacting other applications on the same node, or even crash the node itself.

Today, we will fix that. This lesson focuses on configuring resource requests and limits for your containers. You will learn how to declare the resources your application needs, enabling Kubernetes to make intelligent scheduling decisions and enforce boundaries to maintain a healthy cluster.

1. Why We Need Resource Management

Before diving into the YAML, it's essential to understand the "why." What problems do resource requests and limits solve? In short, they bring predictability and stability to your cluster.

  • Requests are about scheduling. They guarantee that your Pod will have the minimum resources it needs to run. The Kubernetes scheduler uses this information to find a node with enough available capacity.
  • Limits are about runtime enforcement. They prevent a container from consuming more than its allocated share of resources, protecting the node and other workloads from a single "noisy neighbor."

The following video provides an excellent analogy, comparing resource management to personal budgeting, and explains the core problems solved by this mechanism.

All You Need to Know in 12 Minutes: Pods' Requests and Limits in Kubernetes

To understand the motivation behind resource management, watch the first part of the video 'All You Need to Know in 12 Minutes: Pods' Requests and Limits' by The Good Guy. It clearly explains the need for resource controls from both an application and a cluster-wide perspective.

Watch from the beginning to 04:04. Focus on the reasons for managing resources: ensuring your application has enough to run, preventing it from consuming too much, managing costs, and avoiding the 'noisy neighbor' problem.

This diagram provides a great visual summary of how these concepts fit together on a node.

Kubernetes Resource Requests and Limits Visual Explanation
This diagram illustrates how a node's total capacity is divided. A portion is reserved for the system (`kube-reserved`), leaving the `Allocatable` capacity for your Pods. The scheduler uses `requests` to place Pods, ensuring the sum of requests fits within the allocatable capacity. `Limits` act as a hard cap on consumption during runtime.

2. Configuring Requests and Limits in a Pod Manifest

Now, let's see how to implement this in a manifest. Resource requests and limits are defined within the spec of a container, inside a resources block.

apiVersion: v1
kind: Pod
metadata:
  name: frontend
spec:
  containers:
  - name: app
    image: images.my-company.example/app:v4
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"

To properly configure these values, you must understand the units Kubernetes uses.

Resource Management for Pods and Containers

The official Kubernetes documentation, 'Resource Management for Pods and Containers,' is the authoritative source for understanding the syntax and units. Please read the following sections to get the details right.

Please read the sections 'Resource requests and limits of Pod and container', 'Resource units in Kubernetes', and 'Container resources example'. Pay close attention to: The YAML path: spec.containers[].resources. CPU units: m for 'millicpu' (e.g., 500m is half a CPU core). Memory units: Power-of-two (Ki, Mi, Gi) vs. power-of-ten (k, M, G) suffixes, and the importance of case sensitivity.

Key Points on Units:

  • CPU: Measured in "Kubernetes CPUs." 1 equals one physical or virtual core. You will most often use millicpus, written as 100m (100 millicpus = 0.1 CPU).
  • Memory: Measured in bytes. It's crucial to use the correct suffix. 100m of memory is 0.1 bytes (a common mistake!), whereas 100Mi is 100 mebibytes. For clarity and consistency, always use the Mi or Gi suffixes for memory.
Test your understanding!

You have a container that requires at least 1.5 CPU cores and 2 gibibytes of memory to start. You want to cap its usage at 2 CPU cores and 4 gibibytes of memory. Which of the following resources blocks is correct?

A)

resources:
  requests:
    cpu: "1.5"
    memory: "2G"
  limits:
    cpu: "2"
    memory: "4G"

B)

resources:
  requests:
    cpu: "1500m"
    memory: "2Gi"
  limits:
    cpu: "2000m"
    memory: "4Gi"

C)

resources:
  requests:
    cpu: "150m"
    memory: "2Mi"
  limits:
    cpu: "200m"
    memory: "4Mi"
Show answer

Answer B is correct.

  • 1.5 CPU cores is equivalent to 1500m.
  • 2 gibibytes is correctly written as 2Gi.
  • 2G in option A represents 2 gigabytes, not gibibytes, which is a subtle but important difference.
  • Option C uses 150m (0.15 cores) and Mi (mebibytes), which are incorrect magnitudes.

3. Enforcement: What Happens When Limits Are Reached?

Defining requests and limits is only half the story. As a Platform Engineer, you need to know what happens when a container misbehaves. Kubernetes enforces CPU and memory limits differently.

  • CPU Limit: If a container tries to use more CPU than its limit, it will be throttled. It won't be killed, but its performance will be artificially capped, slowing it down.
  • Memory Limit: If a container tries to allocate memory beyond its limit, it will be terminated by the operating system. You will see the Pod's status as OOMKilled (Out Of Memory Killed), and Kubernetes will likely restart it.

The following video demonstrates these scenarios practically. It shows what happens when a Pod operates within its limits, what happens when it exceeds its memory limit, and what happens when it requests more resources than any node can provide.

Day 16/40 - Kubernetes Requests and Limits - CKA Full Course 2025

Let's watch a practical demonstration from 'Tech Tutorials with Piyush'. This video uses a special 'stress' container image to simulate resource consumption and shows the real-world consequences of your configuration.

Watch the following segments: Operating within limits (07:48 - 12:27): Observe how a Pod runs successfully when its memory usage is between its request and limit. Exceeding the memory limit (12:27 - 14:31): See the Pod status change to OOMKilled when it tries to use more memory than its limit. Requesting too much (14:31 - 16:04): Notice the Pod gets stuck in the Pending state with an Insufficient memory event because no node can satisfy its high request.

When you encounter these issues, kubectl describe pod <pod-name> is your best friend. As shown in the video and the official documentation's troubleshooting section, the "Events" section at the bottom of the output will tell you exactly why a Pod is Pending or why it was last terminated.


4. Quality of Service (QoS) Classes

Based on the requests and limits you set, Kubernetes automatically assigns one of three Quality of Service (QoS) classes to your Pod. This class determines how Kubernetes prioritizes your Pod, especially when a node is under pressure and needs to evict Pods to reclaim resources.

  1. Guaranteed: Highest priority. Assigned when requests and limits are set and are equal for both CPU and memory on all containers. These Pods are the last to be killed.
  2. Burstable: Medium priority. Assigned when requests and limits are set, but they are not equal for at least one resource. These Pods can "burst" to use more resources up to their limit if available.
  3. BestEffort: Lowest priority. Assigned when no requests or limits are set at all. These are the first Pods to be evicted when a node is low on resources.

Understanding these classes is important for designing resilient systems. Critical system components should run with a Guaranteed QoS.

All You Need to Know in 12 Minutes: Pods' Requests and Limits in Kubernetes

The video from 'The Good Guy' provides a concise explanation of these three QoS classes.

Watch from 09:14 to 10:57 to understand how your resource settings determine the Pod's QoS class and its eviction priority.

As a best practice, avoid running production workloads with the BestEffort QoS class. Always define requests to ensure your application gets the resources it needs. For memory, it's often recommended to set the request and limit to the same value (Guaranteed QoS for memory) to create the most predictable behavior. The use of CPU limits is more debated, as throttling can sometimes hide performance issues, but they are a useful tool for preventing noisy neighbors.


Conclusion

You have now equipped your Pods with one of the most critical features for production readiness: resource management. By setting requests and limits, you are providing essential information to Kubernetes that enables it to be a more effective orchestrator.

Key Takeaways:

  • Requests are minimum guarantees used for scheduling.
  • Limits are maximum caps enforced at runtime.
  • Exceeding a CPU limit leads to throttling.
  • Exceeding a memory limit leads to an OOMKilled termination.
  • Resource settings determine a Pod's QoS class (Guaranteed, Burstable, BestEffort), which affects its eviction priority.
  • Always use explicit units like m for CPU and Mi/Gi for memory.

Our Pod is now more robust. It has a defined resource profile. But what if the application inside the container crashes or becomes unresponsive, even while staying within its resource limits? Kubernetes wouldn't know anything is wrong. In our next lesson, we will solve this by configuring liveness and readiness probes, which allow Kubernetes to check the health of the actual application.