The upgrade that changes nothing — on purpose
The most important thing about Memory QoS graduating to Beta in Kubernetes v1.37 is what does not happen when you upgrade. The MemoryQoS feature gate is now enabled by default on every v1.37 kubelet running on cgroup v2 nodes — and by default, it writes nothing. No memory.high, no memory.min, no memory.low. Your workloads run exactly as they did the day before the upgrade.
That is not an accident or a half-finished feature. It is the design. And for platform operators, it is the right way to ship a mechanism that touches how the kernel treats container memory.
What actually changed
Memory QoS first appeared as Alpha in v1.22 and gained tiered memory reservation in v1.36. In v1.37 it reaches Beta: on by default, but inert until you configure it. Two changes carry the release:
- The throttling default was reversed. In the Alpha releases, memoryThrottlingFactor defaulted to 0.9, so turning the feature on started setting memory.high on containers. In v1.37 the default is null. The reasoning is stated plainly in the announcement: with the gate now on by default, an automatic memory.high could throttle workloads that were previously running unthrottled. If your kubelet configuration already sets an explicit memoryThrottlingFactor, that value is preserved across the upgrade and throttling continues as before. If it does not, nothing is set — and to get throttling you now add the value deliberately.
- The two behaviors are independent opt-ins. memoryThrottlingFactor enables memory.high throttling for Burstable and BestEffort containers. memoryReservationPolicy set to TieredReservation enables memory protection — memory.min for Guaranteed pods, memory.low for Burstable pods. You can enable either one without the other. Who gets what, at a glance:
| QoS class | memory.min | memory.low | memory.high |
|---|---|---|---|
| Guaranteed | Set — under TieredReservation | — | — |
| Burstable | — | Set — under TieredReservation | Set — when memoryThrottlingFactor is configured |
| BestEffort | — | — | Set — when memoryThrottlingFactor is configured |
Why the null default matters more than the feature
Every platform team has lived some version of the upgrade that silently changed runtime behavior — a new default, a tightened limit, a controller that suddenly enforced a policy nobody remembered adopting. The incident review writes itself, and so does the organizational scar tissue: upgrades get deferred, versions drift, and the security patches wait behind the fear.
The Memory QoS team chose the opposite trade. They accepted a quieter Beta — a headline feature that does nothing out of the box — in exchange for an upgrade that cannot surprise you. Beta, here, is a statement about the mechanism’s maturity, not a change to your cluster. That is a pattern worth copying well beyond Kubernetes: when a feature graduates, the graduation should change what operators trust, not what their workloads experience.
The real decision: reservation is node-wide
The honest limitation in this release is that memoryReservationPolicy applies to every pod on the node. With TieredReservation, every Guaranteed pod receives memory.min and every Burstable pod receives memory.low; there is no per-pod opt-in or opt-out. Hard reservation also covers everything charged to the container’s cgroup, including page cache — so a pod that reads large files can hold memory the kernel would otherwise reclaim for its neighbors.
That makes the operator’s real question a workload question, not a feature question: what shares a node? A node pool of uniform, well-understood services is a good candidate for tiered reservation. A mixed node — latency-sensitive services beside batch jobs that chew through page cache — has to pick one policy for all of them, and the safe answer may be to leave reservation off and take throttling only. SIG Node is tracking both issues, and the announcement points operators with affected workloads to kubernetes/kubernetes#140246.
What to do on Monday morning
- Confirm your nodes are actually on cgroup v2 — Memory QoS does nothing without it.
- Audit your kubelet configuration for an existing memoryThrottlingFactor before upgrading. An explicit value survives the upgrade; a missing one means throttling stops being set unless you add it back deliberately.
- Decide per node pool, not per cluster. The policy is node-wide, so the unit of decision is the pool’s workload mix.
- If you want the gentle on-ramp, start with throttling only (memoryThrottlingFactor, e.g. 0.9) and watch Burstable and BestEffort behavior before adopting tiered reservation.
- If you need out entirely, the feature gate can be set to false — with the documented configuration constraints, and the kubelet resets stale protection values on startup.
The takeaway
Memory QoS reaching Beta is good news delivered the way platform changes should be: the mechanism is declared trustworthy, the defaults protect your upgrade, and the consequential choices — throttling, reservation, and where they apply — stay explicitly yours. The next milestone is GA, and it will be shaped by Beta feedback. If you run mixed-workload nodes, your experience with the node-wide limitation is exactly the feedback that matters.
Sources
- Kubernetes blog: “Kubernetes v1.37: Memory QoS Graduates to Beta” (2026-09-14) — https://kubernetes.io/blog/2026/09/14/kubernetes-v1-37-memory-qos-graduates-to-beta/
- KEP-2570: Memory QoS — https://www.kubernetes.dev/blog/2021/05/10/memory-qos-cgroups-v2 (KEP-2570, SIG Node)
- Known-limitation tracking issue: kubernetes/kubernetes#140246
Top comments (0)