Transit GatewayをCloudFormationで構築してみた

2020.10.31

徐々にCloudFormationと友達になれてきたオンジーです!

Transit GatewayをCloudFormationで構築してVPC間で通信できるかやってみました。

シンプルに試してみたかったので同一アカウント内、単一AZです。

前準備でVPC,サブネット,ルートテーブル,EC2(疎通確認用)を作成します。手順は割愛します。

下記のテンプレートで簡単に作れますのでよろしければ使ってください!

またTransit Gatewayをアタッチメントする専用のサブネット(/28あれば十分)を用意しています。

テンプレートは次の通りです。

AWSTemplateFormatVersion: "2010-09-09"

Parameters:
  EnvironmentName:
    Type: String
    Default: XXXXXXXX-env

  VPCA:
    Description: "VPC ID : vpc-XXXXXXXX"
    Type: String
    Default: vpc-XXXXXXXX

  # TGWをアタッチメントする方のSubnet
  SubnetA:
    Description: "transitgateway attachment VPCA : subnet-XXXXXXXX"
    Type: String
    Default: subnet-XXXXXXXX

  # EC2がある方のSubnetのRouteTable
  RouteTableA:
    Description: "VPCA Subnet RouteTable : rtb-xxxxxxxxxxxxxxx"
    Type: String
    Default: rtb-xxxxxxxxxxxxxxx

  VPCB:
    Description: "VPC ID : vpc-XXXXXXXX"
    Type: String
    Default: vpc-XXXXXXXX

  # TGWをアタッチメントする方のSubnet
  SubnetB:
    Description: "transitgateway attachment VPCB : subnet-XXXXXXXX"
    Type: String
    Default: subnet-XXXXXXXX

  # EC2がある方のSubnetのRouteTable
  RouteTableB:
    Description: "VPCB Subnet RouteTable : rtb-xxxxxxxxxxxxxxx"
    Type: String
    Default: rtb-xxxxxxxxxxxxxxx

Resources:
  TGW:
    Type: AWS::EC2::TransitGateway
    Properties:
      AutoAcceptSharedAttachments: enable
      DefaultRouteTableAssociation: enable
      DefaultRouteTablePropagation: enable
      VpnEcmpSupport: enable
      DnsSupport: enable
      Tags:
        - Key: Name
          Value: !Sub ${EnvironmentName}-TGW

  VPCAattachment:
    Type: AWS::EC2::TransitGatewayAttachment
    Properties:
      SubnetIds:
        - !Ref SubnetA
      TransitGatewayId: !Ref TGW
      VpcId: !Ref VPCA
      Tags:
        - Key: Name
          Value: !Sub ${EnvironmentName}-A-attachment

  VPCBattachment:
    Type: AWS::EC2::TransitGatewayAttachment
    Properties:
      SubnetIds:
        - !Ref SubnetB
      TransitGatewayId: !Ref TGW
      VpcId: !Ref VPCB
      Tags:
        - Key: Name
          Value: !Sub ${EnvironmentName}-B-attachment

  VPCATGWRoute:
    Type: "AWS::EC2::Route"
    Properties:
      RouteTableId: !Ref RouteTableA
      DestinationCidrBlock: 10.204.0.0/16
      TransitGatewayId: !Ref TGW
    DependsOn: VPCAattachment

  VPCBTGWRoute:
    Type: "AWS::EC2::Route"
    Properties:
      RouteTableId: !Ref RouteTableB
      DestinationCidrBlock: 10.192.0.0/16
      TransitGatewayId: !Ref TGW
    DependsOn: VPCBattachment

  EC2SecurityGroupPingA:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: EC2SecurityGroupPingA
      GroupName: !Sub ${EnvironmentName}-EC2SecurityGroupPingA
      VpcId: !Ref VPCA
      Tags:
        - Key: Name
          Value: !Sub ${EnvironmentName}-EC2SecurityGroupPingA
      SecurityGroupIngress:
        - IpProtocol: icmp
          FromPort: -1
          ToPort: -1
          CidrIp: 10.204.0.0/16

  EC2SecurityGroupPingB:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: EC2SecurityGroupPingB
      GroupName: !Sub ${EnvironmentName}-EC2SecurityGroupPingB
      VpcId: !Ref VPCB
      Tags:
        - Key: Name
          Value: !Sub ${EnvironmentName}-EC2SecurityGroupPingB
      SecurityGroupIngress:
        - IpProtocol: icmp
          FromPort: -1
          ToPort: -1
          CidrIp: 10.192.0.0/24

Outputs:
  TGW:
    Value: !Ref TGW
    Export:
      Name: !Sub ${EnvironmentName}-TGW

  VPCAattachment:
    Value: !Ref VPCAattachment
    Export:
      Name: !Sub ${EnvironmentName}-A-attachment

  VPCBattachment:
    Value: !Ref VPCBattachment
    Export:
      Name: !Sub ${EnvironmentName}-B-attachment

  EC2SecurityGroupPingA:
    Value: !Ref EC2SecurityGroupPingA
    Export:
      Name: !Sub ${EnvironmentName}-EC2SecurityGroupPingA

  EC2SecurityGroupPingB:
    Value: !Ref EC2SecurityGroupPingB
    Export:
      Name: !Sub ${EnvironmentName}-EC2SecurityGroupPingB

以上が全文です。ポイントごとにコメントしていきます。

  TGW:
    Type: AWS::EC2::TransitGateway
    Properties:
      AutoAcceptSharedAttachments: enable
      DefaultRouteTableAssociation: enable
      DefaultRouteTablePropagation: enable
      VpnEcmpSupport: enable
      DnsSupport: enable
      Tags:
        - Key: Name
          Value: !Sub ${EnvironmentName}-TGW

Transit Gatewayの本体をここで作成しており、大事な設定がいくつかあります。

  • AutoAcceptSharedAttachments
    • アタッチメントリクエストを自動承諾するかどうかの設定です。
    • 本番運用でTransit Gatewayをクロスアカウントで共有するときなど承認のステップを挟みたい場合はdisable(デフォルト)にしておきます。
  • DefaultRouteTableAssociation
    • 有効にしているとアタッチメントが作成されたタイミングでアソシエーションされます。
    • アソシエーションはTransit Gatewayルートテーブルにアタッチメントを関連づけることです。
  • DefaultRouteTablePropagation
    • 有効にしているとアタッチメントが作成されアソシエーションされたタイミングでプロパゲーションされます。
    • プロパゲーションはTransit Gatewayルートテーブルにアタッチメント先のVPCへの経路を追加することです。

これらのTransit Gateway用語は次の記事がとても参考になります。

上記の設定を有効にしているためアタッチメントが作成された時点で2つのVPCが相互で通信できるようにルートテーブルにレコードが登録された状態になります。

 

  VPCATGWRoute:
    Type: "AWS::EC2::Route"
    Properties:
      RouteTableId: !Ref RouteTableA
      DestinationCidrBlock: 10.204.0.0/16
      TransitGatewayId: !Ref TGW
    DependsOn: VPCAattachment

  VPCBTGWRoute:
    Type: "AWS::EC2::Route"
    Properties:
      RouteTableId: !Ref RouteTableB
      DestinationCidrBlock: 10.192.0.0/16
      TransitGatewayId: !Ref TGW
    DependsOn: VPCBattachment

EC2がある方のサブネットのルートテーブルに対向のVPCへの通信がTransit Gatewayにいくよう経路を追加します。

ここでDependsOnを入れていないとTransit Gateway及びTransit Gatewayアタッチメントが作成される前にルートを追加しようとしてエラーになります。

僕も思いっきり引っかかって次の記事にたどり着きました。

さてスタックが完了したら上記のテンプレートで作成したping用のセキュリティグループをEC2に設定して疎通確認を実施してみます。

VPC-AのEC2よりVPC-BのEC2にpingするとちゃんと到達しました!

クロスアカウントでのTransit Gatewayを構築する際はAWS::RAM::ResourceShareを追記すればできそうです。次のステップで試してみようと思います!