Skip to main content
RunBook Academy

KubernetesCIX · LimitRangeLimitRange

LimitRange anti-patterns — the operational discipline

Advanced⏱ ~16 minkubectl

What you'll learn

  • Identify the most common LimitRange anti-patterns
  • Explain why each anti-pattern is a problem
  • Apply the fixes for each anti-pattern
  • Build the operational discipline of avoiding LimitRange anti-patterns

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.

LimitRange anti-patterns are the most common mistakes when configuring per-namespace resource bounds. This lesson walks the anti-patterns, the fixes, and the operational discipline.

Anti-pattern 1: No LimitRange

flowchart LR
    A[ResourceQuota] --> B[Bounds sum]
    C["LimitRange: missing"] --> D[No defaults]
    B --> E[Quota meaningless for undeclared Pods]

The intent is “the quota is enough”; the result is that the quota cannot enforce on undeclared Pods.

The fix is to always apply LimitRange alongside ResourceQuota. The LimitRange provides defaults; the quota provides the sum.

Anti-pattern 2: Max too tight

# Anti-pattern
limits:
  - type: Container
    max:
      cpu: 100m  # too tight

The intent is “control CPU usage”; the result is that no real workload fits.

The fix: set max based on typical workload characteristics. 2 cores is a reasonable starting point for many workloads.

Anti-pattern 3: Max too loose

# Anti-pattern
limits:
  - type: Container
    max:
      cpu: 64  # too loose

The intent is “never block”; the result is that a single container can monopolise the quota.

The fix: set max based on the quota. With a 32-core quota, max should be ≤ 32 cores; with realistic multi-tenancy, max should be ≤ 4 cores.

Anti-pattern 4: Min too high

# Anti-pattern
limits:
  - type: Container
    min:
      cpu: 4  # too high
      memory: 8Gi

The intent is “ensure meaningful declarations”; the result is that small workloads are rejected.

The fix: set min based on the smallest realistic workload. 50m CPU, 64Mi memory is a reasonable minimum.

Anti-pattern 5: No PVC max

# Anti-pattern: ResourceQuota on storage but no PVC max
apiVersion: v1
kind: ResourceQuota
metadata:
  name: storage-quota
spec:
  hard:
    requests.storage: 1Ti
# No LimitRange on PVCs

The intent is “bound storage”; the result is that a single 1 TiB PVC is allowed (consuming the entire quota in one request).

The fix: add a PVC LimitRange with max 100Gi (or whatever is appropriate for the workload).

Anti-pattern 6: Extreme maxLimitRequestRatio

# Anti-pattern
limits:
  - type: Container
    maxLimitRequestRatio:
      cpu: "100"  # extreme overcommit
      memory: "10"

The intent is “allow bursting”; the result is extreme overcommit and frequent throttling.

The fix: set maxLimitRequestRatio based on the workload characteristics. CPU can typically be 4x; memory should be tighter (2x).

Anti-pattern 7: No defaultRequest

# Anti-pattern
limits:
  - type: Container
    default:
      cpu: 500m
    # No defaultRequest

The intent is “set limits”; the result is that the quota’s requests check is bypassed for Pods that don’t declare requests.

The fix: always set both default and defaultRequest. A workload without requests is invisible to the quota’s requests bound.

Quiz

Knowledge check · 4 questions

  1. Q1. What is the consequence of setting LimitRange `max` too tight?

  2. Q2. Tightening a LimitRange affects only objects created after the change.

  3. Q3. A LimitRange minimum set too high has pushed a namespace's reserved CPU far above what its workloads use; unwind it.

    Someone set `min.cpu: 1` on the `Container` entry in `tools-prod` to stop teams under-declaring. Two weeks later, a Prometheus exporter sidecar and four small CronJobs had been rejected with `minimum cpu usage per Container is 1, but request is 50m`, and their owners raised each request to a full core. `kubectl describe resourcequota -n tools-prod` now shows `requests.cpu 38 / 40`, while `kubectl top pods -n tools-prod` totals under 6 cores.

  4. Q4. Why is `maxLimitRequestRatio` conventionally tighter for memory than for CPU, and what is the observable failure of each when it is set too loose?

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

The operational discipline

LimitRange anti-patterns in production rest on five non-negotiable elements:

  • Apply LimitRange alongside ResourceQuota. No exceptions.
  • Set max based on quota and workload. Tight enough to protect, loose enough to allow typical workloads.
  • Set min based on smallest workload. Don’t reject small workloads.
  • Set PVC max. Prevent oversized PVCs.
  • Tune maxLimitRequestRatio. Tighter for memory than CPU.

LimitRange is the declaration enforcement. The discipline is to set limits deliberately and consistently across all namespaces.