Verified7 commandsAI-assisted

Networking: VPC, Route 53 & ELB

Verified against aws-cli/2.33.6, flags verified via `aws <cmd> help`, 2026-08-20 · official docs

VPC and subnet setup, routing and internet access, security group rules, Route 53 DNS records, and Elastic Load Balancing (ALB/NLB via elbv2).

VPCs and subnets#

aws ec2 create-vpc --cidr-block 10.0.0.0/16 --tag-specifications 'ResourceType=vpc,Tags=[{Key=Name,Value=my-vpc}]'
aws ec2 describe-vpcs --filters "Name=tag:Name,Values=my-vpc"
aws ec2 create-subnet --vpc-id vpc-0123456789abcdef0 --cidr-block 10.0.1.0/24 --availability-zone us-east-1a
aws ec2 describe-subnets --filters "Name=vpc-id,Values=vpc-0123456789abcdef0"

Internet access — gateway, route table, association#

aws ec2 create-internet-gateway
aws ec2 attach-internet-gateway --internet-gateway-id igw-0123456789abcdef0 --vpc-id vpc-0123456789abcdef0
aws ec2 create-route-table --vpc-id vpc-0123456789abcdef0
aws ec2 create-route --route-table-id rtb-0123456789abcdef0 --destination-cidr-block 0.0.0.0/0 --gateway-id igw-0123456789abcdef0
aws ec2 associate-route-table --route-table-id rtb-0123456789abcdef0 --subnet-id subnet-0123456789abcdef0

A subnet is only "public" because its route table has a 0.0.0.0/0 route pointing at an internet gateway — there's no separate "make this subnet public" flag. This four-command chain (gateway → attach → route → associate) is the whole mechanism.

Security group rules#

aws ec2 authorize-security-group-ingress \
  --group-id sg-0123456789abcdef0 \
  --protocol tcp --port 443 --cidr 0.0.0.0/0

aws ec2 authorize-security-group-ingress \
  --group-id sg-0123456789abcdef0 \
  --protocol tcp --port 22 --source-group sg-0123456789abcdef1   # allow from another security group instead of a CIDR

Route 53 — hosted zones#

aws route53 list-hosted-zones
aws route53 create-hosted-zone --name example.com --caller-reference "$(date +%s)"

--caller-reference must be a unique string per call (it's an idempotency token, not a DNS field) — a timestamp or UUID both work; a fixed literal will fail on a second run with the same name.

Route 53 — records#

aws route53 list-resource-record-sets --hosted-zone-id Z1234567890ABC
aws route53 change-resource-record-sets --hosted-zone-id Z1234567890ABC --change-batch '{
  "Changes": [{
    "Action": "UPSERT",
    "ResourceRecordSet": {
      "Name": "app.example.com",
      "Type": "A",
      "TTL": 300,
      "ResourceRecords": [{"Value": "203.0.113.10"}]
    }
  }]
}'

change-resource-record-sets is the only way to create/update/delete records — there's no create-record shortcut. UPSERT creates the record if it doesn't exist or overwrites it if it does; use CREATE/DELETE when you want the API to reject a call that doesn't match the record's current existence state.

Load balancers (ALB/NLB) — creation and listeners#

aws elbv2 create-load-balancer --name my-alb --subnets subnet-0123456789abcdef0 subnet-0123456789abcdef1 --security-groups sg-0123456789abcdef0 --type application
aws elbv2 describe-load-balancers --names my-alb
aws elbv2 create-target-group --name my-targets --protocol HTTP --port 80 --vpc-id vpc-0123456789abcdef0 --health-check-path /healthz
aws elbv2 create-listener --load-balancer-arn <lb-arn> --protocol HTTP --port 80 --default-actions Type=forward,TargetGroupArn=<target-group-arn>

Target groups — registering and checking health#

aws elbv2 register-targets --target-group-arn <target-group-arn> --targets Id=i-0123456789abcdef0
aws elbv2 describe-target-health --target-group-arn <target-group-arn>

describe-target-health is the fastest way to confirm whether an ALB actually considers your instances/tasks healthy — a TargetHealth.State of unhealthy here, not application logs, is usually the first place to look when a load balancer is returning 502s.