【CloudFormation】Multi-AZのネットワークを作ってみる

今回はプライベートサブネットとパブリックサブネットを複数のAZに配置する、よくある構成のネットワークをCloudFormationで作成していきます。

![スクリーンショット 2021-09-17 001645.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92383/79500745-c28f-0da1-f3b1-318189f10303.png)

# ■ テンプレート

```sample-network-multi-az.yml
AWSTemplateFormatVersion: '2010-09-09'

##
# パラメータ定義: https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html
##
Parameters:
  CidrPrefix:
    Type: String

Outputs:
  VPCId:
    Value: !Ref VPC
  PublicSubnet01Id:
    Value: !Ref PublicSubnet01
  PublicSubnet02Id:
    Value: !Ref PublicSubnet02
  PrivateSubnet01Id:
    Value: !Ref PrivateSubnet01
  PrivateSubnet02Id:
    Value: !Ref PrivateSubnet02
  VPC:
    Value: !GetAtt VPC.CidrBlock

Resources:
  ##
  # vpc: https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpc.html
  ##
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Sub ${CidrPrefix}.0.0/16
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-vpc

  ##
  # サブネット: https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-subnet.html
  ##
  PublicSubnet01:
    Type: AWS::EC2::Subnet
    Properties:
      CidrBlock: !Sub ${CidrPrefix}.10.0/24
      AvailabilityZone: ap-northeast-1a
      MapPublicIpOnLaunch: false # このサブネットで起動されたインスタンスが起動時にパブリックIPを設定するか(default = false)
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-public-subnet-01
  PublicSubnet02:
    Type: AWS::EC2::Subnet
    Properties:
      CidrBlock: !Sub ${CidrPrefix}.20.0/24
      AvailabilityZone: ap-northeast-1c
      MapPublicIpOnLaunch: false
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-public-subnet-02
  PrivateSubnet01:
    Type: AWS::EC2::Subnet
    Properties:
      CidrBlock: !Sub ${CidrPrefix}.11.0/24
      AvailabilityZone: ap-northeast-1a
      MapPublicIpOnLaunch: false
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-private-subnet-01
  PrivateSubnet02:
    Type: AWS::EC2::Subnet
    Properties:
      CidrBlock: !Sub ${CidrPrefix}.21.0/24
      AvailabilityZone: ap-northeast-1c
      MapPublicIpOnLaunch: false
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-private-subnet-02

  ##
  # インターネットゲートウェイ: https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-internetgateway.html
  ##
  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-igw

  # VPCにインターネットゲートウェイをアタッチ: https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpc-gateway-attachment.html
  AttachInternetGateway:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref VPC
      InternetGatewayId: !Ref InternetGateway

  ##
  # ElasticIp: https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-eip.html
  ##
  EipNgw01:  # NatGateway01用のグローバルIP
    Type: AWS::EC2::EIP
    Properties:
      Domain: vpc
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-eip-ngw01
  EipNgw02:  # NatGateway02用のグローバルIP
    Type: AWS::EC2::EIP
    Properties:
      Domain: vpc
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-eip-ngw02

  ##
  # NATゲートウェイ: https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-natgateway.html
  ##
  NatGateway01:
    Type: AWS::EC2::NatGateway
    Properties:
      AllocationId: !GetAtt EipNgw01.AllocationId
      SubnetId: !Ref PublicSubnet01
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-ngw-01
  NatGateway02:
    Type: AWS::EC2::NatGateway
    Properties:
      AllocationId: !GetAtt EipNgw02.AllocationId
      SubnetId: !Ref PublicSubnet02
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-ngw-02

  ##
  # ルートテーブル: https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-route-table.html
  ##
  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    DependsOn: AttachInternetGateway
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-public-rt-01
  PrivateRouteTable01:
    Type: AWS::EC2::RouteTable
    DependsOn: AttachInternetGateway
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-private-rt-01
  PrivateRouteTable02:
    Type: AWS::EC2::RouteTable
    DependsOn: AttachInternetGateway
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-private-rt-02

  # サブネットとルートテーブルの紐づけ: https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-subnet-route-table-assoc.html
  PublicRouteAssoc01:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PublicRouteTable
      SubnetId: !Ref PublicSubnet01
  PublicRouteAssoc02:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PublicRouteTable
      SubnetId: !Ref PublicSubnet02
  PrivateRouteAssoc01:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PrivateRouteTable01
      SubnetId: !Ref PrivateSubnet01
  PrivateRouteAssoc02:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PrivateRouteTable02
      SubnetId: !Ref PrivateSubnet02

  # ルート定義: https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-route.html
  PublicRoute:  # パブリックサブネット用のルート定義 (パブリックサブネット->インターネットの通信は直接InternetGatewayをゲートウェイにします)
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway
  PrivateRoute01:  # PrivateSubnet01用のルート定義 (プライベートサブネット->インターネットの通信はNATGatewayを経由させます)
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref PrivateRouteTable01
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId: !Ref NatGateway01
  PrivateRoute02:  # PrivateSubnet02用のルート定義 (プライベートサブネット->インターネットの通信はNATGatewayを経由させます)
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref PrivateRouteTable02
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId: !Ref NatGateway02
```


# ■ スタック作成・削除

```bash
# スタックの作成
aws cloudformation create-stack \
--stack-name sample-network \
--template-body file://./sample-network-multi-az.yml \
--parameters "ParameterKey=CidrPrefix,ParameterValue=10.109"

# スタックの情報を表示
aws cloudformation describe-stacks --stack-name sample-network

# スタックの削除
aws cloudformation delete-stack --stack-name sample-network
```