Kubernetes has three CIDR ranges that need to play nicely: the node CIDR (the VPC subnet your nodes live in), the pod CIDR (where pod IPs come from), and the service CIDR (where ClusterIPs come from). Get any one of them wrong and your cluster either won't start or will run out of addresses mid-deploy.
The three CIDRs
Node CIDR
This is your VPC subnet (or on-prem network). Nodes get their primary IP from here. Size it based on how many nodes you'll run, plus headroom for cluster autoscaling.
Pod CIDR
Every pod gets an IP. By default, Kubernetes assigns each node a /24 from the pod CIDR. So 100 nodes need 100 /24s, which is 256 × 100 = 25,600 addresses — round up to a /16 (65,536 addresses) for headroom.
Service CIDR
ClusterIPs (the virtual IPs services get) come from here. Services don't churn like pods, so a /20 (4,096 services) is plenty for most clusters. Default kubeadm uses 10.96.0.0/12, which is overkill but never causes problems.
Sizing pod CIDR for kubeadm clusters
Default kubeadm: pod CIDR = 10.244.0.0/16, gives each node a /24 (256 IPs per node).
AWS VPC CNI: a different model entirely
EKS by default uses the AWS VPC CNI, which gives each pod a real VPC IP — not a CNI-overlay IP. This means pods consume IPs from your node subnet, not a separate pod CIDR.
A node running 30 pods uses 30 VPC IPs. A /24 subnet (251 usable on AWS) holds about 8 such nodes. Run out of subnet IPs and you'll see InsufficientFreeAddressesInSubnet at the worst possible moment.
Prefix delegation: the fix
Enable prefix delegation on the AWS VPC CNI. Each node gets a /28 (16 IPs) from the subnet instead of warming individual IPs. The math goes from "30 IPs per node" to "1 /28 prefix per node = much higher pod density." This is the right default for any EKS cluster of meaningful size.
Service CIDR sizing
Services are sparse. A /20 holds 4,094 services — more than most clusters will ever have. The default kubeadm 10.96.0.0/12 holds about a million. Pick whatever you want, but don't overlap with pod CIDR or VPC.
The overlap problem
If your pod CIDR overlaps with the VPC range, return traffic gets routed weirdly. Pods can ping nodes but can't reach the internet, or vice versa. Always pick a pod CIDR outside the VPC range.
Common pattern:
- VPC:
10.0.0.0/16 - Node subnets: /20s carved from the VPC
- Pod CIDR:
172.16.0.0/16(different RFC 1918 range entirely) - Service CIDR:
10.96.0.0/12(also outside VPC)
kubeadm config example
kubeadm init \
--pod-network-cidr=172.16.0.0/16 \
--service-cidr=10.96.0.0/12 \
--apiserver-advertise-address=10.0.0.10
For EKS
On EKS you don't pick pod CIDR directly when using AWS VPC CNI — pods just take VPC IPs. What you control:
- The node subnet sizes (make them /22 or bigger)
- Whether to enable prefix delegation (yes, almost always)
- Service CIDR (set at cluster creation, often left at default)
For GKE
GKE uses an overlay model by default. Pod CIDR and service CIDR are set at cluster creation and can't be changed. Pick them well the first time — common defaults are 10.4.0.0/14 for pods and 10.0.32.0/20 for services.
Multi-cluster networking
If you'll ever connect clusters with Submariner, Cilium Cluster Mesh, or Istio multi-cluster, the pod CIDRs across clusters must not overlap. Plan globally: assign each cluster a unique pod CIDR from a parent allocation (e.g. 172.16.0.0/14 with /16 per cluster).
The Kubernetes planner generates the kubeadm config and checks for overlaps. For multi-cluster planning, paste your CIDRs into the overlap checker.