こしあん
2025-03-08

AWS Transit Gatewayでのマルチリージョン接続とRoute Analyzer活用


7{icon} {views}


Transit Gatewayを用いた複数VPC・複数リージョン間の接続構成と、その設定手順を解説。Network ManagerのRoute Analyzerを併用することで、ルートのデバッグやブラックホール範囲の確認が無料で簡易に行える点が特徴。

はじめに

  • ANSで出てきた内容。複数のVPC間のメッシュ接続で便利なTransit Gatewayは、あくまでリージョン内のサービスである。つまり、北米リージョンと東京リージョンでTransit Gatewayを作る場合は、北米用のTransit Gatewayと東京用のTransit Gatewayを作らないといけない
  • Transit GatewayもVPCと同様にピアリングを引くことができ、リージョン間の接続は単純な場合だとピアリングを使う
  • それとは別に、Transit Gateway間の接続もデバッグ用のツールがあり、Network Managerにグローバルネットワークを作り、その中のTransit Gatewayネットワークのルートアナライザーが便利

アーキテクチャー図

  • 東京リージョン(ap-northeast-1)とバージニアリージョン(us-east-1)に3個のAZにまたがるVPCを2つずつ作る
  • リージョン内のVPCの接続はTransit Gatewayで行い、リージョン間はTransit Gatewayのピアリングで行う
  • 別途デバッグ用にNetwork Managerのグローバルネットワークを作り、Route Analyzerで分析する
    • コアネットワークを有効化しなければここは別途料金かからない
    • コアネットワークは直接ルートアナライザーに関係しない上に、有効化するとCloud WANを作ることになりこれが結構高い(0.5USD/hr)なので要注意

参考情報

VPC Reachablity Analyzerとの違い

通信のデバッグといえばReachablity Analyzerがあった。これとの違いは以下の通り(マルチアカウントは考慮しない)

ルートアナライザー Reachablity Analyzer
対象 Transit Gateway専用 VPCやインスタンス、インターネット・VPNゲートウェイなど各種対応
リージョン間の通信テスト 可能 不可能
インスタンス間の通信テスト 不可能 可能
IPを指定して通信テスト 可能 不可能
料金 無料 1回のテストで0.10USD

Transit Gatewayへの登録とピアリング

詳細は末尾のコードを見てほしいのだが、以下の2段階でできる。

Transit GatewayへのVPCの登録

これはリージョン内での話で普通のTransit Gatewayと同じ

  • VPCをTransit Gatewayにアタッチ
  • VPCのルートテーブルにTransit Gatewayを登録

Transit Gatewayのピアリング

今度はリージョン間のピアリングとルートテーブルの追加を行う

  • Transit Gatewayのピアリングのリクエストと承認を行う(VPCピアリングと同じ)
  • Transit Gatewayのルートテーブルに、相手方のリージョンのVPCを追加
  • VPCのルートテーブルに、相手方のリージョンのVPCを追加

Transit Gatewayのルートテーブルと、VPCのルートテーブルの両方をやらないといけないのがわかりづらい。サンプルコードでは3番目の処理はVPCのルートテーブルは総当たりで行っており、結局VPCピアリングでメッシュ張ってるのとそんなに変わらないが、VPCの数が増えるとこれはやってられなくなるので、IPの範囲を丸めたCIDRをVPCのルートテーブルやTransit Gatewayのルートに追加することになる。

CIDRを丸めると一定ブラックホール(通信がロスするIP範囲)が存在するので、そのテストも含めてRoute Analyzerが有効ですよというもの

結局ルートテーブルはどのようになるか

VPC側

VPC側のルートテーブル例。これは東京リージョンのVPC2の例

Transit Gateway側

Transit Gatewayへのルートテーブルは以下の通りになる。東京リージョンの例。VPCの登録と北米リージョンへのピアリングの両方がある。

デフォルトのルートテーブルに登録しているので、自動的に伝播が有効になる。

グローバルネットワークのRoute Analyzer

Network ManagerのRoute Analyzerの機能で、Transit Gatewayをまたいだ2つIP間の通信テストが可能。

事前準備

Network Managerにグローバルネットワークを登録しておく。これは完全に解析用

# モニタリング用のグローバルネットワーク
resource "aws_networkmanager_global_network" "global_network" {
  provider    = aws.jp
  description = "Global network for TGW analysis"
}

# Transit Gatewayの登録
resource "aws_networkmanager_transit_gateway_registration" "tgw_jp" {
  provider            = aws.jp
  global_network_id   = aws_networkmanager_global_network.global_network.id
  transit_gateway_arn = module.multi_vpc_region1.transit_gateway_arn
}

resource "aws_networkmanager_transit_gateway_registration" "tgw_us" {
  provider            = aws.us
  global_network_id   = aws_networkmanager_global_network.global_network.id
  transit_gateway_arn = module.multi_vpc_region2.transit_gateway_arn
}

グローバルネットワーク

以下のようなマップが表示される。マネジメントコンソールの時代にもよるかもしれないが、2025/3現在、ここにはRoute Analyzerはない

トポロジーグラフの機能もある。クリックでいじれるようで結構便利

トポロジーツリー。わかりやすい

Route Analyzerはどこか

マネジメントコンソールが非常にわかりづらいのだが、Transit Gatewayをグローバルネットワークにアタッチすると出てくる「Transit Gatewayネットワーク」の中にある。ここに「ルートアナライザー」がある。

送信元・送信先では、Transit Gatewayのほか、そのアタッチメント、IPアドレスを指定する。IPアドレスは実際にEC2などに付与されていないアドレスも指定可能(ブラックホールのデバッグに使えそうと言った理由はこれ)。

例えば、VPCやサブネットのCIDR範囲内にあるが、EC2に付与されていないIPアドレスを指定してテストすると接続に成功しているのがわかる。ルートテーブルのCIDRを丸めると、IP範囲の管理は楽になるものの、ブラックホールが出てその対応が本当にブラックボックスになってしまうのでそのデバッグに使ってくださいというものだろう。これが無料はありがたい。

EC2間の接続テスト

各VPCにWebサーバーを以下のようにデプロイする。北米リージョンも同様

# EC2インスタンス
resource "aws_instance" "web_server_jp" {
  provider = aws.jp
  for_each = {
    "jp-vpc1" = module.multi_vpc_region1.vpc1_private_subnet_ids
    "jp-vpc2" = module.multi_vpc_region1.vpc2_private_subnet_ids
  }

  ami                         = data.aws_ami.amazon_linux_jp.id
  instance_type               = "t3.micro"
  subnet_id                   = each.value[0]
  vpc_security_group_ids      = [aws_security_group.instance_sg_jp[each.key].id]
  iam_instance_profile        = aws_iam_instance_profile.ssm_instance_profile.name
  associate_public_ip_address = false

  user_data = <<-EOF
    #!/bin/bash
    dnf update -y
    dnf install -y httpd
    systemctl start httpd
    systemctl enable httpd
    TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
    INSTANCE_IP=$(hostname -I | awk '{print $1}')
    AVAILABILITY_ZONE=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/placement/availability-zone)
    INSTANCE_ID=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/instance-id)

    # 表示するHTMLページの作成
    cat > /var/www/html/index.html <<HTMLDOC
    <!DOCTYPE html>
    <html>
    <head>
        <title>VPC Information</title>
        <style>
            body { font-family: Arial, sans-serif; text-align: center; margin-top: 50px; }
            h1 { color: #333; }
            .info { background-color: #f5f5f5; padding: 20px; border-radius: 5px; margin: 20px auto; max-width: 600px; }
        </style>
    </head>
    <body>
        <h1>EC2 Instance Information</h1>
        <div class="info">
            <h2>${each.key}</h2>
            <p>Subnet ID: ${each.value[0]}</p>
            <p>Instance Private IP: $${INSTANCE_IP}</p>
            <p>Availability Zone: $${AVAILABILITY_ZONE}</p>
            <p>Instance ID: $${INSTANCE_ID}</p>
        </div>
    </body>
    </html>
    HTMLDOC
  EOF

  tags = {
    Name = "transit-instance-${each.key}"
  }
}

東京リージョンのVPC1のEC2に接続し、各リージョンの各VPC下にあるEC2にcurlを送る。

結果

以下のようにすべてのEC2に対してアクセスできた。ただわざわざこんな面倒なテストしなくてもRoute Analyzerで割とテストできますよ、という話。

## 東京リージョンのVPC1
sh-5.2$ curl http://10.10.4.59
<!DOCTYPE html>
<html>
<head>
    <title>VPC Information</title>
    <style>
        body { font-family: Arial, sans-serif; text-align: center; margin-top: 50px; }
        h1 { color: #333; }
        .info { background-color: #f5f5f5; padding: 20px; border-radius: 5px; margin: 20px auto; max-width: 600px; }
    </style>
</head>
<body>
    <h1>EC2 Instance Information</h1>
    <div class="info">
        <h2>jp-vpc1</h2>
        <p>Subnet ID: subnet-09bb0aa20b0fe606e</p>
        <p>Instance Private IP: 10.10.4.59</p>
        <p>Availability Zone: ap-northeast-1a</p>
        <p>Instance ID: i-063c30e0250798e81</p>
    </div>
</body>
</html>

## 東京リージョンのVPC2
sh-5.2$ curl http://10.10.21.85
<!DOCTYPE html>
<html>
<head>
    <title>VPC Information</title>
    <style>
        body { font-family: Arial, sans-serif; text-align: center; margin-top: 50px; }
        h1 { color: #333; }
        .info { background-color: #f5f5f5; padding: 20px; border-radius: 5px; margin: 20px auto; max-width: 600px; }
    </style>
</head>
<body>
    <h1>EC2 Instance Information</h1>
    <div class="info">
        <h2>jp-vpc2</h2>
        <p>Subnet ID: subnet-0a3475c54ca9a5a8f</p>
        <p>Instance Private IP: 10.10.21.85</p>
        <p>Availability Zone: ap-northeast-1a</p>
        <p>Instance ID: i-033255001e9db4ab0</p>
    </div>
</body>
</html>

## 北米リージョンのVPC1
sh-5.2$ curl http://10.11.4.207
<!DOCTYPE html>
<html>
<head>
    <title>VPC Information</title>
    <style>
        body { font-family: Arial, sans-serif; text-align: center; margin-top: 50px; }
        h1 { color: #333; }
        .info { background-color: #f5f5f5; padding: 20px; border-radius: 5px; margin: 20px auto; max-width: 600px; }
    </style>
</head>
<body>
    <h1>EC2 Instance Information</h1>
    <div class="info">
        <h2>us-vpc1</h2>
        <p>Subnet ID: subnet-077328487f427d44b</p>
        <p>Instance Private IP: 10.11.4.207</p>
        <p>Availability Zone: us-east-1a</p>
        <p>Instance ID: i-0b4f8dc98d19a672b</p>
    </div>
</body>
</html>

## 北米リージョンのVPC2
sh-5.2$ curl http://10.11.20.112
<!DOCTYPE html>
<html>
<head>
    <title>VPC Information</title>
    <style>
        body { font-family: Arial, sans-serif; text-align: center; margin-top: 50px; }
        h1 { color: #333; }
        .info { background-color: #f5f5f5; padding: 20px; border-radius: 5px; margin: 20px auto; max-width: 600px; }
    </style>
</head>
<body>
    <h1>EC2 Instance Information</h1>
    <div class="info">
        <h2>us-vpc2</h2>
        <p>Subnet ID: subnet-05f1758099c3f7907</p>
        <p>Instance Private IP: 10.11.20.112</p>
        <p>Availability Zone: us-east-1a</p>
        <p>Instance ID: i-07e492c3aadb7dcf4</p>
    </div>
</body>
</html>

ソースコード

全体のソースコードは長いのでGitHubにあげている

https://github.com/koshian2/transit-gateway-peering-route-analyzer

所感

  • これを使う日はいつになるのだろうという気がするが、普通に便利そうだった


Shikoan's ML Blogの中の人が運営しているサークル「じゅ~しぃ~すくりぷと」の本のご案内

技術書コーナー

北海道の駅巡りコーナー


Add a Comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です