In this tutorial, we will implement transitive routing across all of your VPCs and share internet egress from a shared services VPC to your other VPCs to reduce the amount of NAT gateways you have to deploy.
Deploy an AWS Transit Gateway (TGW) and configure Transit Gateway VPC attachments for all of your VPCs. Update your VPC route tables of each VPC to send all nonlocal traffic to the Transit Gateway and enable sharing of the NAT gateway in your shared services VPC for all of your spoke VPCs.
Prerequisites
- 3 VPCs in the same region with private and isolated subnet tiers
- Internet gateway attached to a VPC (VPC2 in our example)
- NAT gateway deployed in public subnets
Steps
- Create a Transit Gateway.
TGW_ID=$(aws ec2 create-transit-gateway \ --description AWSKloudVM \ -- options=AmazonSideAsn=65010,AutoAcceptSharedAttachments=enable,Def aultRouteTableAssociation=enable,Default RouteTablePropagation=enable,VpnEcmpSupport=enable,DnsSupport=enable \ --output text --query TransitGateway.TransitGatewayId)<
/pre> - Wait until the Transit Gateway’s state has reached “available.” This may take several minutes:
aws ec2 describe-transit-gateways \ --transit-gateway-ids $TGW_ID \ --output text --query TransitGateways[0].State<
/pre> - Create a Transit Gateway attachment for the VPC1:
TGW_ATTACH_1=$(aws ec2 create-transit-gateway-vpc-attachment \ --transit-gateway-id $TGW_ID \ --vpc-id $VPC_ID_1 \ --subnet-ids $ATTACHMENT_SUBNETS_VPC_1 \ --query TransitGatewayVpcAttachment.TransitGatewayAttachmentId \ --output text)
- Create a Transit Gateway attachment for the VPC2:
=$(aws ec2 create-transit-gateway-vpc-attachment \ --transit-gateway-id $TGW_ID \ --vpc-id $VPC_ID_2 \ --subnet-ids $ATTACHMENT_SUBNETS_VPC_2 \ --query TransitGatewayVpcAttachment.TransitGatewayAttachmentId \ --output text)
- Create a Transit Gateway attachment for the VPC3:
TGW_ATTACH_3=$(aws ec2 create-transit-gateway-vpc-attachment \ --transit-gateway-id $TGW_ID \ --vpc-id $VPC_ID_3 \ --subnet-ids $ATTACHMENT_SUBNETS_VPC_3 \ --query TransitGatewayVpcAttachment.TransitGatewayAttachmentId \ --output text)
- Add route for all private subnets in VPCs 1 and 3 to target the TGW for destinations of 0.0.0.0/0. This enables consolidated internet egress through the NAT gateway in VPC2 and transitive routing to other VPCs.
aws ec2 create-route --route-table-id $VPC_1_RT_ID_1 \ --destination-cidr-block 0.0.0.0/0 \ --transit-gateway-id $TGW_ID aws ec2 create-route --route-table-id $VPC_1_RT_ID_2 \ --destination-cidr-block 0.0.0.0/0 \ --transit-gateway-id $TGW_ID aws ec2 create-route --route-table-id $VPC_3_RT_ID_1 \ --destination-cidr-block 0.0.0.0/0 \ --transit-gateway-id $TGW_ID aws ec2 create-route --route-table-id $VPC_3_RT_ID_2 \ --destination-cidr-block 0.0.0.0/0 \ --transit-gateway-id $TGW_ID
- Now add a route to your 10.10.0.0/24 supernet in the private subnets VPC2, pointing its destination to the Transit Gateway. This is more specific than the 0.0.0.0/0 destination that is already present and therefore, takes higher priority in routing decisions. This directs traffic bound for VPCs 1, 2, and 3 to the TGW:
aws ec2 create-route --route-table-id $VPC_2_RT_ID_1 \ --destination-cidr-block 10.10.0.0/24 \ --transit-gateway-id $TGW_ID aws ec2 create-route --route-table-id $VPC_2_RT_ID_2 \ --destination-cidr-block 10.10.0.0/24 \ -transit-gateway-id $TGW_ID
- Query for the Nat gateways in use; we’ll need these to add routes to them for internet traffic:
NAT_GW_ID_1=$(aws ec2 describe-nat-gateways \ --filter "Name=subnet-id,Values=$VPC_2_PUBLIC_SUBNET_ID_1" \ --output text --query NatGateways[*].NatGatewayId) NAT_GW_ID_2=$(aws ec2 describe-nat-gateways \ --filter "Name=subnet-id,Values=$VPC_2_PUBLIC_SUBNET_ID_2" \ --output text --query NatGateways[*].NatGatewayId)
- Add a route for the attachment subnet in VPC2 to direct internet traffic to the NAT gateway:
aws ec2 create-route --route-table-id $VPC_2_ATTACH_RT_ID_1 \ --destination-cidr-block 0.0.0.0/0 \ --nat-gateway-id $NAT_GW_ID_1 aws ec2 create-route --route-table-id $VPC_2_ATTACH_RT_ID_2 \ --destination-cidr-block 0.0.0.0/0 \ --nat-gateway-id $NAT_GW_ID_2
- Add a static route to the route tables associated with the public subnet in VPC2. This enables communication back to the TGW to allow sharing the NAT gateway with all attached VPCs:
aws ec2 create-route --route-table-id $VPC_2_PUBLIC_RT_ID_1 \ --destination-cidr-block 10.10.0.0/24 \ --transit-gateway-id $TGW_ID aws ec2 create-route --route-table-id $VPC_2_PUBLIC_RT_ID_2 \ --destination-cidr-block 10.10.0.0/24 \ --transit-gateway-id $TGW_ID
- Add a static route for the private subnets in VPC2 to allow communication back to the TGW attachments from VPC2 private subnets:
aws ec2 create-route --route-table-id $VPC_2_RT_ID_1 \ --destination-cidr-block 10.10.0.0/24 \ --transit-gateway-id $TGW_ID aws ec2 create-route --route-table-id $VPC_2_RT_ID_2 \ --destination-cidr-block 10.10.0.0/24 \ --transit-gateway-id $TGW_ID
- Get the transit route table ID:
TRAN_GW_RT=$(aws ec2 describe-transit-gateways \ --transit-gateway-ids $TGW_ID --output text \ --query TransitGateways[0].Options.AssociationDefaultRouteTableId)
- Add a static route in the Transit Gateway route table for VPC2 (with the NAT gateways) to send all internet traffic over this path:
aws ec2 create-transit-gateway-route \ --destination-cidr-block 0.0.0.0/0 \ --transit-gateway-route-table-id $TRAN_GW_RT \ --transit-gateway-attachment-id $TGW_ATTACH_2
Validation checks
Ensure your EC2 Instance 1 has registered with SSM. Use this command to check the status. This command should return the instance ID:
aws ssm describe-instance-information \
--filters Key=ResourceType,Values=EC2Instance \
--query "InstanceInformationList[].InstanceId" --output text
Connect to your EC2 instance using SSM Session Manager:
aws ssm start-session --target $INSTANCE_ID_1
Test internet access:
ping -c 4 aws.amazon.com
You should see output similar to the following:
PING dr49lng3n1n2s.cloudfront.net (99.86.187.73) 56(84) bytes of data.
64 bytes from server-99-86-187-73.iad79.r.cloudfront.net (99.86.187.73): icmp_seq=1 ttl=238 time=3.44 ms
64 bytes from server-99-86-187-73.iad79.r.cloudfront.net (99.86.187.73): icmp_seq=2 ttl=238 time=1.41 ms
64 bytes from server-99-86-187-73.iad79.r.cloudfront.net (99.86.187.73): icmp_seq=3 ttl=238 time=1.43 ms
64 bytes from server-99-86-187-73.iad79.r.cloudfront.net (99.86.187.73): icmp_seq=4 ttl=238 time=1.44 ms
--- dr49lng3n1n2s.cloudfront.net ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 1.411/1.934/3.449/0.875 ms
sh-4.2$
Exit the Session Manager session:
exit
Leave a Reply