Skip to main content
RunBook Academy

KubernetesCIX · LimitRangeLimitRange

Container defaults — the foundation of resource accounting

Advanced⏱ ~16 minkubectl

What you'll learn

  • Configure container defaults (default, defaultRequest)
  • Apply the overcommit strategy via defaults
  • Reason about the operational impact
  • Apply the operational discipline of setting sensible defaults

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.

Container defaults in LimitRange ensure every container is declared. This lesson walks the defaults, the admission behaviour, the overcommit strategy, and the discipline.

The default fields

apiVersion: v1
kind: LimitRange
metadata:
  name: container-defaults
  namespace: tenant-a-prod
spec:
  limits:
    - type: Container
      default:
        cpu: 500m
        memory: 512Mi
      defaultRequest:
        cpu: 100m
        memory: 128Mi

The default fields:

  • default. Limits applied to containers that don’t specify them. If a container has no limits, the admission controller adds the defaults.
  • defaultRequest. Requests applied to containers that don’t specify them. If a container has no requests, the admission controller adds the defaults.

The admission controller’s behaviour:

  1. The user submits a Pod.
  2. The LimitRange admission plugin checks each container.
  3. If a container has no requests, the defaultRequest is applied.
  4. If a container has no limits, the default is applied.
  5. The Pod is stored with the applied defaults.

The overcommit strategy

flowchart LR
    A[default] --> B[500m CPU]
    C[defaultRequest] --> D[100m CPU]
    B --> E["Limit: 500m"]
    D --> F["Request: 100m"]
    E --> G["Overcommit ratio: 5x"]
    F --> G

The overcommit strategy:

  • default at 500m CPU. The container can use up to 500m.
  • defaultRequest at 100m CPU. The scheduler reserves 100m.
  • Overcommit ratio: 5x. 5 containers with default requests can fit on a node that has 1 container’s worth of CPU at full limits.

The trade-off:

  • High overcommit. More containers per node; lower density; bursts more likely to throttle.
  • Low overcommit. Fewer containers per node; higher density; bursts less likely.

The default ratio

flowchart TD
    A["Default ratio"] --> B{"Ratio"}
    B -->|"1:1 (default = defaultRequest)"| C["Guaranteed QoS"]
    B -->|"2:1 to 5:1"| D["Burstable QoS"]
    B -->|"> 5:1"| E["BestEffort QoS if no requests; high overcommit"]

The default-to-request ratio determines the QoS:

  • 1:1. Default = defaultRequest. Containers are Guaranteed QoS.
  • 2:1 to 5:1. Default > defaultRequest. Containers are Burstable QoS.
  • > 5:1. Very high overcommit. Containers may frequently throttle.

Most production deployments use a 2:1 to 5:1 ratio.

Observing defaults

kubectl describe pod myapp-pod -n tenant-a-prod
Containers:
  app:
    Image:    myapp
    Limits:
      cpu:     500m       # from default
      memory:  512Mi      # from default
    Requests:
      cpu:     100m       # from defaultRequest
      memory:  128Mi      # from defaultRequest
    ...

The Pod spec reflects the applied defaults. If the container originally had no resources, the defaults are now visible.

Setting sensible defaults

flowchart LR
    A[Setting defaults] --> B[Observe typical workload sizes]
    B --> C[Set default at typical]
    C --> D[Set defaultRequest at 50% of default]
    D --> E[Test with new Pods]
    E --> F["Adjust if too tight/loose"]

The discipline:

  1. Observe typical workload sizes. Use kubectl top or metrics to determine typical CPU and memory.
  2. Set default at typical. 500m CPU, 512Mi memory is a reasonable starting point for many workloads.
  3. Set defaultRequest at 50% of default. 100m CPU, 128Mi memory.
  4. Test with new Pods. Verify the defaults produce the expected QoS.
  5. Adjust if too tight/loose. Quarterly review.

Quiz

Knowledge check · 4 questions

  1. Q1. When are LimitRange defaults applied to a container?

  2. Q2. Changing a LimitRange updates the defaults on Pods that were already created.

  3. Q3. A Java service starts being OOMKilled the day after a LimitRange is introduced; explain the link and fix it properly.

    `billing-worker` in `finance-prod` ran for a year with no `resources` block. A LimitRange with `default.memory: 512Mi` and `defaultRequest.memory: 128Mi` was applied yesterday, and the Deployment was rolled this morning. `kubectl describe pod` now shows `Last State: Terminated, Reason: OOMKilled, Exit Code: 137` with three restarts in twenty minutes, and the container's Limits section reads `memory: 512Mi`. The JVM is started without any heap flag.

  4. Q4. A Container LimitRange sets `default.memory: 512Mi` and `defaultRequest.memory: 128Mi`. A container declares `limits.memory: 1Gi` and no requests. What memory request does it end up with?

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

The operational discipline

Container defaults in production rest on five non-negotiable elements:

  • Set defaults for every namespace. No namespace should be without defaults.
  • Match defaults to typical workloads. 500m/512Mi is a starting point; adjust based on observation.
  • Set defaultRequest at 50% of default. Allow bursting.
  • Verify defaults in practice. Quarterly: create a Pod without resources; verify defaults are applied.
  • Document the defaults. The runbook lists each namespace’s defaults.

Defaults are the foundation of resource accounting. Without defaults, the quota is meaningless.