Kubernetes Resource Limits: A Practical Guide

2 min read

Resource limits in Kubernetes are one of those things that seem optional until they are very much not. This post covers the practical patterns for setting CPU and memory limits on workloads running in production clusters.

Why Limits Matter

Without resource limits, a single misbehaving pod can consume all CPU time on a node, starving every other workload. Kubernetes calls this the "noisy neighbor" problem. Setting limits gives the scheduler the information it needs to enforce fair sharing.

Setting CPU and Memory Limits

Here is a deployment with both requests and limits set:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  template:
    spec:
      containers:
        - name: my-app
          image: my-app:latest
          resources:
            requests:
              cpu: "250m"
              memory: "128Mi"
            limits:
              cpu: "500m"
              memory: "256Mi"

The requests value is what Kubernetes uses for scheduling — it reserves that capacity on the node. The limits value is the ceiling. For CPU, exceeding the limit results in throttling; for memory, exceeding the limit results in the container being OOM-killed.

Checking Current Usage

Use kubectl top to see actual consumption before setting limits:

kubectl top pods -n my-namespace
kubectl top nodes

Match your limits to the 95th-percentile usage observed over several days, not the peak spike.

LimitRange for Namespace Defaults

Apply a LimitRange object to enforce defaults at the namespace level:

apiVersion: v1
kind: LimitRange
metadata:
  name: default-limits
  namespace: my-namespace
spec:
  limits:
    - default:
        cpu: "500m"
        memory: "256Mi"
      defaultRequest:
        cpu: "100m"
        memory: "64Mi"
      type: Container

With this in place, any container that omits resources gets the namespace defaults automatically — no forgotten limits.

Summary

Set requests and limits on every workload, use kubectl top to calibrate them from observed usage, and enforce namespace defaults with LimitRange. Your cluster will thank you.