Kubernetes capacity planning sets how much node capacity a cluster holds before the load needs it, and at what price: which part is paid as baseline with a commitment, which part stands ready as headroom on demand, and which part comes from spot or on-demand only when needed. Headroom is paid capacity without work, that is idle, but idle with a purpose, and it belongs on its own cost line rather than disappearing into the rest of the idle. This page describes headroom as a cost line, the buffers clusters are over-provisioned with and the autoscaler's limits, the split into baseline and burst, the signals to plan from, and a worked example of baseline plus burst. Choosing and sizing the commitments themselves is commitment strategy, their ongoing use commitment coverage and utilisation.

How it works

A cluster with nodes runs on two clocks. A pod needs seconds to start, a new node minutes, and between the two lies the time in which new replicas are Pending (HPA, VPA, KEDA and the bill). Headroom closes that gap: free allocatable capacity on running nodes a pod fits into at once. The Cluster Autoscaler keeps no headroom by itself; it adds nodes only once a pod is unschedulable. An over-provisioning buffer forces it: a deployment of placeholder pods with a low PriorityClass that reserve capacity and are preempted as soon as a real pod needs it, whereupon the autoscaler adds a node for the preempted placeholders. The buffer's size is the headroom's size and thereby a number on the bill. Karpenter offers the same through a NodePool with minimum capacity or placeholder pods, GKE through its autoscaler's balanced profile, which keeps reserves for fast starts.

Three things cap capacity from above: the pool's maximum size or the NodePool's limits, the account's quotas per instance family and region, and the availability of spot capacity. Each is a point at which pods stay Pending without any bill rising; they are therefore planned, not discovered at the load test.

The split follows the shape of the load. The baseline is the capacity occupied in every hour of the month; it is paid with a commitment, at AWS through Savings Plans or Reserved Instances, at Azure through reservations or savings plans, at Google Cloud through committed use discounts. The burst above it is the capacity occupied only hours a day; it comes from a spot pool where the workloads tolerate interruptions, otherwise on demand. The headroom sits between the two and is paid on demand, because it moves with the baseline and still has to be removable at any time.

The load over a monthThe baseline: capacity occupiedin every hourThe headroom: free capacitykept for pods to start at onceThe burst: capacity occupiedonly hours a dayA commitment: Savings Plans,reservations or committeduse discountsOn demand: it moveswith the baselineSpot where the workloadstolerate interruption,otherwise on demand
The baseline runs on a commitment, the headroom above it on demand, and the burst on spot where the workloads tolerate interruption

Planning draws on four signals the cluster provides. The sum of requests per pool over time, compared with allocatable capacity, shows the baseline and the peaks; measured usage beneath it shows how much of the requests is idle inside the workloads; the number and duration of Pending pods shows where the headroom was too small; the start time of new nodes shows how large it has to be. Without those four, capacity planning stays a guess, and the autoscaler corrects the guess with a delay.

What it means for your cost

Headroom costs the on-demand price of the nodes it occupies, every hour, and its benefit is the time pods do not wait. It is therefore a cost line with an owner, the cluster operator, and with a number that is justified: this many nodes, because a node takes this many minutes and the load rises this much in that time. Headroom that is never occupied is too large; headroom under which pods are regularly Pending is too small.

headroom neveroccupiedpods regularlyPendingpods start at once,little left overHeadroom: free capacity on runningnodes at the on-demand price,owned by the cluster operatorIts number justified: this manynodes, because a node takes thismany minutes and the load risesthis much in that timeWhat does thecluster show?Too largeToo smallRight
Headroom is a cost line with an owner and a justified size: never occupied means too large, pods pending means too small

The commitment covers the baseline and only that. A commitment sized to the peak sits unused two thirds of the day; one tied to an instance family Karpenter no longer picks likewise (Cluster autoscaler, Karpenter and node provisioning). A planned cluster's bill thereby has three lines: baseline at the commitment price, headroom at the on-demand price, burst at the spot or on-demand price; a fourth, idle without purpose, is meant to be small. Which nodes carry the lines is decided by the node pool: one pool for the baseline with a type that can be reserved, one for the burst with many permitted types.

Where it goes wrong

  • Headroom hidden in idle. Symptom: the idle share is reported as waste although it was planned. Cause: the buffer is not shown as its own line; headroom and packing waste sit in one number.
  • Commitment sized to the peak. Symptom: the Savings Plan's utilisation is high by day and low by night. Cause: the commitment was sized to peak load, not to the hour with the least load.
  • Pending despite the autoscaler. Symptom: pods wait for minutes although the pool may scale. Cause: no headroom, and a node's start time exceeds the length of the peak.
  • Quota as the limit. Symptom: the autoscaler reports errors, new nodes do not come. Cause: the family's vCPU quota in the region is reached; the pool's maximum was set above it.
  • Buffer without priority. Symptom: the placeholder pods are not preempted, real pods stay Pending. Cause: the placeholders' PriorityClass is not lower than the workloads'.
  • Spot for the baseline. Symptom: the baseline fails at spot interruptions. Cause: spot was chosen for the part that must always run; it belongs in the burst.

Example

List prices read on 2026-10-21 from the AWS price list for Frankfurt (eu-central-1), Linux: m6i.large (2 vCPU, 8 GiB) on demand USD 0.115 per hour; as a standard Reserved Instance over one year with no upfront payment USD 0.07607 per hour.

A cluster occupies six m6i.large in every hour, up to ten in peaks of four hours on weekdays. Baseline: six nodes on the reservation, 6 × 0.07607 × 730 = USD 333.19 a month. Headroom: one node on demand, 0.115 × 730 = USD 83.95. Burst: up to four nodes in about 20 percent of the hours, on demand 4 × 0.115 × 146 = USD 67.16, or less on spot. Together USD 484.30 a month, three lines with one reason each. The same cluster with eleven nodes around the clock on demand, so that no pod ever waits, costs 11 × 0.115 × 730 = USD 923.45; six reserved nodes without headroom cost USD 333.19, and every peak starts with waiting pods until the autoscaler has caught up.

Sources

Read on 2026-10-21. Cluster Autoscaler FAQ, Kubernetes pod priority and preemption, Karpenter NodePools, Google Cloud GKE Cluster Autoscaler, AWS Reserved Instances for EC2, AWS Price List bulk API, offer AmazonEC2, eu-central-1.