Kubernetes node pool cost is the sum of the hourly prices of the pool's nodes, and the node pool is the unit in which a cluster makes its pricing decisions: one machine family, one size, one purchase option and one scaling range per pool. Everything a pod costs derives from the price of the node it lands on (what a pod costs); the choice of pool sets that price. This page describes how family and size fix the price per vCPU and per GiB, what bin packing has to do with size, why ARM pools and separate system pools are cost decisions, and how taints and affinity steer pods into the right pool.
How it works
A node pool is a group of nodes with one instance type, one image and one scaling range; the provider keeps it as an Auto Scaling group, a virtual machine scale set or a managed instance group. The bill shows the nodes as virtual machines at their type's hourly price, and only a tag or label ties an instance to a pool and a cluster. Three properties of the pool set the price.
The machine family fixes the ratio of CPU, memory and price. Within one generation, a memory-optimised instance with the same vCPU count costs more than a general-purpose one because it carries four times the memory; a compute-optimised one costs less and carries half. ARM instances (AWS Graviton, Azure Cobalt, Google Axion) of the same class have a lower hourly price for the same vCPU count and need container images built for the architecture. Which family fits a workload is decided by the ratio of its requests: a pool with too much memory per vCPU pays for memory no pod asks for.
Size scales linearly within a family: the double-sized instance costs double. The price per vCPU does not change with it, the packing does. Every node reserves capacity for the kubelet and the container runtime and carries one copy of every DaemonSet (logging, monitoring, the network agent); on small nodes that fixed share weighs more. Large nodes fit more pods without waste, small nodes let the autoscaler scale down in finer steps. A pod that fits no node because its requests exceed the allocatable capacity of every type forces a larger type on the whole pool.
The role separates system from workloads. AKS requires at least one system node pool for critical system pods and recommends running workloads in user pools; GKE Standard has a default pool, EKS no role but the same practice. A small system pool of fixed size keeps the add-ons out of the workloads' autoscaling.
Taints and affinity are the cost rules between pools. A taint on a pool keeps away every pod that does not tolerate it, so a GPU pool or a spot pool stays reserved for the pods meant for it. nodeSelector and node affinity pull pods towards a pool, for instance by architecture (kubernetes.io/arch: arm64) or capacity type. Without these rules the scheduler places pods by free space, and an expensive pool fills with pods that would have run on the cheap one.
AWS
EKS has managed node groups with one or several instance types; Karpenter and EKS Auto Mode replace the static pool with a NodePool of requirements (families, sizes, architectures, capacity type) from which the cheapest fitting instance is chosen per pending pod. Auto Mode adds a management fee per launched instance, by instance type, on top of the EC2 price (EKS, ECS and Fargate).
Azure
AKS node pools are virtual machine scale sets with one VM size per pool; a pool carries the mode System or User, and node auto-provisioning picks VM sizes from the requests of pending pods. AKS Automatic adds a fee per vCPU and hour by VM category.
Google Cloud
GKE Standard has node pools with one machine type per pool, optionally with node pools created automatically for pending pods; Autopilot has no pools, there the pod's compute class selects the hardware and requests are billed.
What it means for your cost
The node pool is where most of a cluster's cost is decided before a pod runs. The order of decisions: first measure the workloads' ratio of CPU to memory and choose the family by it; then the size, so that typical pods fit without waste and a DaemonSet set occupies no more than a small share of the node; then the architecture, if the images can be built for ARM; then the purchase option per pool, commitments for the baseline (commitment strategy) and spot for what tolerates interruption. A pool that admits several instance types gives the autoscaler and the spot market room; a pool with exactly one type is easier to reserve.
What a pool costs is not visible in billing data as a pool, only as instance hours with tags; tags and labels on the pool are what makes a comparison of two pools possible from the data. A pool's efficiency, requests against allocatable, is Kubernetes efficiency; the number of nodes in the pool is set by the node autoscaler.
Where it goes wrong
- Expensive pool full, cheap pool empty. Symptom: the GPU or memory-optimised pool scales up although the pods on it request no GPU and no large memory. Cause: the pool has no taint, and the scheduler takes the space it finds.
- Memory paid for that nobody requests. Symptom: nodes are full by CPU and half empty by memory. Cause: the family carries more GiB per vCPU than the workloads request; a compute-optimised or general-purpose family fits better.
- Small nodes, large fixed share. Symptom: a noticeable part of every node is taken before the first workload pod runs. Cause: kube-reserved and one DaemonSet set per node weigh heavily on a two-vCPU instance.
- Pod fits no node. Symptom: a pod stays
Pendingalthough the pool may scale. Cause: its requests exceed the allocatable capacity of the pool's only instance type. - ARM pool without images. Symptom: pods on the ARM pool fail with
exec format error. Cause: the images are built for x86 only; without multi-arch images the cheaper pool goes unused. - System pool scales along. Symptom: add-ons are moved and restarted at every scale-down. Cause: system pods run in the workload pool; a system pool of fixed size keeps them stable.
Example
List prices read on 2026-10-21 from the AWS price list for Frankfurt (eu-central-1), on demand, Linux: m6i.large (2 vCPU, 8 GiB) USD 0.115, m6i.2xlarge (8 vCPU, 32 GiB) USD 0.46, m7g.large (2 vCPU, 8 GiB, Graviton) USD 0.0978, c6i.large (2 vCPU, 4 GiB) USD 0.097, r6i.large (2 vCPU, 16 GiB) USD 0.152 per hour.
Four m6i.large cost 4 × 0.115 = USD 0.46 per hour, exactly one m6i.2xlarge: size does not change the price per vCPU. A DaemonSet set requesting 200 millicores per node takes 800 millicores of 8 vCPU on the four small nodes and 200 millicores on the large one. The same pool as four m7g.large costs 4 × 0.0978 = USD 0.3912 per hour, USD 0.0688 less, USD 50.22 per four nodes in a 730-hour month. Per vCPU-hour the c6i.large costs USD 0.0485, the m6i.large USD 0.0575 and the r6i.large USD 0.076; what makes a family dearer is the memory it brings per vCPU.
Sources
Read on 2026-10-21. AWS Price List bulk API, offer AmazonEC2, eu-central-1, AWS managed node groups, Karpenter NodePools, AWS EKS Auto Mode, Microsoft system and user node pools in AKS and node auto-provisioning, Google Cloud node pools and compute classes in Autopilot, Kubernetes assigning pods to nodes, taints and tolerations and reserving compute resources for system daemons.