InsightsCloud
Planning VPC IP address space before you need it
How to size VPC CIDR blocks, keep ranges unique across accounts and on-premises networks, lay out subnet tiers, and leave room for Kubernetes pod addresses.
Published August 27, 20245 min read
IP address planning is one of the few cloud decisions that is genuinely hard to undo. Instances can be resized and services rewritten, but a VPC's primary CIDR block is fixed at creation, and every network that will ever be peered or routed to it needs a range that does not overlap.
The usual story: the first VPCs are created with the console default of 10.0.0.0/16. A year later, two of them need to talk to each other, or to the office network, and they cannot, because they use the same addresses. The fix is a migration. A few hours of planning up front avoids it.
Allocate from one plan
Treat private address space as a shared resource with an owner and a register, not something each team picks when creating a VPC. The RFC 1918 ranges give you three blocks:
| Range | Size | Typical use |
|---|---|---|
10.0.0.0/8 | About 16.7 million addresses | Cloud networks, split into large regional blocks |
172.16.0.0/12 | About 1 million addresses | Often already used on-premises or by Docker defaults |
192.168.0.0/16 | 65,536 addresses | Home and office networks; avoid for cloud |
Before allocating anything, find out what is already in use: on-premises networks, VPN client pools, partner connections, and the default bridge networks of tools like Docker. These collide with cloud ranges more often than cloud ranges collide with each other.
A hierarchical plan keeps allocation simple and routes summarizable:
For instance, 10.0.0.0/12 for eu-west-1, 10.16.0.0/12 for us-east-1, and within eu-west-1 a /14 each for production, staging and development. A Transit Gateway or on-premises router can then carry one route per region or environment instead of one per VPC.
Sizing a VPC
AWS allows VPC CIDR blocks from /16 down to /28. The temptation is to give every VPC a /16 because it is the largest. With a /8 to divide, that allows only 256 VPCs in total, across every region, environment and team. Size by what the VPC will hold instead:
- Shared or platform VPCs running Kubernetes clusters, large fleets or many services:
/16to/18. - Single-workload VPCs:
/20to/22is usually plenty. - Inspection, egress or endpoint VPCs: often
/24or smaller.
When unsure, err larger for VPCs that will run Kubernetes and smaller for everything else. A VPC can gain secondary CIDR blocks later, but a secondary block has to come from somewhere in the plan too, and some services only use the primary range.
Subnet tiers
Within a VPC, subnets are usually split by tier and by Availability Zone. A common layout uses three tiers in three zones:
Public 10.20.0.0/22 10.20.4.0/22 10.20.8.0/22 load balancers, NAT gateways
Private 10.20.32.0/19 10.20.64.0/19 10.20.96.0/19 workloads, nodes
Data 10.20.128.0/21 10.20.136.0/21 10.20.144.0/21 databases, caches
Reserved 10.20.152.0/21 and above future tiers or zones
eu-west-1a eu-west-1b eu-west-1cSome principles behind those sizes:
- Public subnets stay small. They hold load balancer nodes and NAT gateways, not workloads.
- Private subnets get the most space, because that is where instances, containers and pod addresses live.
- Data subnets are separate so network ACLs and route tables can treat them differently, and so database subnet groups have their own clear ranges.
- Leave part of the range unallocated. A fourth Availability Zone or a new tier is much easier when there is space for it.
AWS reserves five addresses in every subnet: the network address, the next three for the VPC router, DNS and future use, and the broadcast address. This only matters for very small subnets, but it is why a /28 gives 11 usable addresses rather than 16.
Room for Kubernetes pods
Amazon EKS with the default VPC CNI gives every pod an address from the VPC. A node with 30 pods uses 31 or more addresses, and the CNI pre-allocates spare addresses per node so pods start quickly. A cluster that runs out of IP addresses while it still has spare CPU and memory is a common problem.
There are three ways to deal with it, and they combine:
- Large private subnets. A
/19per zone gives about 8,000 addresses each, which suits a medium-sized cluster. - Prefix delegation. Setting
ENABLE_PREFIX_DELEGATION=trueon the VPC CNI assigns/28prefixes to nodes instead of individual addresses. It raises the pod density per node and reduces API calls, but it needs contiguous free/28blocks in the subnet, so fragmented subnets cause failures. - Custom networking on a secondary range. Add a secondary CIDR to the VPC, often from
100.64.0.0/10, and configure the CNI withENIConfigresources so pods draw addresses from it while nodes stay on the primary range. Because pod traffic leaving the VPC is translated to the node address by default, the secondary range can be reused in every VPC without causing routing conflicts.
IPv6 is the other answer. EKS supports IPv6 clusters, where pods get addresses from a /56 assigned to the VPC and IPv4 exhaustion stops being a concern. It is worth evaluating for new clusters, but every dependency, including on-premises systems and third-party endpoints, needs to work with it.
Keep the register in code
A spreadsheet of allocations works until two people edit it in the same week. Better options:
- Amazon VPC IP Address Manager (IPAM) lets you define pools per region and environment, and allocate VPC CIDRs from them automatically. Terraform can request an allocation with
ipv4_ipam_pool_idandipv4_netmask_lengthonaws_vpc, so nobody picks a range by hand. - A Terraform module or data file with the allocation table, reviewed through pull requests, is a lighter-weight alternative that works across clouds.
Either way, include on-premises and partner ranges in the register, marked as reserved, so they are never handed out.
Where to start
- List every range in use today: VPCs in all accounts and regions, on-premises networks, VPN pools, partner links.
- Pick a top-level block for cloud use that overlaps none of them, and split it by region and environment.
- Choose standard VPC sizes, such as
/16for cluster VPCs and/20for single-workload VPCs. - Define a standard subnet layout with tiers per zone and reserved space.
- Decide how EKS clusters will get pod addresses: large subnets, prefix delegation, a secondary range or IPv6.
- Move allocation into IPAM or a reviewed code module, and stop creating VPCs with hand-picked ranges.