AWS Transit Gateway を使ってみるメモ

Transit Gateway (TGW) を使ったことが無かったので、試しに使ってみました。残骸はこちら

Direct Connect や VPN Connection では簡単には試せないので VPC と Transit Gateway Peering のみ試しています。

構成要素

TGW の構成要素について。

アタッチメント(Attachment)

TGW にアタッチされた VPC、Direct Connect、Transit Gateway Peering、VPN Connection です。

1つの TGW に複数の接続をアタッチして TGW でルーティングすることで、それらの接続の間で相互に通信できるようになります。

ルートテーブル

TGW はルートテーブルを持ちます。宛先IPアドレスに基づいてどのアタッチメントへトラフィックを送るかが決定されます。

ルートテーブルは複数作成できます。アタッチメントごとにどのルートテーブルを関連付けるかを変えることができます。1つの TGW に複数の接続をアタッチしているとき、関連付けるルートテーブルをアタッチメントによって変えることでネットワークを分離することが出来ます。

TGW の作成時に Default association route tableDefault propagation route table のどちらかを有効にしているとデフォルトルートテーブルが1つ作成されます。両方とも無効だとデフォルトルートテーブルは作成されません。

Default association route table を有効にしていると、TGW にアタッチされた新規のアタッチメントは自動的にデフォルトルートテーブルに関連付けられます。

Default propagation route table を有効にしていると、TGW にアタッチされた新規のアタッチメントは自動的にデフォルトルートテーブルへのルート伝播が有効になります。

ルート伝播

アタッチメントでルート伝播を有効にすると、そのアタッチメントを宛先とする CIDR のルートが指定したルートテーブルに伝播されるようになります。

例えば VPC のアタッチメントでルート伝播を有効にすると、その VPC の CIDR を宛先とするトラフィックがその VPC に向かうようにルートテーブルに伝播されます。

アタッチメントが関連付けられていないルートテーブルへ伝播させることも可能です。例: 隔離された VPC - Amazon Virtual Private Cloud のような構成ではそうなります。また、1つのアタッチメントから複数のルートテーブルへ伝播させることも可能です。

なお、VPC のルートテーブルへ TGW へのルートを伝播できません。なので VPC のルートテーブルには TGW へのルートを静的に設定する必要があります。

ピアリング接続

TGW に接続できる VPC は同じリージョンのものだけですが、異なるリージョンの TGW 同士をピアリング接続すればリージョン間でも通信できるようになります。

TGW ピアリング接続のルートは TGW のルートテーブルへ伝播させることは出来ません。なので、TGW ピアリング接続でリージョン間の VPC で通信できるようにするためには、TGW ルートテーブルへの TGW ピアリング接続へのルート、VPC のルートテーブルへの TGW へのルート、の両方を静的に設定する必要があります。

その他注意点

試していた中で気づいたことなど。

apne1-az3 では使えない

一部の AWS アカウントでのみ利用可能な AZ である apne1-az3 だと TGW が使えません。

ので、次のように Terraform で利用可能な AZ を全部取得していると失敗します。

data aws_availability_zones available {
  state = "available"
}

しかたないので ID 指定で除外するようにしました。

data aws_availability_zones available {
  state            = "available"
  exclude_zone_ids = ["apne1-az3"]
}

Terraform でのピアリング接続のリクエスタとアスペクタの ID

VPC ピアリング接続でも同じだったと思いますが、TGW ピアリング接続を Terraform で作るとき、リクエスタとなる aws_ec2_transit_gateway_peering_attachment の ID と、アスペクタである aws_ec2_transit_gateway_peering_attachment_accepter の ID は同じ値になります。

がしかし、アスペクタの transit_gateway_attachment_id に指定するとき以外は、基本的にアスペクタの ID を使うほうが良いです。

というのも aws_ec2_transit_gateway_peering_attachmentaws_ec2_transit_gateway_peering_attachment_accepter ではリソースの作成が完了したとみなされるタイミングが異なるためです。

aws_ec2_transit_gateway_peering_attachment の場合は pending になってアスペクタの受け入れ待ちになった時点でリソースの作成が完了したことになります。

aws_ec2_transit_gateway_peering_attachment_accepter の場合はピアリングを受け入れてアタッチメントが available になった時点でリソースの作成が完了したことになります。

例えばピアリング接続のアタッチメントへの経路をルートテーブルに登録するための前者の ID を使用すると、アタッチメントが利用可能になる前にルートテーブルに登録しようとして、

Error: error creating EC2 Transit Gateway Route: IncorrectState: tgw-attach-xxxxxxxxxxxxxxxxx is in invalid state

などとエラーになります。しばらく待ってから再実行すると成功してしまうので、なかなか気づきにくく厄介です。

後者の ID を使用していれば、ピアリング接続が受け入れられて available になるまで待ってくれるので大丈夫です。

もしくは、前者の ID を指定しつつ、depends_onaws_ec2_transit_gateway_peering_attachment_accepter を指定する、という方法も考えられます。どちらでも良いと思いますが、もしかしたら depends_on を使うほうが明示的で良いかもしれません。

さいごに

VPC ピアリング接続であれば費用は AZ 間やリージョン間の転送量しかかからないのに対して、TGW だと転送量以外にアタッチメントごとの費用がかかるのと、転送量に掛かる費用も若干大きいので、VPC だけであればよほどメッシュにならない限りは VPC ピアリングで十分な気もしますが、TGW の方が構成はシンプルで運用コストは小さく済みそうです(ただし Direct Connect が絡むならだいぶ話は変わってくる)。