You buy a 16 GiB node. Kubernetes lets your pods use 11.9 GiB of it. The other 4 GiB go to kubelet reservations you never configured — and the managed services changed the rules recently, so most blog posts and calculators still show the old numbers.
I went through the EKS nodeadm source and the current GKE and AKS docs and computed allocatable CPU and memory for every instance type. Three things surprised me.
1. On EKS, prefix delegation quietly eats a gigabyte
EKS reserves memory per possible pod: 11 MiB × maxPods + 255 MiB. With the default VPC CNI, maxPods is the ENI limit — 17 on a t3.medium. Turn on prefix delegation (to fit more pods) and maxPods jumps to 110, so the reservation jumps too:
- t3.medium, default CNI: 442 MiB reserved → 87% of RAM usable- t3.medium, prefix delegation: 1465 MiB reserved → 62% of RAM usable- m5.large: 92% → 81%On small nodes you pay a gigabyte for pod slots you will never fill, because the 4 GiB box runs out of memory long before pod 110. Prefix delegation pays off on big nodes (m6i.4xlarge goes from 95.5% to 97.6%), not small ones. ## 2. GKE 1.37 gave you up to 7 GiB per node back Until 1.36, GKE reserved a regressive share of memory: 25% of the first 4 GiB, 20% of the next 4, 10% of the next 8, 6% up to 128 GiB. From 1.37 on Container-Optimized OS it is min(old value, 15 MiB × maxPods + 500 MiB) — about 2.1 GiB with 110 pods, whatever the node size:
- n2-standard-16 (64 GiB): 5.5 GiB reserved → 2.1 GiB- n2-standard-32 (128 GiB): 9.3 GiB reserved → 2.1 GiB, +7.2 GiB for podsIf you sized node pools on the old numbers, a node pool upgrade alone may let you drop nodes. The CPU reservation is also capped at 1 vCPU now. (Small print: shared-core e2-medium still reserves 1060m of its 2 vCPUs — 940m left.) ## 3. AKS with Azure CNI Overlay reserves for 250 pods by default Since 1.29 AKS reserves min(20 MB × maxPods + 50 MB, 25% of RAM). Azure CNI Overlay defaults to 250 max pods, so on a 16 GiB D4s v5 you hit the 25% cap:
- D4s v5, overlay default (250 pods): 4 GiB reserved → 74% usable- D4s v5, maxPods 110: 2.2 GiB reserved → 86% usableThat is 1.8 GiB per node for one flag at node pool creation. You can’t change maxPods on an existing pool — you add a new pool and migrate. ## What I do now
- Set maxPods to what the node can realistically run, not the maximum the CNI allows.- Size requests against kubectl describe node → Allocatable, minus DaemonSets — never against the instance spec.- Re-check after control-plane upgrades: the formula can change under you (GKE 1.37 did).I put the math for all ~2,900 AWS, GCP and Azure instance types into a free calculator: enter your pod requests and replica count, and it ranks node types by monthly cost after these reservations — nodesize.kalik8s.com. Each instance type has its own page, e.g. t3.medium on EKS. Sources for every formula are on the formulas page; if a number disagrees with your cluster, tell me and I’ll fix it. Which reservation bit you? I’m curious whether anyone measured the GKE 1.37 change on a real cluster yet. AI-assisted: numbers computed by a script I wrote with an AI coding assistant, checked against the sources above.
Top comments (0)