High CPU throttling — containers starved by CPU limits
High response latency with low CPU saturation on the node
Focused incident mode — strips away everything but this runbook.
Symptoms
- High response latency with low CPU saturation on the node
- container_cpu_cfs_throttled_periods rising sharply
- Throughput collapses at random traffic peaks
Since Kubernetes 1.20+ CPU limits throttle at 100ms windows and can cause duplicates vs memory OOM; many teams ship requests-only CPU.
Evidence to grab
Collect these artifacts before you change anything — they prove (or rule out) each cause.
Throttling metric
sum(rate(container_cpu_cfs_throttled_periods_total[5m])) by (namespace, pod)CPU limit and usage
kubectl get deploy <name> -n <namespace> -o jsonpath='{.spec.template.spec.containers[0].resources}'
Diagnostic flow
Run the steps in order, marking each claim confirmed or refuted. The evidence you gather feeds the ranked causes below.
Guided decision tree is ready.
Steps with commands, expected output, and pass/fail branches.
Ranked root causes
Evidence checklist
- Throttling ratio (throttled/run periods) high while server under load
- usage == limit at the busy period
Confirm before fixing
kubectl top pod <pod> -n <namespace> --containersCompare CPU usage to limit
Fix
kubectl set resources deployment/<deploy> --limits=cpu=<new> --requests=cpu=<new>Raise the limit with headroom
Resolution runbook
Apply from top to bottom after the cause is confirmed. Review every command before running it — risk tags are shown on each.
kubectl top pod <pod> -n <namespace> --containersUsage vs limit
kubectl get deploy <name> -n <namespace> -o jsonpath='{.spec.template.spec.containers[0].resources}'Current limits
kubectl set resources deployment/<deploy> --limits=cpu=<new> --requests=cpu=<new>Right-size the limit
Prevention
- Use requests-only for CPU-bound bursty services (avoid hard throttling).
- Alert on throttled_periods / run_periods ratio > 0.1.
- Profile CPU headroom before setting limits in the first place.
Related runbooks
Same stack, same failure family — worth a skim.
Commands marked READ CHANGE DESTRUCTIVE — never run DESTRUCTIVE commands against production data you cannot restore. Copy → verify → execute.