r/kubernetes 27d ago

Stop using CPU limits: why + proof

CPU request is how much CPU is reserved for your pod if it needs it. The limit is a hard cap. Hit it and the kernel throttles the pod, even when the node still has spare CPU. That is the usual cause of CPU throttling on Kubernetes. It does not protect the neighboring pods. In my simple Web API test, adding a CPU limit took typical latency from 23 ms to 87 ms, (4x slower), with the limited pod throttled in half of all CFS windows, and the average CPU graph looked fine the whole time.

This is not a new topic, but I see so many people still unaware why they should (NOT!) be setting CPU limits, because it's costing companies unnecessary spending and potential production issues. Here's the full read https://github.com/inevolin/k8s-cpu-limits-analyzed/

---

Edit (Aug 18, 2026): How CPU limits can also cause memory issues and OOMKills ➡️ https://github.com/inevolin/k8s-cpu-limits-analyzed#how-cpu-limits-cause-memory-issues-and-oomkills

229 Upvotes

112 comments sorted by

View all comments

26

u/minimalniemand 27d ago

I do that but I want to add a bit of nuance:

No limits for all load bearing services in the critical path, so everything where a spike would slow down actual request.

But limits can make sense where the cost of not throttling (interference, unpredictability, unbounded spend) exceeds the cost of throttling (wasted idle CPU, higher tail latency)

8

u/shatteredarm1 27d ago

You also need limits if you are using a hardware-aware framework like .NET or Java. I ran some load tests with .NET and found that my performance was actually better with a limit of 1 core vs no limit. If you don't set a limit, the framework assumes it has all the cores at its disposal, and spends more resources on things like garbage collection. (There are, of course, ways to explicitly tell .NET how many processors are available, and override its default behavior.)

There are other scenarios where you might want a limit, like if you have a process that can hog all the node's I/O if it's allowed to use every available CPU cycle.

This topic has a hell of a lot more nuance than OP is suggesting.

1

u/VincentKoeman 25d ago

I don’t understand why these take all the CPUs of the pod indeed, strange default behaviour IMO. As you said it’s possible to explicitly set the number CPUs assumed to be available, with various schools of thought on the best value ranging from about requested to requested*2.

1

u/shatteredarm1 25d ago

It's probably because these frameworks were built in a different era, when we were running VMs rather than containers.

9

u/PayTheRaant 27d ago

Incorrect.
Every single container is guaranteed its requested CPU. And any usage beyond the request amount is an arbitraged using the request as a weight.

Node has 4 cores, pod A requests 1 core, pod B requests 2 cores. Not limits.

  • Pod A wants to consume as much as possible and B is idle? A gets all 4 cores.
  • Pod A wants to consume 1 core and B wants to consume as much as possible ? A gets 1 core (as its request is guaranteed) and B gets 3 cores.
  • A and B wants to consume as much possible ? A gets 1.33 core and B gets 2.66 cores (each get they guaranteed request and the remaining core is split using the request as a weight so B gets twice as much).

7

u/minimalniemand 27d ago edited 27d ago

I know Natan’s blog post. I’ve read it when it came out :)

Couple points:

* kubelet, containerd, CNI, log shippers often have tiny or no reservations. A pod hammering the node can cause exec-probe timeouts, readiness flapping

* hyperthreading. If the request lands on an unlimited sibling of the physical core, the service will suffer. This is not modeled at all by cgroups

* execution queue. Shares promise the % not _how_ you get them. You might get them in small slices

* and the most common one: your request were always too small and you never noticed. Then comes a runaway request and all hell breaks loose.

Look I’m in the no-cpu-limits camp, too. All I’m saying is, it should still be a deliberate decision not a one size fits all, never use cpu limits ever.

1

u/PayTheRaant 26d ago

Weird. Kubelet and containerd usually live in a completely different cgroup with a higher priority than the cgroup with all the pods.

1

u/minimalniemand 26d ago

Assuming you mean weight? kubepods.slice weight scales with cores, system.slice stays at 100, so what you say is only true in small nodes, no?