🕌

【AWS】CloudFormationで、定番のネットワーク構成を作成してみた

2021/08/21に公開

CloudFormationとは

簡単に言うと、AWSインフラをコードで実装できる仕組みのことです。
AWSマネジメントコンソールを使ってポチポチやっている操作を、コード化できるものです。
コードと聞くと尻込みしてしまいますが、慣れてくるとこっちのほうがAWSインフラを早く作成できるようになると思います(まだそこまで使いこなせていませんが、多分..)。

今回作成する範囲

以下の構成図に従って作成していきます。
構成図の作成には、VS CodeのプラグインであるDraw.io Integrationを使用しました。

よくありがちなネットワーク構成と、EC2インスタンスを1つ作るところまでを実装してみました。

雛形

VS CodeのCloudFormationプラグインを使って作成しました。

AWSTemplateFormatVersion: 2010-09-09
Resources: 

雛形としては、いろんな要素が生成されますが、
今回は、Resources:セクションの配下に記載していきます。
他の要素は削除しておきます。
今回はYAML形式で記述しており、インデントを付けています。

まずはVPCの作成から

testVPCという名前で、10.0.0.0/16の大きいネットワークを作成します。

  testVPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      EnableDnsSupport: true
      Tags:
        - Key: Name
          Value: testVPC

サブネットの作成

次に、4つのサブネットをType: AWS::EC2::Subnetで作成します。
内訳は、2つのパブリックサブネットと2つのプライベートサブネットです。
パブリックサブネット:10.0.0.0/2410.0.2.0/24
プライベートサブネット:10.0.0.0/2410.0.2.0/24
それぞれのサブネットは、先ほど作成したtestVPCに所属させたいので、VpcId:で参照させます。参照には!Refという文字列を指定します。

  publicsubnet01:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: ap-northeast-1a
      VpcId: !Ref testVPC
      CidrBlock: 10.0.0.0/24
      Tags:
        - Key: Name
          Value: publicsubnet01

  publicsubnet02:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: ap-northeast-1c
      VpcId: !Ref testVPC
      CidrBlock: 10.0.2.0/24
      Tags:
        - Key: Name
          Value: publicsubnet02

  privatesubnet01:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: ap-northeast-1a
      VpcId: !Ref testVPC
      CidrBlock: 10.0.1.0/24
      Tags:
        - Key: Name
          Value: privatesubnet01

  privatesubnet02:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: ap-northeast-1c
      VpcId: !Ref testVPC
      CidrBlock: 10.0.3.0/24
      Tags:
        - Key: Name
          Value: privatesubnet02

インターネットゲートウェイの作成

インターネットゲートウェイを作成するには、Type: AWS::EC2::InternetGatewayを指定します。

  igwCF:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: CFigw

インターネットゲートウェイをVPCへアタッチ

インターネットゲートウェイはVPCにアタッチ(関連付け)しないと使えませんので、Type: AWS::EC2::VPCGatewayAttachmentでアタッチします。

  AttachGateway:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref testVPC
      InternetGatewayId: !Ref igwCF

ルートテーブルの作成

パブリックサブネット用のルートテーブルをType: AWS::EC2::RouteTableで作成します。

routepublicsubnet:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref testVPC
      Tags:
        - Key: Name
          Value: rt-publicsubnet

インターネットへ抜けられるようにするためのルートをType: AWS::EC2::Routeで作成します。ルートテーブルへのアタッチはRouteTableId:で指定します。

  routePublic:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref routepublicsubnet
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref igwCF

ルートテーブルへサブネットを関連付ける

Type: AWS::EC2::SubnetRouteTableAssociationで、インターネットへ抜けられるサブネットを指定します。
今回は、2つのパブリックサブネットのみインターネットへ抜けられるようにしたいので、サブネットをSubnetId:で、ルートテーブルをRouteTableId:で指定します。

  routeTableAssocPublic01:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref publicsubnet01
      RouteTableId: !Ref routepublicsubnet

  routeTableAssocPublic02:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref publicsubnet02
      RouteTableId: !Ref routepublicsubnet

EC2用セキュリティグループの作成

ここまでで、ネットワークがひととおり作成できました。
次は、そのうちの1つのパブリックサブネットにEC2インスタンスを作成します。
まず、EC2用のセキュリティグループを作成します。セキュリティグループとはEC2インスタンス用のファイアウォールのようなものです。
セキュリティグループは、AWS::EC2::SecurityGroupで作成します。
Webサーバを想定して、httpと管理用のSSHのみを許可するセキュリティグループを作成しまう。

  SecGroupPublic:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: GroupName-SG
      GroupDescription: SecGroupPublic
      VpcId: !Ref testVPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: 0.0.0.0/0
      Tags:
        - Key: Name
          Value: SecGroupPublic

EC2の作成

最後にEC2インスタンスの作成です。
インスタンスタイプはInstanceType:でt3.micro、イメージはImageId:でAmazon Linuxを指定しました。

  publicEC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      KeyName: KeyPair-210816
      DisableApiTermination: false
      ImageId: ami-09ebacdc178ae23b7
      InstanceType: t3.micro
      Monitoring: false
      NetworkInterfaces:
        - AssociatePublicIpAddress: "true"
          DeviceIndex: "0"
          SubnetId: !Ref publicsubnet01
          GroupSet:
          - !Ref SecGroupPublic
      Tags:
        - Key: Name
          Value: publicEC2Instance

ここで悩んだのが、パブリックIPアドレスの割り当て方法でした。
公式ドキュメントを見ましたが、どうも分かりにくい..結局ググりまくって、以下の部分を発見しました。

NetworkInterfaces:
  - AssociatePublicIpAddress: "true"
    DeviceIndex: "0"

動作確認

最終的に出来上がったCloudFormationテンプレートです。

AWSTemplateFormatVersion: 2010-09-09
Resources: 
  testVPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      EnableDnsSupport: true
      Tags:
        - Key: Name
          Value: testVPC

  publicsubnet01:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: ap-northeast-1a
      VpcId: !Ref testVPC
      CidrBlock: 10.0.0.0/24
      Tags:
        - Key: Name
          Value: publicsubnet01

  publicsubnet02:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: ap-northeast-1c
      VpcId: !Ref testVPC
      CidrBlock: 10.0.2.0/24
      Tags:
        - Key: Name
          Value: publicsubnet02

  privatesubnet01:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: ap-northeast-1a
      VpcId: !Ref testVPC
      CidrBlock: 10.0.1.0/24
      Tags:
        - Key: Name
          Value: privatesubnet01

  privatesubnet02:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: ap-northeast-1c
      VpcId: !Ref testVPC
      CidrBlock: 10.0.3.0/24
      Tags:
        - Key: Name
          Value: privatesubnet02

  igwCF:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: CFigw

  AttachGateway:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref testVPC
      InternetGatewayId: !Ref igwCF

  routepublicsubnet:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref testVPC
      Tags:
        - Key: Name
          Value: rt-publicsubnet

  routePublic:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref routepublicsubnet
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref igwCF

  routeTableAssocPublic01:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref publicsubnet01
      RouteTableId: !Ref routepublicsubnet

  routeTableAssocPublic02:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref publicsubnet02
      RouteTableId: !Ref routepublicsubnet

  SecGroupPublic:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: GroupName-SG
      GroupDescription: SecGroupPublic
      VpcId: !Ref testVPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: 0.0.0.0/0
	  
  #EC2
  publicEC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      KeyName: KeyPair-210816
      DisableApiTermination: false
      ImageId: ami-09ebacdc178ae23b7
      InstanceType: t3.micro
      Monitoring: false
      NetworkInterfaces:
        - AssociatePublicIpAddress: "true"
          DeviceIndex: "0"
          SubnetId: !Ref publicsubnet01
          GroupSet:
          - !Ref SecGroupPublic
      Tags:
        - Key: Name
          Value: publicEC2Instance

これをAWSマネジメントコンソールのCloudFormationから以下の手順で読み込ませて、動作確認します。

  1. AWSマネジメントコンソールからCloudFormationの画面を開く。
  2. スタックの作成ボタンをクリック
  3. テンプレートの準備は、テンプレートの準備完了を選択
  4. テンプレートの指定は、テンプレートファイルのアップロードを選択
  5. ファイルを選択から先ほど作成したYAMLファイルを指定
  6. 次へを選択
  7. スタックの名前を入力し、次へ
  8. スタックオプションの設定と詳細オプションはデフォルトのままで次へ
  9. スタックの作成をクリック
  10. イベントタブで、作成したスタックのステータスがCREATE_COMPLETEになったことを確認する。
  11. AWSマネジメントコンソールでVPCの画面に移動して、VPC、サブネット、インターネットゲートウェイ、ルートテーブルが作成されていることを確認する。
  12. AWSマネジメントコンソールでEC2の画面に移動して、EC2インスタンスが作成されていることを確認する。
  13. 最後に、Tera Termで、作成したEC2インスタンスにSSHでログインできることを確認する。

確認が終わったら、課金を防ぐためAWSマネジメントコンソールのCloudFormation画面から、先ほど作成したスタックを削除しておきます。
AWSマネジメントコンソールで作成すると、それぞれの画面でリソースを削除する必要があります(しかも消す順番にも決まりあり)が、CloudFormationだとスタックを削除すれば、順番も考慮して全てやってくれるので楽ですね!

次はEC2のAuto Scalingを試してみようと思います。

以上

Discussion