Public subnet instances have no internet access
ping/curl to the internet fails from an instance in a public subnet
Focused incident mode — strips away everything but this runbook.
Symptoms
- ping/curl to the internet fails from an instance in a public subnet
- Instances in other subnets work fine
- Route table shows no 0.0.0.0/0 route in the console
Route tables are evaluated per subnet (explicit association wins over main). Always confirm WHICH table the subnet is actually using before editing any route.
Evidence to grab
Collect these artifacts before you change anything — they prove (or rule out) each cause.
Subnet AZ and association
aws ec2 describe-subnets --subnet-ids <SUBNET-ID> --query 'Subnets[0].{AZ:AvailabilityZone,MapPublicIpOnLaunch:MapPublicIpOnLaunch}'Routes applied to the subnet
aws ec2 describe-route-tables --filters Name=association.subnet-id,Values=<SUBNET-ID> --query 'RouteTables[0].Routes'
Diagnostic flow
Run the steps in order, marking each claim confirmed or refuted. The evidence you gather feeds the ranked causes below.
Guided decision tree is ready.
Steps with commands, expected output, and pass/fail branches.
Ranked root causes
Evidence checklist
- Route table for the subnet lacks the default route
- Other subnets that do have the route work
Confirm before fixing
aws ec2 describe-route-tables --filters Name=association.subnet-id,Values=<SUBNET-ID> --query 'RouteTables[0].Routes[*].{Dest:DestinationCidrBlock,GW:GatewayId}'Look for the default route
Expected: Empty GatewayId for 0.0.0.0/0 or the route missing
Fix
aws ec2 create-route --route-table-id <ROUTE-TABLE-ID> --destination-cidr-block 0.0.0.0/0 --gateway-id <IGW-ID>Add the default route to the IGW
Expected: route added
Resolution runbook
Apply from top to bottom after the cause is confirmed. Review every command before running it — risk tags are shown on each.
aws ec2 describe-route-tables --filters Name=association.subnet-id,Values=<SUBNET-ID> --query 'RouteTables[0].Routes[*].{Dest:DestinationCidrBlock,GW:GatewayId}'Baseline the route table
aws ec2 describe-internet-gateways --filters Name=attachment.vpc-id,Values=<VPC-ID>Verify IGW attachment
aws ec2 create-route --route-table-id <ROUTE-TABLE-ID> --destination-cidr-block 0.0.0.0/0 --gateway-id <IGW-ID>Add the default route
aws ssm send-command --instance-ids <INSTANCE-ID> --document-name AWS-RunShellScript --parameters 'commands=["ping -c 3 8.8.8.8"]'Verify connectivity after the change
Prevention
- Drive route tables through IaC and enforce an explicit subnet association for every public subnet.
- Run a scheduled reachability analyzer (Reachability Analyzer) from public subnets to the internet.
- Document public/private subnet design so a route to igw- is never 'surprising'.
Related runbooks
Same stack, same failure family — worth a skim.
Instances in private subnets cannot reach package repos or APIs
Traffic fails in one direction only (e.g. inbound works, replies dropped)
aws ec2 describe-instances shows no PublicIpAddress for a fresh instance
Commands marked READ CHANGE DESTRUCTIVE — never run DESTRUCTIVE commands against production data you cannot restore. Copy → verify → execute.