Happy Dussehra! May good always win. Happy Diwali! Wishing you a bright year ahead. Merry Christmas! Warm wishes from Vizag. Happy New Year! Here’s to a great year ahead.

Archive · AWS

VPC Basics: Subnets, Routes and NAT

Design a VPC for Mumbai with public and private subnets across two Availability Zones, route tables, an internet gateway, NAT gateways, endpoints and flow logs.

4 min read

  • Amazon VPC
  • Internet Gateway
  • NAT Gateway
  • Region ap-south-1

A Virtual Private Cloud (VPC) is your own private network inside AWS. Every EC2 instance, load balancer, database and Lambda-in-VPC lives in one. Get the layout right once and everything after it, from security to cost, is easier.

State of AWS on this date. ap-south-1 (Mumbai) has three Availability Zones (a, b, c). Each account gets a default VPC in every region (172.31.0.0/16 with public subnets), good for experiments, but production workloads should use a VPC you design. A NAT gateway is billed per hour plus per GB processed, so it is a common surprise on bills.

A standard two-AZ layout

flowchart TB
  NET[Internet] --> IGW[Internet gateway]
  subgraph VPC[VPC 10.0.0.0/16]
    subgraph AZA[AZ ap-south-1a]
      PUB1[Public subnet 10.0.0.0/24<br/>ALB NAT gateway bastion]
      PRV1[Private subnet 10.0.10.0/24<br/>app servers]
      DB1[Data subnet 10.0.20.0/24<br/>RDS]
    end
    subgraph AZB[AZ ap-south-1b]
      PUB2[Public subnet 10.0.1.0/24]
      PRV2[Private subnet 10.0.11.0/24]
      DB2[Data subnet 10.0.21.0/24]
    end
    PUB1 --> NAT1[NAT gateway A]
    PUB2 --> NAT2[NAT gateway B]
    PRV1 -->|0.0.0.0/0| NAT1
    PRV2 -->|0.0.0.0/0| NAT2
    PRV1 --> DB1
    PRV2 --> DB2
  end
  IGW --> PUB1
  IGW --> PUB2
  PRV1 -.->|gateway endpoint| S3[S3 and DynamoDB]

Three tiers, two AZs: the load balancer is public, application servers have no public IPs, and databases accept connections only from the application tier.

Building blocks

Piece What it does
CIDR block The address range, for example 10.0.0.0/16 (65,536 addresses). Choose ranges that do not overlap with your offices, other VPCs or partners, because overlap blocks peering and VPN later
Subnet A slice of the VPC inside one AZ. AWS reserves 5 addresses per subnet
Route table Decides where packets for a destination go; each subnet uses one
Internet gateway (IGW) Lets public subnets reach the internet and be reached (needs a public or Elastic IP)
NAT gateway Lets private instances start outbound connections (updates, APIs) without being reachable from outside
Security group Stateful firewall on the instance or network interface; allow rules only
Network ACL Stateless, subnet-level, allow and deny rules; usually left at default
VPC endpoint Private path to AWS services without internet or NAT

A subnet is “public” only because its route table has 0.0.0.0/0 pointing to an internet gateway.

Create it with the CLI

VPC=$(aws ec2 create-vpc --cidr-block 10.0.0.0/16 --query Vpc.VpcId --output text)
aws ec2 modify-vpc-attribute --vpc-id $VPC --enable-dns-hostnames
aws ec2 create-tags --resources $VPC --tags Key=Name,Value=prod-vpc

PUB1=$(aws ec2 create-subnet --vpc-id $VPC --cidr-block 10.0.0.0/24 --availability-zone ap-south-1a --query Subnet.SubnetId --output text)
PRV1=$(aws ec2 create-subnet --vpc-id $VPC --cidr-block 10.0.10.0/24 --availability-zone ap-south-1a --query Subnet.SubnetId --output text)

IGW=$(aws ec2 create-internet-gateway --query InternetGateway.InternetGatewayId --output text)
aws ec2 attach-internet-gateway --vpc-id $VPC --internet-gateway-id $IGW

RT_PUB=$(aws ec2 create-route-table --vpc-id $VPC --query RouteTable.RouteTableId --output text)
aws ec2 create-route --route-table-id $RT_PUB --destination-cidr-block 0.0.0.0/0 --gateway-id $IGW
aws ec2 associate-route-table --route-table-id $RT_PUB --subnet-id $PUB1

EIP=$(aws ec2 allocate-address --domain vpc --query AllocationId --output text)
NAT=$(aws ec2 create-nat-gateway --subnet-id $PUB1 --allocation-id $EIP --query NatGateway.NatGatewayId --output text)
aws ec2 wait nat-gateway-available --nat-gateway-ids $NAT
RT_PRV=$(aws ec2 create-route-table --vpc-id $VPC --query RouteTable.RouteTableId --output text)
aws ec2 create-route --route-table-id $RT_PRV --destination-cidr-block 0.0.0.0/0 --nat-gateway-id $NAT
aws ec2 associate-route-table --route-table-id $RT_PRV --subnet-id $PRV1

Treat this as a learning aid; for real environments define the VPC in CloudFormation or Terraform so it is reviewed, repeatable and easy to tear down. Remember to repeat the subnets, route tables and NAT gateway in the second AZ.

Cost and resilience decisions

  • A NAT gateway lives in one AZ. For resilience, one per AZ with each private route table pointing to its own; for a cheap lab, one NAT (or a NAT instance) and accept the risk.

  • Traffic through NAT is billed per GB. Add gateway endpoints for S3 and DynamoDB (free) so heavy S3 traffic bypasses NAT:

    aws ec2 create-vpc-endpoint --vpc-id $VPC --service-name com.amazonaws.ap-south-1.s3 --route-table-ids $RT_PRV
  • Interface endpoints (PrivateLink) for services such as ECR, SSM and Secrets Manager cost per hour; use them when security or NAT cost justifies it.

  • Cross-AZ traffic costs a little per GB; keep chatty components in the same AZ where you can.

Security and visibility

  1. Put only load balancers, bastions (or no bastion, using Session Manager) and NAT in public subnets.

  2. Use security groups that reference other security groups (app-sg allows alb-sg on 8080), not IP ranges.

  3. Turn on VPC Flow Logs to CloudWatch Logs or S3 to see accepted and rejected connections when debugging:

    aws ec2 create-flow-logs --resource-type VPC --resource-ids $VPC --traffic-type ALL \
      --log-destination-type cloud-watch-logs --log-group-name /vpc/prod-flow --deliver-logs-permission-arn arn:aws:iam::111111111111:role/flowlogs
  4. Leave the default VPC unused (or delete it where policy allows).

Troubleshooting connectivity

Work through: security group (inbound on the target, outbound on the source), network ACL, route table of the source subnet, whether a NAT/IGW exists for the route, DNS settings, and the target’s own listener. The VPC Reachability Analyzer can trace a path between two resources and name the blocking component.