AWS-CloudFormation

再利用できるCloudFormationを作ろう~VPC編~

はじめに

こんにちは新入社員のタナミです。

VPCの構築ではCIDRの設定やルートテーブルのアタッチなど、意外と手間が多いように感じます。
そこで、今回はCloudFormationを使ってVPCを作成しようと思います。

今回作成できるもの

今回のCloudFormationでは下記のようなリソースを作成します。
また、ここには載っていませんが自身のIPを許可したセキュリティグループも同時に作成されます。

テンプレートを書こう

CloudFormationで扱うテンプレートの作成を行います。
現在CloudFormationではJSONYAMLの二つの形式に対応しているので、今回はYAMLでテンプレートを作っていきます。

vpc-automatic.yaml

AWSTemplateFormatVersion: '2010-09-09'
Description: 'Parameterized VPC and Security Groups template'

Parameters:
  # リソース名のパラメータ
  ResourceName:
    Type: String
    Description: Enter resource name
    Default: test

  # 自身のIPアドレスを入力
  MyIP:
    Type: String
    Description: Enter your IP
    Default: 0.0.0.0/0

  # VPC CIDRのパラメータ
  VpcCidr:
    Type: String
    Description: CIDR block for the VPC
    Default: 10.0.0.0/16

  # パブリックサブネットのCIDRパラメータ
  PublicSubnetPrimaryCidr:
    Type: String
    Description: CIDR block for the primary public subnet
    Default: 10.0.1.0/24

  PublicSubnetSecondaryCidr:
    Type: String
    Description: CIDR block for the secondary public subnet
    Default: 10.0.2.0/24

  PublicSubnetTertiaryCidr:
    Type: String
    Description: CIDR block for the tertiary public subnet
    Default: 10.0.3.0/24

  # プライベートサブネットのCIDRパラメータ
  PrivateSubnetPrimaryCidr:
    Type: String
    Description: CIDR block for the primary private subnet
    Default: 10.0.101.0/24

  PrivateSubnetSecondaryCidr:
    Type: String
    Description: CIDR block for the secondary private subnet
    Default: 10.0.102.0/24

  PrivateSubnetTertiaryCidr:
    Type: String
    Description: CIDR block for the tertiary private subnet
    Default: 10.0.103.0/24

Resources:
  # VPCを作成
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref VpcCidr
      EnableDnsHostnames: true
      EnableDnsSupport: true
      Tags:
        - Key: Name
          Value: !Sub '${ResourceName}-vpc'

  # インターネットゲートウェイを作成
  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: !Sub '${ResourceName}-igw'

  # VPCをインターネットゲートウェイにアタッチ
  AttachGateway:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref VPC
      InternetGatewayId: !Ref InternetGateway

  # パブリックルートテーブルを作成
  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub '${ResourceName}-public-route-table'

  # プライベートルートテーブルを作成
  PrivateRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub '${ResourceName}-private-route-table'

  # パブリックルートテーブルをインターネットゲートウェイにアタッチ
  PublicRoute:
    Type: AWS::EC2::Route
    DependsOn: AttachGateway
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway

  # パブリックサブネットを作成
  PublicSubnetPrimary:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: !Ref PublicSubnetPrimaryCidr
      AvailabilityZone: !Select [0, !GetAZs '']
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: !Sub '${ResourceName}-public-subnet-primary'

  PublicSubnetSecondary:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: !Ref PublicSubnetSecondaryCidr
      AvailabilityZone: !Select [1, !GetAZs '']
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: !Sub '${ResourceName}-public-subnet-secondary'

  PublicSubnetTertiary:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: !Ref PublicSubnetTertiaryCidr
      AvailabilityZone: !Select [2, !GetAZs '']
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: !Sub '${ResourceName}-public-subnet-tertiary'

  # プライベートサブネットを作成
  PrivateSubnetPrimary:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: !Ref PrivateSubnetPrimaryCidr
      AvailabilityZone: !Select [0, !GetAZs '']
      Tags:
        - Key: Name
          Value: !Sub '${ResourceName}-private-subnet-primary'

  PrivateSubnetSecondary:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: !Ref PrivateSubnetSecondaryCidr
      AvailabilityZone: !Select [1, !GetAZs '']
      Tags:
        - Key: Name
          Value: !Sub '${ResourceName}-private-subnet-secondary'

  PrivateSubnetTertiary:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: !Ref PrivateSubnetTertiaryCidr
      AvailabilityZone: !Select [2, !GetAZs '']
      Tags:
        - Key: Name
          Value: !Sub '${ResourceName}-private-subnet-tertiary'

  # パブリックサブネットをルートテーブルに割り当て
  PublicSubnetPrimaryRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnetPrimary
      RouteTableId: !Ref PublicRouteTable

  PublicSubnetSecondaryRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnetSecondary
      RouteTableId: !Ref PublicRouteTable

  PublicSubnetTertiaryRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnetTertiary
      RouteTableId: !Ref PublicRouteTable

  # プライベートサブネットをルートテーブルに割り当て
  PrivateSubnetPrimaryRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnetPrimary
      RouteTableId: !Ref PrivateRouteTable

  PrivateSubnetSecondaryRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnetSecondary
      RouteTableId: !Ref PrivateRouteTable

  PrivateSubnetTertiaryRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnetTertiary
      RouteTableId: !Ref PrivateRouteTable

  # セキュリティグループを作成
  MainSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: !Sub '${ResourceName}-main-sg'
      GroupDescription: Security group for my ip
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: -1
          CidrIp: !Ref MyIP
      SecurityGroupEgress:
        - IpProtocol: -1
          CidrIp: 0.0.0.0/0
      Tags:
        - Key: Name
          Value: !Sub '${ResourceName}-main-sg'

Outputs:
  VPCId:
    Description: VPC ID
    Value: !Ref VPC
    Export:
      Name: !Sub '${ResourceName}-vpc'

  PublicSubnetPrimaryId:
    Description: Public Subnet Primary ID
    Value: !Ref PublicSubnetPrimary
    Export:
      Name: !Sub '${ResourceName}-public-subnet-primary'

  PublicSubnetSecondaryId:
    Description: Public Subnet Secondary ID
    Value: !Ref PublicSubnetSecondary
    Export:
      Name: !Sub '${ResourceName}-public-subnet-secondary'

  PublicSubnetTertiaryId:
    Description: Public Subnet Tertiary ID
    Value: !Ref PublicSubnetTertiary
    Export:
      Name: !Sub '${ResourceName}-public-subnet-tertiary'

  PrivateSubnetPrimaryId:
    Description: Private Subnet Primary ID
    Value: !Ref PrivateSubnetPrimary
    Export:
      Name: !Sub '${ResourceName}-private-subnet-primary'

  PrivateSubnetSecondaryId:
    Description: Private Subnet Secondary ID
    Value: !Ref PrivateSubnetSecondary
    Export:
      Name: !Sub '${ResourceName}-private-subnet-secondary'

  PrivateSubnetTertiaryId:
    Description: Private Subnet Tertiary ID
    Value: !Ref PrivateSubnetTertiary
    Export:
      Name: !Sub '${ResourceName}-private-subnet-tertiary'

  MainSecurityGroupId:
    Description: Main Security Group ID
    Value: !Ref MainSecurityGroup
    Export:
      Name: !Sub '${ResourceName}-main-sg'

CloudFormationを作成しよう

コードが出来たのでCloudFormationの作成に移ります。

スタックの作成から新しいリソースを使用を選択し
下記のようにテンプレートファイルを追加します。

また今回のCloudFormationでは、リソース名とCIDRを自由に設定できるようにしたので設定をしていきます。
さらに、MyIPのパラメーターでセキュリティグループに割り当てる自身のIPを指定します。

これによりスタックが作成され、スタックのステータスがCREATE_COMPLETEとなればリソースの作成完了です。

削除時の注意点

今回作成したスタックの削除を行う時にVPC上にデプロイされたリソースがある場合、削除が実行されません。
特にテンプレート以外から作成したセキュリティグループなどもスタックの削除が実行されない原因になるのでご注意ください。

まとめ

いかがでしたでしょうか。

今回はCloudFormationを使ってVPCの作成を行いました。
このCloudFormationを使うことで次回以降、同様のリソースを作成する際の時短になるかと思いますのでぜひ活用してみて下さい。

返信を残す

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

CAPTCHA