How to Enable Cross VPC Connections With Transit Gateway Using AWS CLI

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 …

AWS VPC

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.

AWS Transit Gateway with 3 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

  1. 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>
  2. 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>
  3. 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)
  4. 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)
  5. 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)
  6. 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
  7. 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
  8. 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)
  9. 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
  10. 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
  11. 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
  12. 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)
  13. 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 Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.