クロスリージョンのVPC間通信をTransit Gatewayでやってみた

クロスリージョンのVPC間通信をTransit Gatewayでやってみた

Clock Icon2025.02.13

同じリージョン内のVPCをTransit Gatewayで接続して通信するということはやったことがあるのですが、クロスリージョンの場合は設定の方法は知っていても実際にやったことは無かったのでやってみました。

やること

東京リージョンと大阪リージョンにVPCを作成してTransit Gateway経由で各リージョンのEC2から対向のリージョンのEC2へpingで疎通できることを確認します。
Transit Gatewayの設定は以下のドキュメントを参考に進めていきます。
https://docs.aws.amazon.com/ja_jp/prescriptive-guidance/latest/patterns/peer-vpcs-different-regions-transit-gateway.html

構成

構成としては以下の画像の通りとなります。
東京リージョンと大阪リージョンにVPCを作成して各リージョンのTransit Gatewayをピアリング後にルートテーブルを設定して相互に通信できるように設定を行います。
VPCと疎通確認用EC2はCloudFormationで作成してTransit Gatewayはマネジメントコンソールから設定してみたいと思います。
TransitGatewayクロスリージョン_202502121727

設定

疎通確認用EC2作成

まずは東京リージョンと大阪リージョンにVPCと疎通確認用EC2を作成します。
VPCとEC2の作成は以下のCloudFormationテンプレートで行います。

AWSTemplateFormatVersion: "2010-09-09"

Description: vpc,ec2 stack

Mappings:
# ------------------------------------------------------------#
# Mappings
# ------------------------------------------------------------# 
  RegionMap:
    ap-northeast-3:
      VPCCIDR: 10.1.0.0/16
      AvailabilityZone: ap-northeast-3a
      PrvSubnet1CIDR: 10.1.0.0/24
      PrvSubnet2CIDR: 10.1.1.0/24
      SecurityGroupCIDR: 10.0.1.0/24
    ap-northeast-1:
      VPCCIDR: 10.0.0.0/16
      AvailabilityZone: ap-northeast-1a
      PrvSubnet1CIDR: 10.0.0.0/24
      PrvSubnet2CIDR: 10.0.1.0/24
      SecurityGroupCIDR: 10.1.1.0/24

Metadata:
# ------------------------------------------------------------#
# Metadata
# ------------------------------------------------------------# 
  AWS::CloudFormation::Interface:
    ParameterGroups:
        Parameters:
          - EC2VolumeSize
          - EC2VolumeIOPS
          - EC2AMI
          - EC2InstanceType

Parameters:
# ------------------------------------------------------------#
# Parameters
# ------------------------------------------------------------# 
  EC2VolumeSize:
    Default: 32
    Type: Number

  EC2VolumeIOPS:
    Default: 3000
    Type: Number

  EC2AMI:
    Default: '/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-x86_64'
    Type: 'AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>'

  EC2InstanceType:
    Default: t3.micro
    Type: String

Resources:
# ------------------------------------------------------------#
# VPC
# ------------------------------------------------------------# 
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !FindInMap
        - RegionMap 
        - !Ref 'AWS::Region'
        - VPCCIDR
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags: 
        - Key: Name
          Value: test-vpc

# ------------------------------------------------------------#
# Subnet
# ------------------------------------------------------------# 
  PrivateSubnet01:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: !FindInMap
        - RegionMap 
        - !Ref 'AWS::Region'
        - AvailabilityZone
      CidrBlock: !FindInMap
        - RegionMap 
        - !Ref 'AWS::Region'
        - PrvSubnet1CIDR
      Tags: 
        - Key: Name
          Value: test-private-01
      VpcId: !Ref VPC

  PrivateSubnet02:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: !FindInMap
        - RegionMap 
        - !Ref 'AWS::Region'
        - AvailabilityZone
      CidrBlock: !FindInMap
        - RegionMap 
        - !Ref 'AWS::Region'
        - PrvSubnet2CIDR
      Tags: 
        - Key: Name
          Value: test-private-02
      VpcId: !Ref VPC

# ------------------------------------------------------------#
# RouteTable
# ------------------------------------------------------------# 
  PrivateRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: test-private-rtb

  PrivateRtAssociation1:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PrivateRouteTable
      SubnetId: !Ref PrivateSubnet01

  PrivateRtAssociation2:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PrivateRouteTable
      SubnetId: !Ref PrivateSubnet02

# ------------------------------------------------------------#
# Security Group
# ------------------------------------------------------------# 
  EC2SG:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: for EC2
      GroupName: EC2-sg
      SecurityGroupEgress: 
        - CidrIp: 0.0.0.0/0
          FromPort: -1
          IpProtocol: -1
          ToPort: -1
      SecurityGroupIngress: 
        - CidrIp: !FindInMap
            - RegionMap
            - !Ref 'AWS::Region'
            - SecurityGroupCIDR
          FromPort: -1
          IpProtocol: icmp
          ToPort: -1
      Tags: 
        - Key: Name
          Value: ec2-sg
      VpcId: !Ref VPC

  VPCEndpointSG:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: for VPC Endpoint
      GroupName: vpcendpoint-sg
      SecurityGroupEgress: 
        - CidrIp: 0.0.0.0/0
          FromPort: -1
          IpProtocol: -1
          ToPort: -1
      SecurityGroupIngress: 
        - SourceSecurityGroupId: !Ref EC2SG
          FromPort: 443
          IpProtocol: tcp
          ToPort: 443
      Tags: 
        - Key: Name
          Value: vpcendpoint-sg
      VpcId: !Ref VPC

# ------------------------------------------------------------#
# VPC Endpoint
# ------------------------------------------------------------# 
  SystemsManagerEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      ServiceName: !Sub com.amazonaws.${AWS::Region}.ssm
      VpcId: !Ref VPC
      SubnetIds:
        - !Ref PrivateSubnet01
      SecurityGroupIds:
        - !Ref VPCEndpointSG

  SystemsManagerMessageEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      ServiceName: !Sub com.amazonaws.${AWS::Region}.ssmmessages
      VpcId: !Ref VPC
      SubnetIds:
        - !Ref PrivateSubnet01
      SecurityGroupIds:
        - !Ref VPCEndpointSG

# ------------------------------------------------------------#
# IAM
# ------------------------------------------------------------# 
  EC2IAMRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument: 
        Version: "2012-10-17"
        Statement: 
          - Effect: Allow
            Principal: 
              Service: 
                - ec2.amazonaws.com
            Action: 
              - 'sts:AssumeRole'
      ManagedPolicyArns: 
        - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
      RoleName: !Sub iam-role-ec2-${AWS::Region}
      Tags:
        - Key: Name
          Value: !Sub iam-role-ec2-${AWS::Region}

  EC2IAMInstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      InstanceProfileName: !Sub iam-instanceprofile-ec2-${AWS::Region}
      Roles: 
        - !Ref EC2IAMRole

# ------------------------------------------------------------#
# EC2
# ------------------------------------------------------------# 
  EC2:
    Type: AWS::EC2::Instance
    Properties:
      BlockDeviceMappings: 
        - DeviceName: /dev/xvda
          Ebs:
            DeleteOnTermination: true
            Encrypted: true
            Iops: !Ref EC2VolumeIOPS
            VolumeSize: !Ref EC2VolumeSize
            VolumeType: gp3
      DisableApiTermination: false
      IamInstanceProfile: !Ref EC2IAMInstanceProfile
      ImageId: !Ref EC2AMI
      InstanceType: !Ref EC2InstanceType
      NetworkInterfaces: 
        - DeleteOnTermination: true
          DeviceIndex: 0
          GroupSet: 
            - !Ref EC2SG
          SubnetId: !Ref PrivateSubnet02
      Tags:
        - Key: Name
          Value:  !Sub test-ec2-${AWS::Region}

上記のCloudFormationテンプレートの110行目~128目でサブネットにルートテーブルを紐づけています。
Transit Gateway作成後にこのルートテーブルに対向のVPCのCIDR宛ルートを追加します。
疎通確認用EC2にはSystems Manager Session Managerで接続するのでSystems ManagerのVPCエンドポイントを作成しています。

CloudFormationテンプレートファイルを作成したら以下のAWS CLIコマンドを実行して東京リージョンと大阪リージョンにデプロイします。

# 東京リージョンへのデプロイ
aws cloudformation create-stack --stack-name スタック名 --template-body file://CloudFormationテンプレートファイル名 --capabilities CAPABILITY_NAMED_IAM --region ap-northeast-1

# 大阪リージョンへのデプロイ
aws cloudformation create-stack --stack-name スタック名 --template-body file://CloudFormationテンプレートファイル名 --capabilities CAPABILITY_NAMED_IAM --region ap-northeast-3

コマンド実行後、しばらくすると各リージョンにEC2が起動していることが確認できます。
起動していることが確認できたら下準備は完了です。
スクリーンショット 2025-02-13 131019

スクリーンショット 2025-02-13 131058

Transit Gateway作成

疎通確認用EC2が作成できたらTransit Gatewayを作成していきます。

東京リージョン

マネジメントコンソールからVPCのダッシュボードに移動後、画面左のメニューから「Transit Gateway」をクリックします。
画面遷移後、「Transit Gatewayを作成」をクリックします。
スクリーンショット 2025-02-13 131929

設定画面が表示されたら「名前タグ」と「説明」にわかりやすいもの (リージョンごとに識別しやすいものを入れるとよいです) を入力して「Amazon 側の自律システム番号 (ASN)」に64512と入力します。
上記で設定した内容以外はデフォルトのまま、画面下にある「Transit Gatewayを作成」をクリックします。
スクリーンショット 2025-02-13 132633

余談ですが、「Transit Gateway を設定」欄にあった設定は以下のような意味になります。

設定名 内容
DNS サポート Transit Gatewayに接続されたVPCからパブリックIPv4 DNS名を名前解決したときにプライベートIPアドレスに名前解決できるようにする設定です。
例えばVPC AのEC2からVPC BのEC2インスタンスのパブリックIPv4 DNS名を名前解決した際にプライベートIPアドレスに名前解決することが可能になります。
セキュリティグループ参照サポート 別のVPCに紐づいているセキュリティグループをセキュリティグループのインバウンドルールで参照させることが可能になる設定です。
制限などもあるので、以下のブログを参考にしてみてください。
https://dev.classmethod.jp/articles/general-availability-security-group-referencing-aws-transit-gateway/
VPN ECMP サポート VPNトンネル間で等コストマルチパスルーティングを使用する際に必要な設定です。
デフォルトルートテーブルの関連付け Transit Gatewayアタッチメントを作成した際にデフォルトのルートテーブルを自動的に紐づける設定です。
デフォルトルートテーブル伝播 Transit Gatewayアタッチメントを作成した際にデフォルトのルートテーブルにアタッチメントへのルートを伝播する設定です。
マルチキャストサポート マルチキャスト通信を行う際に必要な設定です。

「Transit Gatewayを作成」をクリック後、5分くらいで作成が完了します。
スクリーンショット 2025-02-13 140317

Transit Gatewayが作成できたらTransit Gateway アタッチメントを作成します。
画面左のメニューから「Transit Gateway アタッチメント」をクリックして「Transit Gateway アタッチメントを作成」をクリックします。
スクリーンショット 2025-02-13 141338

設定画面が表示されたら「名前タグ」、「Transit Gateway ID」、「VPC ID」、「サブネット ID」を設定します。
「名前タグ」は識別しやすいものを入力してください。
「Transit Gateway ID」は上記の手順で作成したTransit Gatewayを選択してください。
「VPC ID」はCloudFormationで作成したVPCを選択してください。
「サブネット ID」は「test-private-01」を選択してください。
設定をしたら画面下の「Transit Gatewayアタッチメントを作成」をクリックします。
スクリーンショット 2025-02-13 141601

「Transit Gatewayアタッチメントを作成」クリック後、5分程度で状態がAvailableになります。

Transit Gatewayアタッチメントが作成できたらサブネットに紐づいているVPCルートテーブルにTransit Gateway宛のルートを追加します。
画面左のメニューから「ルートテーブル」をクリックし「test-private-rtb」を選択後、「ルート」タブを開いて「ルートを編集」をクリックします。
スクリーンショット 2025-02-13 142611

設定画面に移動したら大阪リージョンのVPC CIDR(10.1.0.0/16)を送信先にしてターゲットでTransit Gatewayを選択して「変更を保存」をクリックします。
スクリーンショット 2025-02-13 143047

大阪リージョン

ここからは大阪リージョンの設定を行います。
手順は東京リージョンのものと同じなので、設定値(ルートテーブルに設定するCIDRなど)に注意しながら設定を進めます。

まずはTransit Gatewayを作成します。
マネジメントコンソールで大阪リージョンを開いたらVPCのダッシュボードに移動後、画面左のメニューから「Transit Gateway」をクリックします。
画面遷移後、「Transit Gatewayを作成」をクリックします。
スクリーンショット 2025-02-13 131929

設定画面が表示されたら「名前タグ」と「説明」にわかりやすいもの (リージョンごとに識別しやすいものを入れるとよいです) を入力して「Amazon 側の自律システム番号 (ASN)」に64513と入力します。
上記で設定した内容以外はデフォルトのまま、画面下にある「Transit Gatewayを作成」をクリックします。
スクリーンショット 2025-02-13 143846

Transit Gatewayが作成できたらTransit Gateway アタッチメントを作成します。
画面左のメニューから「Transit Gateway アタッチメント」をクリックして「Transit Gateway アタッチメントを作成」をクリックします。
スクリーンショット 2025-02-13 141338

設定画面が表示されたら「名前タグ」、「Transit Gateway ID」、「VPC ID」、「サブネット ID」を設定します。
「名前タグ」は識別しやすいものを入力してください。
「Transit Gateway ID」は上記の手順で作成したTransit Gatewayを選択してください。
「VPC ID」はCloudFormationで作成したVPCを選択してください。
「サブネット ID」は「test-private-01」を選択してください。
設定をしたら画面下の「Transit Gatewayアタッチメントを作成」をクリックします。
スクリーンショット 2025-02-13 144305

Transit Gatewayアタッチメントが作成できたらサブネットに紐づいているVPCルートテーブルにTransit Gateway宛のルートを追加します。
画面左のメニューから「ルートテーブル」をクリックし「test-private-rtb」を選択後、「ルート」タブを開いて「ルートを編集」をクリックします。
スクリーンショット 2025-02-13 144545

設定画面に移動したら東京リージョンのVPC CIDR(10.0.0.0/16)を送信先にしてターゲットでTransit Gatewayを選択して「変更を保存」をクリックします。
スクリーンショット 2025-02-13 144753

Transit Gatewayピアリングアタッチメント設定

東京リージョンのTransit Gatewayアタッチメントの画面から「Transit Gatewayアタッチメントを作成」をクリックします。
設定画面が開いたら「名前タグ」、「Transit Gateway ID」、「アタッチメントタイプ」、「リージョン」、「Transit Gateway (アクセプタ)」を設定します。
「名前タグ」は識別しやすいものを入力すれば問題ありません。
「Transit Gateway ID」は東京リージョンのTransit Gateway IDを選択してください。
「アタッチメントタイプ」はPeering Connectionを選択してください。
「リージョン」は大阪リージョンを選択してください。
「Transit Gateway (アクセプタ)」は大阪リージョンで作成したTransit Gateway IDを入力してください。
設定をしたら画面下の「Transit Gatewayアタッチメントを作成」をクリックします。
スクリーンショット 2025-02-13 145248

「Transit Gatewayアタッチメントを作成」をクリックしたら大阪リージョンのTransit Gatewayアタッチメントの画面を開きます。
画面を開くと東京リージョンからのピアリングアタッチメントが表示されるので、「アクション」から「Transit Gatewayアタッチメントを承諾」をクリックします。
スクリーンショット 2025-02-13 145819

承諾が完了したらTransit Gatewayルートテーブルに対向VPC宛のルートを追加します。
東京リージョン、大阪リージョン両方で作業を行います。
Transit Gatewayルートテーブルの画面を開いたら「ルート」タブを開いて「静的ルートを作成」をクリックします。
スクリーンショット 2025-02-13 150934

設定画面が開いたら「CIDR」に対向VPCのCIDRを入力して「アタッチメントを選択」でピアリングアタッチメントを選択してください。
設定を行ったら「静的ルートを作成」をクリックします。

東京リージョンでの設定画面

スクリーンショット 2025-02-13 151631

大阪リージョンでの設定画面

スクリーンショット 2025-02-13 151842

疎通確認

設定が完了したら疎通確認用EC2にSystems Manager Session Managerで接続します。
マネジメントコンソールでEC2インスタンスの画面を開き(東京リージョン、大阪リージョンどちらでも構いません)「接続」をクリックします。
スクリーンショット 2025-02-13 152414

「セッションマネージャー」タブから「接続」をクリックします。
スクリーンショット 2025-02-13 152608

接続ができたらpingコマンドを対向VPCのEC2宛に実行して疎通できていることが確認できれば設定は完了です。(EC2のプライベートIPアドレスはマネジメントコンソールから確認してください)
スクリーンショット 2025-02-13 152858

さいごに

両方のリージョンでのルーティング設定が必要なので、もし疎通に失敗した際はまずTransit Gatewayのルートテーブルの確認から行うとよさそうです。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.