実践!AWS Transit Gateway を分離環境と共通環境に分けた構成パターン #reinvent

re:Invent が終わって、はや1週間。各所で re:Invent 報告会が行われている今日このごろですが、みなさん時差ボケはなおりましたか。私は夜型の生活からなかなか戻れておりませぬ。。

さて、東京リージョンのリリースが待ち遠しい AWS Transit Gateway も、使ってみた系の記事が多く見られ、その注目度の高さが伺えます。とりあえず試すには、デフォルトルートテーブル1つで、すべての VPC/VPN を Any-to-Any で接続してしまうのが手っ取り早く、検証記事も書きやすいのですが、実運用を考えると Any-to-Any というのは考えにくいです。Deep Dive セッションなどを観て、「ふむふむ。ルートテーブルで環境分離するんだね」ということは理解していたのですが、実際どうやるんかなー、というのが気になったので、試してみました。 というのが、今回の記事です。

構成図

今回作ってみた環境は、こんな感じです。

  • オンプレ環境はないので、VyOS を使って疑似環境として VPN 接続しています。
  • VPN および、共通環境からはすべての VPC/VPN への通信が可能です。
  • 分離環境として VPC1、VPC2 を作成しました。例えば、VPC1 からは VPN と共通環境への通信は可能ですが、VPC2 への通信は出来ません。(VPC2 からの場合は VPC1 に通信できません)

ざっくり、やりたいことを理解いただいたかと思いますので、それでは試していきましょう!

やってみた

おおまかに以下のことをやります。作業の順番については、これが must ではないので、やりやすいように変えてください。

  • Transit Gateway の作成
  • Transit Gateway ルートテーブルの作成
  • Transit Gateway アタッチメントの作成
  • Transit Gateway の関連付けとルート伝播の設定
  • VPC ルートテーブルの設定
  • 疎通確認

Transit Gateway の作成

Create Transit Gateway から Transit Gateway(以降、TGW) の作成を行います。とりあえず使ってみた系の記事では、Default route table associationDefault route table propagation がデフォルトのチェック状態のまま作成されていると思いますが、今回は Any-to-Any ではない環境を作りたいので、この 2 箇所のチェックを外して作成します。

すると、このように Association route table IDPropagation route table ID が空っぽの状態の TGW が出来上がります。

Transit Gateway ルートテーブルの作成

次に、TGW のルートテーブルを作成します。Transit Gateway Route Tables のコンソールを開き、Create Transit Gateway Route Table をクリックします。名前と、先程作成した TGW ID を指定するだけです。

ここでは 2 つのルートテーブルを作成しました。

  • 共通環境用のルートテーブル(VPN、共通サービス VPC が使います)
  • 分離環境用のルートテーブル(VPC1、VPC2 が使います)

Transit Gateway アタッチメントの作成

次に TGW のアタッチメントを作成します。Transit Gateway Attachments のコンソールを開き、Create Transit Gateway Attachment をクリックします。今回、オンプレ想定環境は VPC 上に作成していますが、VPN 接続で検証を行いたいため、VPN タイプを選択します。カスタマーゲートウェイも新規作成しますので New を選び、VPN ルータのパブリック IP を指定します。あと、VPN は BGP を使用したいので Dynamic を選択し、作成します。

カスタマーゲートウェイが作成されていますので、VPN 接続のコンソールを開き、設定のダウンロード から Config をダウンロードし、VPN ルータに適用します。

次に、VPC タイプの TGW アタッチメントを作成しますので、再度、Transit Gateway Attachments のコンソールを開き、Create Transit Gateway Attachment をクリックします。VPC タイプを選択します。今回、オンプレの疑似環境を除いて 3 つの VPC がありますので、3 つのアタッチメントをそれぞれ作成します。サブネットの指定ですが、1 AZ につき 1 サブネットしか指定できませんので、設計時にはご注意ください。

これで、1 つの VPN アタッチメント、3 つの VPC アタッチメントが作成できました。

Transit Gateway の関連付けとルート伝播の設定

それでは、関連付けとルート伝播設定を行っていきましょう。Transit Gateway Route Tables のコンソールを開き、まずは共有サービス用のルートテーブルから設定していきます。対象の TGW ルートテーブルを選択し、Associations タブから、Create association をクリックします。

関連付ける TGW アタッチメントを選択し、関連付けを行います。

共通環境用の TGW ルートテーブルには、VPN アタッチメントと、共通サービス VPC アタッチメントを関連付けています。

同じ手順で、分離環境用の TGW ルートテーブルには、VPC1 アタッチメント、VPC2 アタッチメントを関連付けています。

次に、ルート伝播の設定を行います。まず共通環境用のルートテーブルを選択し、Propagations タブを開き、Create propagation をクリックします。関連付けのときと同様に、ルート伝播するアタッチメントを選択し、設定します。

共通環境用には、関連付けと同じ VPN アタッチメントと、共通サービス VPC アタッチメントに加えて、VPC1 アタッチメント、VPC2 アタッチメントを設定しています。

次にルートの設定ですが、今回の対象はすべてルート伝播により自動登録されています。手動登録する場合は、Routes タブから、Create route をクリックし、以下のように対象の CIDR と アタッチメントを指定し、作成します。(TGW ではブラックホールのルーティングが許容されており、強制的にドロップさせたい場合はブラックホールにチェックを入れます)

共通環境用のルートテーブルは以下のようになりました。

今回は VPN アタッチメントを Dynamic(BGP) で作成していますので、このルートテーブルは VPN ルータ側にも伝播されています。

$ sho ip bgp
BGP table version is 0, local router ID is 172.16.0.18
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,
              r RIB-failure, S Stale, R Removed
Origin codes: i - IGP, e - EGP, ? - incomplete

   Network          Next Hop            Metric LocPrf Weight Path
*> 172.16.0.0/27    0.0.0.0                  1         32768 i
*  192.168.0.0      169.254.47.45          100             0 64512 e
*>                  169.254.46.197         100             0 64512 e
*  192.168.10.0     169.254.47.45          100             0 64512 e
*>                  169.254.46.197         100             0 64512 e
*  192.168.20.0     169.254.47.45          100             0 64512 e
*>                  169.254.46.197         100             0 64512 e

分離環境用のルートテーブルも同様にルート伝播と、ルート設定を行います。こちらは、VPN と 共通サービス VPC のみが対象となりますので、ルート伝播設定は下記のとおりです。

ルートテーブルは以下のようになります。

VPC ルートテーブルの設定

VPC ルートテーブルは以下のようになっています。 VPC1、VPC2 のルートテーブルでは、共通サービス VPC の 192.168.0.0/24 のみに限定しても良いのですが、今回は TGW ルートテーブルを参照しても、VPC1、VPC2 間で疎通できないことを確認する意味でも、すべての VPC を包含する CIDR で指定しました。

VPC1 用

VPC2 用

共通サービス用

オンプレ想定用

192.168.0.0/16eni に向けているのは、VyOS で VPN を設定している関係上、戻りのルートが必要だったためです。TGW とは関係ないので、読み流していただいて結構です。

Transit Gateway 利用時の VPC ルートテーブル設計(思いつき)

先程、VPC1, VPC2 間が TGW ルートテーブルを参照しても疎通できないことを確認するため、と書きましたが、設計の観点でもう 1 つ理由あります。それは、今後 VPC がスケールしていくことを考慮する場合、このように設定しているほうが、TGW ルートテーブル側でコントロールできるというメリットがあります。

たとえば、VPC 毎の CIDR でキッチリ指定している場合、仮に共通サービスが増えて VPC が新設されたとします。その場合、VPC 毎にあらたな CIDR のルートを追加設定してまわる必要があります。既存で 10、20 の VPC がある場合どうします、、。これって Transit Gateway がリリースされる前の手間とあまり変わらないのではないでうしょか??なので、可能であるなら TGW のルートテーブルでコントロールできる設計に寄せておいたほうが、後々の VPC 拡張時の対応負荷が減るんじゃないかと思います。

TGW を使うメリットの一部として、複雑な VPC 環境の運用管理コスト削減があると思いますので、そこを潰してしまわないように考慮した設計がポイントになりそうですね。

疎通確認

結論としては、想定どおり VPC1 → VPC2 もしくは VPC2 → VPC1 のみが疎通不可となり、共通環境についてはすべて疎通 OK でした。結果ログは最後に掲載しておきます。

さいごに

これまでデフォルトルートテーブルでしか TWG を触っていなかったのですが、今回、分離環境と共通環境とを区別して TGW ルートテーブルを作ってみたことで、より実用的な使い方がわかりました。本当は、共通サービスも動かしたうえで確認したいことがあったのですが、ひとまずは疎通確認まで! ということで今回は締めたいと思います。共通サービスについては、また別記事としてご紹介します!

以上!大阪オフィスの丸毛(@marumo1981)でした!

付録:疎通結果ログ

オンプレ(想定)環境から (すべて疎通 OK)

$ ping -c 3 192.168.0.12
PING 192.168.0.12 (192.168.0.12) 56(84) bytes of data.
64 bytes from 192.168.0.12: icmp_seq=1 ttl=252 time=3.70 ms
64 bytes from 192.168.0.12: icmp_seq=2 ttl=252 time=2.79 ms
64 bytes from 192.168.0.12: icmp_seq=3 ttl=252 time=2.63 ms
--- 192.168.0.12 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 2.638/3.045/3.705/0.470 ms

$ ping -c 3 192.168.10.51
PING 192.168.10.51 (192.168.10.51) 56(84) bytes of data.
64 bytes from 192.168.10.51: icmp_seq=1 ttl=252 time=2.78 ms
64 bytes from 192.168.10.51: icmp_seq=2 ttl=252 time=2.35 ms
64 bytes from 192.168.10.51: icmp_seq=3 ttl=252 time=2.20 ms
--- 192.168.10.51 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 2.201/2.447/2.783/0.249 ms

$ ping -c 3 192.168.20.23
PING 192.168.20.23 (192.168.20.23) 56(84) bytes of data.
64 bytes from 192.168.20.23: icmp_seq=1 ttl=252 time=3.00 ms
64 bytes from 192.168.20.23: icmp_seq=2 ttl=252 time=5.68 ms
64 bytes from 192.168.20.23: icmp_seq=3 ttl=252 time=2.35 ms
--- 192.168.20.23 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 2.359/3.681/5.684/1.441 ms

共有サービス環境から (すべて疎通 OK)

$ ping -c 3 172.16.0.17
PING 172.16.0.17 (172.16.0.17) 56(84) bytes of data.
64 bytes from 172.16.0.17: icmp_seq=1 ttl=253 time=3.88 ms
64 bytes from 172.16.0.17: icmp_seq=2 ttl=253 time=2.96 ms
64 bytes from 172.16.0.17: icmp_seq=3 ttl=253 time=3.47 ms
--- 172.16.0.17 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 2.963/3.440/3.887/0.383 ms

$ ping -c 3 192.168.10.51
PING 192.168.10.51 (192.168.10.51) 56(84) bytes of data.
64 bytes from 192.168.10.51: icmp_seq=1 ttl=254 time=2.06 ms
64 bytes from 192.168.10.51: icmp_seq=2 ttl=254 time=0.969 ms
64 bytes from 192.168.10.51: icmp_seq=3 ttl=254 time=0.920 ms
--- 192.168.10.51 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2001ms
rtt min/avg/max/mdev = 0.920/1.318/2.067/0.531 ms

$ ping -c 3 192.168.20.23
PING 192.168.20.23 (192.168.20.23) 56(84) bytes of data.
64 bytes from 192.168.20.23: icmp_seq=1 ttl=254 time=0.892 ms
64 bytes from 192.168.20.23: icmp_seq=2 ttl=254 time=0.281 ms
64 bytes from 192.168.20.23: icmp_seq=3 ttl=254 time=0.268 ms
--- 192.168.20.23 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2049ms
rtt min/avg/max/mdev = 0.268/0.480/0.892/0.291 ms

VPC1から (VPC2 のみ疎通不可)

$ ping -c 3 172.16.0.17
PING 172.16.0.17 (172.16.0.17) 56(84) bytes of data.
64 bytes from 172.16.0.17: icmp_seq=1 ttl=253 time=3.35 ms
64 bytes from 172.16.0.17: icmp_seq=2 ttl=253 time=2.34 ms
64 bytes from 172.16.0.17: icmp_seq=3 ttl=253 time=2.56 ms
--- 172.16.0.17 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 2.346/2.756/3.353/0.431 ms

$ ping -c 3 192.168.0.12
PING 192.168.0.12 (192.168.0.12) 56(84) bytes of data.
64 bytes from 192.168.0.12: icmp_seq=1 ttl=254 time=2.02 ms
64 bytes from 192.168.0.12: icmp_seq=2 ttl=254 time=0.988 ms
64 bytes from 192.168.0.12: icmp_seq=3 ttl=254 time=1.02 ms
--- 192.168.0.12 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 0.988/1.343/2.020/0.480 ms

$ ping -c 3 192.168.20.23
PING 192.168.20.23 (192.168.20.23) 56(84) bytes of data.
--- 192.168.20.23 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2029ms

VPC2から (VPC1 のみ疎通不可)

$ ping -c 3 172.16.0.17
PING 172.16.0.17 (172.16.0.17) 56(84) bytes of data.
64 bytes from 172.16.0.17: icmp_seq=1 ttl=253 time=3.35 ms
64 bytes from 172.16.0.17: icmp_seq=2 ttl=253 time=2.43 ms
64 bytes from 172.16.0.17: icmp_seq=3 ttl=253 time=2.46 ms
--- 172.16.0.17 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 2.430/2.749/3.353/0.431 ms

$ ping -c 3 192.168.0.12
PING 192.168.0.12 (192.168.0.12) 56(84) bytes of data.
64 bytes from 192.168.0.12: icmp_seq=1 ttl=254 time=0.962 ms
64 bytes from 192.168.0.12: icmp_seq=2 ttl=254 time=0.214 ms
64 bytes from 192.168.0.12: icmp_seq=3 ttl=254 time=0.233 ms
--- 192.168.0.12 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2034ms
rtt min/avg/max/mdev = 0.214/0.469/0.962/0.349 ms

$ ping -c 3 192.168.10.51
PING 192.168.10.51 (192.168.10.51) 56(84) bytes of data.
--- 192.168.10.51 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2034ms