AWS Transit Gateway — How to get started using the AWS CLI

If you’re designing or running in a multi-VPC or multi-account AWS architecture then you’re likely to need to communicate between resources in different VPCs or reach systems in an on-premise datacentre.

In the past, you had several options for creating this network connectivity. This ranged from creating a transit VPC with a hub-and-spoke network to a fully meshed network over VPC Peering with n-squared connections.

Today, AWS have released a new service that simplifies the challenge and complexities of creating and managing a distributed network.

AWS Transit Gateway (TGW) is a new networking service that will allow a very large number of VPCs to be connected with point-to-point peerings. What is different about this service is that you can also connect a site-to-site VPN to the gateway to allow the VPN connection to be shared across the connected VPCs. This means you no longer have to create new site-to-site VPNs for each new VPC that needs connectivity. VPCs and VPNs can dynamically propagate their routes to the Gateway route tables, and routes will be advertised over BGP when connecting pack to on-premises routers.

AWS Transit Gateway is easy to set up and integrates with native services for management and monitoring, including CloudFormation, CloudWatch, and VPC Flow Logs. Additionally, Gateways can be peered across different AWS regions which allows you to create a global distributed network. Security is covered by existing VPC controls like security groups and NACLs.

Creating a TGW

First, make sure you have the latest AWS CLI installed.

Use case 1 — single route table
Following these high-level steps to create a centralised TGW to interconnect all attached VPCs and VPNs.

The above diagram shows a Transit Gateway with a single default route table that all attachments will propagate their routes to. Attaching VPCs with overlapping subnet CIDRs is supported, but note that you can’t add identical routes.

First, create a Transit Gateway with default settings:
> aws ec2 create-transit-gateway

{
"TransitGateway": {
"OwnerId": "1234",
"State": "pending",
"Options": {
“DefaultRouteTableAssociation”: “enable”,
“AssociationDefaultRouteTableId”: “tgw-rtb-{default}”,
“PropagationDefaultRouteTableId”: “tgw-rtb-{default}”,
“AmazonSideAsn”: 64512,
“DefaultRouteTablePropagation”: “enable”
},
"TransitGatewayId": "tgw-1234"
}
}

The TGW will be created in a “pending” state while it is being provisioned. This will transition to “available” when it has been created.

> aws ec2 describe-transit-gateway — resource-owner self — transit-gateway-id tgw-1234

{
"TransitGateways": [{
"OwnerId": "1234",
"State": "available",
"Options": {
"DefaultRouteTableAssociation": "enable",
"AssociationDefaultRouteTableId": "tgw-rtb-1234",
"PropagationDefaultRouteTableId": "tgw-rtb-1234",
"AmazonSideAsn": 64512,
"DefaultRouteTablePropagation": "enable"
},
"TransitGatewayId": "tgw-1234567891234567",
"Tags": [] }]
}

Then, you can attach VPCs to the new TGW. The attachments will automatically propagate to the default route table.

> aws ec2 create-transit-gateway-vpc-attachment 
 — transit-gateway-id <tgw-id>
 — vpc-id <vpc-id>
 — subnet-ids <subnet-id-1> <subnet-id-2>

{
"TransitGatewayAttachment": {
“VpcId”: “vpc-0a12b0c34d0e56f”,
“TransitGatewayAttachmentId”: “tgw-attach-{vpc}”,
“SubnetIds”: [
“subnet-1234”,
“subnet-1235”
],
“State”: “pending”,
“TransitGatewayId”: “tgw-1234567891234567”
}
}

You can also attach VPNs to the new TGW with a new option in the create-vpn-connection CLI command.

> aws ec2 create-vpn-connection — customer-gateway-id <cgw-id> — transit-gateway-id <tgw-id> — type ipsec.1

Use the CLI to list the propagation details for attachments.

> aws ec2 get-transit-gateway-attachment-propagations — transit-gateway-attachment-id tgw-attach-<vpc-id>

{
"PropagatingRouteTableIds": [
"tgw-rt-{default}"
]
}

And similarly for route tables.

> aws ec2 get-transit-gateway-route-table propagations — transit-gateway-route-table-id tgw-rt-{route-table-id}

{
"TransitGatewayRouteTablePropagations": [{
"TransitGatewayRouteTablePropagation": {
"TransitGatewayAttachmentId": "tgw-attach-{vpc}",
"ResourceId": "vpc-0a12b0c34d0e56f,
"ResourceType": "vpc"
}
},
{
"TransitGatewayRouteTablePropagation": {
"TransitGatewayAttachmentId": "tgw-attach-{vpn}",
"ResourceId": "vpn-0733107331073311",
"ResourceType": "vpn"
}
}]
}

Use case 2 — multiple route tables
There may be a need to have multiple route tables, for example to run a Production domain separate to Non-Production. Multiple route tables may be created to separate these environments.

Running a set up like the diagram above will provide more flexibility, where routes and attachments may be moved between environments.

After creating your TGW, create a new route table

> aws ec2 create-transit-gateway-route-table — transit-gateway-id <tgw-id>

{
"TransitGatewayRouteTable": {
"State": "pending",
"TransitGatewayId": "tgw-1234567891234567",
"TransitGatewayRouteTableId": "tgw-rtb-{route-table-2}"
}
}

Given the example in the diagram above, say we now want to disassociate VPC A from the default route table, and associate it with our newly created route table.

List the associations to the default route table and note the AssociationId of VPC A.

> aws ec2 get-transit-gateway-route-table-associations — transit-gateway- route-table-id tgw-rtb-{route-table-default}

{
"Associations": [
{
"ResourceType": "vpc",
"ResourceId": "vpc-2343234",
"State": "associated",
"AssociationId": "tgw-rtbassoc-{vpc-A}",
"TransitGatewayAttachmentId": "tgw-attach-{vpc-A}"
},
{
"ResourceType": "vpc",
"ResourceId": "vpc-1246534",
"State": "associated",
"AssociationId": "tgw-rtbassoc-{vpc-B}",
"TransitGatewayAttachmentId": "tgw-attach-{vpc-B}",
},
{
"ResourceType": "vpc",
"ResourceId": "vpn-2587534",
"State": "associated",
"AssociationId": "tgw-rtbassoc-{vpc-C}",
"TransitGatewayAttachmentId": "tgw-attach-{vpc-C}"
},
{
"ResourceType": "vpc",
"ResourceId": "vpn-2587534",
"State": "associated",
"AssociationId": "tgw-rtbassoc-{vpn}",
"TransitGatewayAttachmentId": "tgw-attach-{vpn}"
}
}]
}

Now we can disassociate VPC A from the default route table

> aws ec2 disassociate-transit-gateway-route-table
 — association-id tgw-rtbassoc-{VPC A}

{
"Association": {
“State”: “disassociating”,
“AssociationId”: “tgw-rtassoc-{vpc-A}”,
“TransitGatewayRouteTableId”: “tgw-rtb-{route-table-default}”,
“TransitGatewayAttachmentId”: “tgw-attach-{vpc-A}"
}
}

To associate VPC A with the new route table, run the command like below

> aws ec2 associate-transit-gateway-route-table — transit-gateway-route-table-id tgw-rtb-{route-table-1} — transit-gateway-attachment-id tgw-attach-{VPC A}

We also need to enable the route propagation to the new route table, and disable it for the old route table

> aws ec2 enable-transit-gateway-route-propagation — transit-gateway-route-table-id tgw-rtb-{route-table-1} — transit-gateway-attachment-id tgw-attach-{VPC A}

{
"ReturnValue": "true"
}

> aws ec2 disable-transit-gateway-route-propagation — transit-gateway- route-table-id tgw-rtb-{route-table-default} — transit-gateway-attachment-id tgw-attach-{VPC A}

{
"ReturnValue": "true"
}

We can do the same to associate VPC B & C to the new route tables.

That’s all, now you have set up a transitive network using AWS Transit Gateway!

Check out the launch blog for more info.