kubernetescost-optimizationfinopsaws

Kubernetes node pool sizing for cost: big nodes, small nodes, and the waste between

Node size is one of the highest-leverage cost decisions in Kubernetes and most teams pick by habit. Too small and system overhead eats your capacity, too big and a single pod strands half a node. Here is how to size node pools with real numbers.

The C3X Team··7 min read

Quick answer

Node size trades system overhead against packing granularity. Small nodes waste a larger share to kubelet, DaemonSets, and reserved capacity: a 2 vCPU node can lose 25 to 35 percent to overhead while a 16 vCPU node loses 8 to 12 percent. Large nodes waste through stranded capacity when pod shapes do not divide evenly and through coarse scale-in steps. For most general workloads, 8 to 16 vCPU nodes hit the sweet spot, typically 25 percent cheaper per usable vCPU than 2 vCPU nodes, and you should run multiple pools sized for the pod shapes you actually have rather than one pool for everything.

Ask three platform engineers what node size to use and you will get three answers based on what they used last time. The question has a real answer, and it comes from two competing forms of waste: fixed overhead per node, which punishes small nodes, and stranded capacity, which punishes large ones.

The overhead tax on small nodes

Every node loses capacity before a workload pod schedules. The cloud provider reserves memory and CPU for the kubelet and OS, and your DaemonSets take a fixed slice regardless of node size. A typical stack, CNI, kube-proxy, a log shipper, a metrics agent, and a security agent, consumes roughly 0.4 to 0.7 vCPU and 1 to 1.5 GB per node.

InstancevCPUAllocatable after overheadUsable shareOn-demand per monthCost per usable vCPU
m5.large2about 1.3568 percent$70$51.85
m5.xlarge4about 3.383 percent$140$42.42
m5.2xlarge8about 7.290 percent$280$38.89
m5.4xlarge16about 14.993 percent$561$37.65

Going from m5.large to m5.2xlarge cuts cost per usable vCPU by 25 percent. That is a real saving with no workload change at all, purely from amortizing fixed overhead across more capacity. Twenty m5.large nodes give you 27 usable vCPU for $1,400. Five m5.2xlarge nodes give you 36 usable vCPU for $1,400. Same money, 33 percent more capacity.

The stranding tax on large nodes

Large nodes waste differently. If your dominant pod requests 3 vCPU, an m5.2xlarge with 7.2 allocatable vCPU fits two pods and strands 1.2 vCPU, 17 percent of the node. An m5.4xlarge with 14.9 allocatable fits four pods and strands 2.9 vCPU, 19 percent. The waste is not monotonic, it depends on how cleanly your pod shapes divide into the node shape.

Large nodes also make scale-in coarse. If the cluster autoscaler can only remove capacity in 16 vCPU chunks, a cluster that needs 50 vCPU either runs 64 vCPU or 48 vCPU, and it will always round up. With 8 vCPU nodes the granularity halves and the rounding waste halves with it. On a 200 vCPU cluster that difference is roughly $280 per month of permanently over-provisioned headroom.

Pick node size from pod shape

The practical rule: a node should fit at least 4 to 6 copies of your median pod, and no single pod should need more than about 30 percent of a node. Below 4 pods per node, stranding dominates. Above roughly 20 pods per node you start hitting pod-per-node limits and blast-radius concerns.

Median pod requestGood node sizePods per node
0.25 vCPU / 512 MB4 vCPU / 16 GBabout 13
0.5 vCPU / 2 GB8 vCPU / 32 GBabout 14
2 vCPU / 8 GB16 vCPU / 64 GBabout 7
4 vCPU / 32 GB32 vCPU / 128 GBabout 7

Match the CPU to memory ratio

Choosing the wrong family wastes more than choosing the wrong size. General-purpose m5 gives 4 GB per vCPU, compute-optimized c5 gives 2 GB per vCPU at $0.085 per hour for c5.large, and memory-optimized r5 gives 8 GB per vCPU at $0.126 per hour for r5.large. If your pods request 1 vCPU and 8 GB, packing them onto m5 nodes exhausts memory at 50 percent CPU utilization: you pay for CPU you can never schedule. Moving that workload to r5 nodes costs 31 percent more per hour but roughly doubles the pods per node, a net saving near 34 percent.

Run multiple pools, not one

Most clusters have at least three distinct pod shapes: small stateless services, memory-heavy caches or JVM apps, and batch or CI jobs. One node pool cannot serve all three efficiently. A common layout is a general-purpose pool on 8 vCPU nodes for the bulk of services, a memory-optimized pool for the heavy ones, and a spot pool for interruptible batch. Taints and node selectors keep the workloads where they belong. Tools like Karpenter handle this by choosing instance types per pending pod instead of forcing you to pre-declare pools.

Sizing decisions live in Terraform node group definitions, which means they can be priced before merge. Price the node pool against the resource catalog and the cost per usable vCPU of a proposed instance type becomes a review comment rather than a quarterly discovery.

FAQ

What is the best node size for a Kubernetes cluster?

For most general workloads, 8 to 16 vCPU nodes hit the sweet spot. Smaller nodes lose a large share of capacity to kubelet reservations and DaemonSets, a 2 vCPU node can lose 25 to 35 percent, while a 16 vCPU node loses only 8 to 12 percent. Larger nodes waste through stranded capacity and coarse scale-in steps. A good rule is that a node should fit 4 to 6 copies of your median pod.

How much does node size affect Kubernetes cost?

Significantly. Cost per usable vCPU on m5.large is about $51.85 per month versus $38.89 on m5.2xlarge, a 25 percent difference from overhead amortization alone. Twenty m5.large nodes give 27 usable vCPU for $1,400 while five m5.2xlarge nodes give 36 usable vCPU for the same money, 33 percent more capacity with no workload change.

Why do small Kubernetes nodes waste money?

Because overhead is fixed per node. The kubelet and OS reservation plus DaemonSets such as the CNI, kube-proxy, log shippers, metrics agents, and security agents consume roughly 0.4 to 0.7 vCPU and 1 to 1.5 GB on every node regardless of its size. On a 2 vCPU node that is a third of the capacity, on a 16 vCPU node it is under a tenth.

Should I use one node pool or several?

Several. Most clusters have at least three distinct pod shapes: small stateless services, memory-heavy caches or JVM applications, and interruptible batch or CI jobs. One pool cannot serve all three efficiently. A typical layout is a general-purpose pool on 8 vCPU nodes, a memory-optimized pool for heavy workloads, and a spot pool for batch, with taints and node selectors routing pods appropriately.

How do I pick between compute-optimized and memory-optimized nodes?

Match the node's CPU to memory ratio to your pods' request ratio. General-purpose m5 gives 4 GB per vCPU, compute-optimized c5 gives 2 GB, and memory-optimized r5 gives 8 GB. If pods request 1 vCPU and 8 GB, m5 nodes run out of memory at 50 percent CPU utilization, so you pay for unschedulable CPU. Moving to r5 costs 31 percent more per hour but roughly doubles pods per node, netting about 34 percent savings.

How does C3X help with node pool sizing?

Node pool definitions live in Terraform, so C3X prices them against a live catalog before merge. A change that switches an instance family or doubles a node group's desired size shows its monthly cost delta in the pull request, letting reviewers compare cost per usable vCPU across candidate instance types instead of discovering the choice on the next invoice.

What to do next

Price node pools before you scale them. C3X reads your Terraform and prices your resources against a live catalog. Start with the quickstart.

Try C3X on your own Terraform

Free and open source. No API key required. One command to install, one command to estimate.