The four building blocks
- VPC — your own private virtual network in a region, spanning multiple AZs. Every VPC has an implicit router and a main route table with a
localroute (so every subnet in the VPC can talk to each other). - Subnet — a slice of the VPC CIDR that lives entirely in one AZ. If you want to run in 2 AZs, create 2 subnets.
- Internet Gateway (IGW) — the VPC's door to the Internet. After you create it, you must attach it to the VPC.
- Route table — a list of "destination → where to send it". Each subnet is associated with exactly 1 route table; one route table can be associated with many subnets. The
localroute can't be deleted.
The route table decides public or private
flowchart LR
Internet((Internet)) <--> IGW[Internet Gateway]
subgraph VPC["VPC 10.0.0.0/16"]
subgraph Pub["Public subnet 10.0.1.0/24 (AZ a)"]
EC2A[EC2 with a public IP]
end
subgraph Priv["Private subnet 10.0.2.0/24 (AZ a)"]
EC2B[EC2 with only a private IP]
end
end
IGW <--> Pub
%% step Internet: Traffic from the Internet arrives at the VPC through the Internet Gateway.
%% step IGW: The IGW is attached to the VPC and translates public IPs to private IPs.
%% step EC2A: The public subnet routes 0.0.0.0/0 to the IGW and the instance has a public IP, so it is reachable.
%% step EC2B: The private subnet has only the local route, so the instance cannot be reached from the Internet.
The public subnet's route table:
| Destination | Target |
|---|---|
10.0.0.0/16 |
local |
0.0.0.0/0 |
igw-xxxx |
The private subnet only has the local row. There's no "public" flag on a subnet — it's the 0.0.0.0/0 → IGW route that makes it public.
But a route alone isn't enough: the instance also needs a public IP or Elastic IP. Remember to turn on auto-assign public IPv4 for your public subnet.
Creating it with the CLI
| Step | Command |
|---|---|
| Create the VPC | aws ec2 create-vpc --cidr-block 10.0.0.0/16 |
| Create a subnet | aws ec2 create-subnet --vpc-id vpc-xxxx --cidr-block 10.0.1.0/24 --availability-zone ap-southeast-1a |
| Create the IGW | aws ec2 create-internet-gateway |
| Attach the IGW | aws ec2 attach-internet-gateway --internet-gateway-id igw-xxxx --vpc-id vpc-xxxx |
| Create a route table | aws ec2 create-route-table --vpc-id vpc-xxxx |
| Route to the Internet | aws ec2 create-route --route-table-id rtb-xxxx --destination-cidr-block 0.0.0.0/0 --gateway-id igw-xxxx |
| Associate the subnet | aws ec2 associate-route-table --route-table-id rtb-xxxx --subnet-id subnet-xxxx |
Common mistakes
- Creating the IGW but forgetting to attach it, or forgetting to add the
0.0.0.0/0route. - Adding the route to a new route table but forgetting to associate the subnet → the subnet still uses the main route table.
- The subnet is public, but the instance has no public IP.
- Thinking a subnet can span multiple AZs.
Default limits (soft limits): 5 VPCs per region, 200 subnets per VPC.