AWS CloudFormation テンプレートファイルの初心者向け解説

AWS CloudFormation テンプレートファイルの解説(初心者向け YAML形式)

業務で AWS CloudFormation テンプレートを触れることがあり、学習のため技術情報を調べてみると様々な解説が確認できます。 ですが検索して出てくる情報は、知識が乏しい初心者から見るとどうも取っ付き辛い、、、
(複雑な環境を構築するテンプレートだったり、大規模な環境を構築するテンプレートであったり)

なので、ここでは余分な情報を省き AWS CloudFormation とは、テンプレートの書き方の基本、最初の導入を解説したいと思います。

AWS CloudFormation とは?

一言でいうと、
『コードの通りにAWS環境を構築するサービス』
になります。

AWS環境の構築はマネージドコンソール上の操作で簡単に構築できます。
ですが、複雑な環境、大規模な環境等は操作が煩雑となり、手動での登録は設定値の登録誤りや誤操作の原因になります。

そこで、便利なのが AWS CloudFormation です。
環境の設定値を記載したファイル(テンプレートファイル)を読み込ませるだけで、あとは自動で環境を構築するAWSの機能になります。

テンプレートファイルとは?

AWSの環境(VPC、EC2等)の情報を記述したテキストファイル。
記述形式はJSON形式、YAML形式があります。(今回はYAML形式を解説します。)

AWS CloudFormation の使い方

ここで一旦整理したいと思います。
テンプレートファイルを使い、CloudFormation がどのように環境を構築するのか流れを解説します。

  1. テンプレートファイルをテキストで作成(拡張子は .yaml
  2. AWS の CloudFormation からテンプレートファイルを読み込み、スタックを作成
  3. スタック作成と同時にテンプレートファイルで指定した環境が構築される
    (環境の規模によって時間が掛かる)
  4. 環境構築完成
  5. スタックを削除すると、作成された環境が削除される
     *CloudFormationで作成した環境はスタックと紐づいているため、
      スタックの削除を行うと環境も一括削除される

テンプレートファイルの基本的な文法

様々な解説があり、またそれぞれ独自の記述方法がありますが、今回は実践を交え基本的で最低限の構文を使い解説をします。

まずは実際に環境が作れるテンプレートファイルを作成してみましょう。

例えば、VPCを作る場合のYAMLは、、

AWSTemplateFormatVersion: "2010-09-09"        ......①

Description:        ......②
  test-blog

Resources:        ......③
  TestVPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: ***.***.***.***/**
      Tags:
        - Key: Name
          Value: TEST-VPC

これで、VPC【TEST-VPC】が作成できます。

文法は①~③の要素から成ります。
一つ一つ解説していきます。

  • ①テンプレートファイルのバージョン指定 (任意)
AWSTemplateFormatVersion: "2010-09-09"

 ※現在は "2010-09-09" のみサポート

  • ②スタックの説明 (任意)
Description:
  test-blog

 ※スタックの【説明】欄に入る文言を記載
  上記の記載では、作成後のスタックの説明欄に【test-blog】と記載される

  • ③リソースの定義 (必須)
Resources:

  TestVPC:              (A)
    Type: AWS::EC2::VPC         (B)
    Properties:             (C)
      CidrBlock: ***.***.***.***/**
      Tags:
        - Key: Name
          Value: TEST-VPC

ここでは VPC を構築する内容になります
 (A).リソースの名前
  →『ここでは○○という名前で設定します』という宣言です。
   テンプレートファイル内での任意の名称を付ける事が出来ます。
   (名称は英数字のみ可能)
 (B).リソースのタイプ
  →設定する環境をここで指定します。
   今回はVPCを設定するタイプになります。
 (C).リソースの設定値
  →タイプで指定した設定値をここに記述します。
   タイプが異なると、設定値の記述方法が異なります。
    ※リソースの設定値は"必須項目"が記載されていればスタックの作成は可能です。
     記載の無い項目はデフォルト値が入ります。

テンプレートファイルで記述するタイプについては、下記公式ドキュメントをご参照ください。

docs.aws.amazon.com

実際に環境を構築してみる

それでは、AWSマネージドコンソールから CloudFormation テンプレートファイルを使用して上記の VPC を作成してみます。
※掲載しているマネージドコンソールの画面は 2021/12 のものになります。

1. CloudFormationサービス

まずはAWSマネージドコンソールのサービスから【CloudFormation】を選択する。

f:id:swx-yuya-suzuki:20211204122952p:plain

2. スタック

左ペインの一覧から【スタック】を選択する。

f:id:swx-yuya-suzuki:20211204124029p:plain

3. スタックの作成

画面右の【スタックの作成】を選択する。

f:id:swx-yuya-suzuki:20211204124720p:plain

4. テンプレートファイルの指定

下記の通り選択する。

  • テンプレート準備:【テンプレートの準備完了】
  • テンプレートの指定:【テンプレートファイルのアップロード】
    ※作成したVPC構築テンプレートファイルを指定する。
    設定後、【次へ】を選択する。

f:id:swx-yuya-suzuki:20211204125927p:plain

5. スタックの名前

スタックの名前を入力する。
入力後、【次へ】を選択する。 f:id:swx-yuya-suzuki:20211204130442p:plain

6. スタックオプションの設定

全てそのままで【次へ】を選択する。

f:id:swx-yuya-suzuki:20211204131245p:plain

7. 設定内容の確認

設定内容が表示されるので、問題が無ければ【スタックの作成】を選択する。

f:id:swx-yuya-suzuki:20211204131424p:plain

8. スタックの作成開始・完了

作成したスタックのステータスが【CREATE_COMPLETE】になることを確認する。 f:id:swx-yuya-suzuki:20211204131546p:plain   ↓
f:id:swx-yuya-suzuki:20211204131642p:plain

9.VPC作成確認

VPCを確認し、VPC【TEST-VPC】が作成されていることを確認する。 f:id:swx-yuya-suzuki:20211204131947p:plain

10.スタックの削除

スタックの一覧から、対象のスタックを選択し、【削除】を選択する。 f:id:swx-yuya-suzuki:20211205102138p:plain ポップアップの【スタックの削除】を選択する。 f:id:swx-yuya-suzuki:20211205102537p:plain

11.VPC削除確認

VPCを確認し、作成したVPC【TEST-VPC】が削除されていることを確認する。 f:id:swx-yuya-suzuki:20211205102837p:plain

簡単な環境を構築するテンプレートを作成してみる

今回は以下の構成図のような環境を構築するテンプレートを作成します。

  • 構築する構成図
    f:id:swx-yuya-suzuki:20211204104425p:plain
    構成図

構成図で示した環境を構築するテンプレートは以下の通りになります。
 (構文は最低限の設定値で記載しています)
※今回はキーペア【TEST-KEY】を事前に作成済みとなります。

  • テンプレートファイル
AWSTemplateFormatVersion: "2010-09-09"

Description:
  test-blog

Resources:
  TestVPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.124.0.0/16
      Tags:
        - Key: Name
          Value: TEST-VPC


  TestIGW:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: TEST-IGW


  AttachGateway:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref TestVPC
      InternetGatewayId: !Ref TestIGW


  TestSubNet1:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: ap-northeast-1a
      VpcId: !Ref TestVPC
      CidrBlock: 10.124.10.0/24
      Tags:
        - Key: Name
          Value: TEST-SubNet1


  TestRouteTable1:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref TestVPC
      Tags:
        - Key: Name
          Value: TEST-RouteTable1


  TestRoute1:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref TestRouteTable1
      DestinationCidrBlock: ***.***.***.***/**
      GatewayId: !Ref TestIGW


  TestSubNetRoutTablAsso:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref TestSubNet1
      RouteTableId: !Ref TestRouteTable1


  TestSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: TEST-SecurityGroup
      GroupDescription: TEST-SecurityGroup
      VpcId: !Ref TestVPC
      SecurityGroupIngress:
      - 
        IpProtocol: tcp
        CidrIp: ***.***.***.***/**
        FromPort: "22"
        ToPort: "22"


  TestEC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: ami-09ebacdc178ae23b7
      KeyName: TEST-KEY
      InstanceType: t2.micro
      InstanceInitiatedShutdownBehavior: stop
      Tenancy: default
      NetworkInterfaces:
        - AssociatePublicIpAddress: "true"
          DeviceIndex: "0"
          SubnetId: !Ref TestSubNet1
          GroupSet:
            - !Ref TestSecurityGroup
          PrivateIpAddress: 10.124.10.10

      Tags:
          - Key: Name
            Value: test_linux_instance
      
      BlockDeviceMappings:  
        - DeviceName: /dev/xvda
          Ebs:
            VolumeType: gp2
            DeleteOnTermination: true 
            VolumeSize: 10

      UserData: !Base64 |
        sudo hostnamectl set-hostname TEST-LINUX-INSTANCE


  EipTestServer:
    Type: AWS::EC2::EIP
    Properties:
      InstanceId: !Ref TestEC2Instance

それでは各リソースの記述を解説します。

  TestVPC:                   #リソースの名前【TestVPC】
    Type: AWS::EC2::VPC             #VPC作成するタイプを指定【AWS::EC2::VPC】
    Properties:
      CidrBlock: 10.124.0.0/16      #CidrBlockを指定
      Tags:             #タグの指定、Key、Valueの順に記載する
        - Key: Name
          Value: TEST-VPC
  • IGW作成
  TestIGW:               #リソースの名前【TestIGW】
    Type: AWS::EC2::InternetGateway #インターネットゲートウェイ作成するタイプを指定【AWS::EC2::InternetGateway】
    Properties:
      Tags:             #タグの指定、Key、Valueの順に記載する
        - Key: Name
          Value: TEST-IGW
  • IGWをVPCにアタッチ
  AttachGateway:             #リソースの名前【AttachGateway】
    Type: AWS::EC2::VPCGatewayAttachment    #IGWをVPCにアタッチするタイプを指定【AWS::EC2::VPCGatewayAttachment】
    Properties:
      VpcId: !Ref TestVPC           #【!Ref】は設定済みのリソースを指定できる
      InternetGatewayId: !Ref TestIGW       #今回は上で設定したVPCにIGWを適応する

 ※リソースの設定は、以下の流れで設定します。
  1.各リソースの設定
  2.設定したリソースの関係性を設定
 ※【!Ref】を使用する事で作成したリソースを指定する事が出来ます。

  • サブネット作成
  TestSubNet1:               #リソースの名前【TestSubNet1】
    Type: AWS::EC2::Subnet      #サブネットを作成するタイプを指定【AWS::EC2::Subnet】
    Properties:
      AvailabilityZone: ap-northeast-1a     #AZの指定
      VpcId: !Ref TestVPC           #【!Ref】で上で設定したVPCを指定
      CidrBlock: 10.124.10.0/24         #CidrBlockを指定
      Tags:                 #タグの指定、Key、Valueの順に記載する
        - Key: Name
          Value: TEST-SubNet1
  • ルートテーブル作成
  TestRouteTable1:           #リソースの名前【TestRouteTable1】
    Type: AWS::EC2::RouteTable      #ルートテーブルを作成するタイプを指定【AWS::EC2::RouteTable】
    Properties:
      VpcId: !Ref TestVPC       #【!Ref】で上で設定したVPCを指定
      Tags:             #タグの指定、Key、Valueの順に記載する
        - Key: Name
          Value: TEST-RouteTable1
  • ルートテーブルの内容を設定
     (サブネット-インターネット間のルーティングをルートテーブルに設定)
  TestRoute1:                    #リソースの名前【TestRoute1】
    Type: AWS::EC2::Route           #ルートテーブルに設定を登録するタイプを指定【AWS::EC2::Route】
    Properties:
      RouteTableId: !Ref TestRouteTable1        #【!Ref】で適用するルートテーブルを指定
      DestinationCidrBlock: ***.***.***.***/**      #許可するCidrBlockを指定
      GatewayId: !Ref TestIGW               #【!Ref】で適用するIGWを指定
  • ルートテーブルをサブネットに関連付け
  TestSubNetRoutTablAsso:                #リソースの名前【TestSubNetRoutTablAsso】
    Type: AWS::EC2::SubnetRouteTableAssociation     #ルートテーブルをサブネットに関連付けするタイプを指定【AWS::EC2::SubnetRouteTableAssociation】
    Properties:
      SubnetId: !Ref TestSubNet1            #【!Ref】で適用するサブネットを指定
      RouteTableId: !Ref TestRouteTable1        #【!Ref】で適用するルートテーブルを指定
  • セキュリティグループ作成
  TestSecurityGroup:             #リソースの名前【TestSecurityGroup】
    Type: AWS::EC2::SecurityGroup       #セキュリティグループを作成するタイプを指定【AWS::EC2::SecurityGroup】
    Properties:
      GroupName: TEST-SecurityGroup     #ルールのName
      GroupDescription: TEST-SecurityGroup  #ルールの説明
      VpcId:  !Ref TestVPC          #【!Ref】で上で設定したVPCを指定
      SecurityGroupIngress:         #接続許可(複数設定の場合は"-"で区切って連続して書く)
      - 
        IpProtocol: tcp             #プロトコル指定
        CidrIp: ***.***.***.***/**      #送信元IPアドレス
        FromPort: "22"              #送信元ポート
        ToPort: "22"                #送信先ポート
  TestEC2Instance:               #リソースの名前【TestEC2Instance】
    Type: AWS::EC2::Instance            #インスタンスを作成するタイプを指定【AWS::EC2::Instance】
    Properties:
      ImageId: ami-09ebacdc178ae23b7        #AMIのID
      KeyName: TEST-KEY         #キーペア(作成済みのキーペアを指定)
      InstanceType: t2.micro            #インスタンスタイプ
      InstanceInitiatedShutdownBehavior: stop   #シャットダウン動作
      Tenancy: default              #テナンシー
      NetworkInterfaces:            #インターフェースの設定
        - AssociatePublicIpAddress: "true"
          DeviceIndex: "0"          # パブリックIPを自動で割り振り
          SubnetId: !Ref TestSubNet1        #【!Ref】で上で設定したサブネット指定
          GroupSet:
            - !Ref SecGrp           # 上のセキュリティグループを指定
          PrivateIpAddress: 10.124.10.10    # プライベートIPアドレス指定

      Tags:                 #タグの指定、Key、Valueの順に記載する
          - Key: Name
            Value: test_linux_instance
      
      BlockDeviceMappings:          #ストレージの設定
        - DeviceName: /dev/xvda         #デバイス名
          Ebs:
            VolumeType: gp2         #ボリュームタイプ
            DeleteOnTermination: true       #インスタンス終了時に削除するのか
            VolumeSize: 10          #ディスクサイズ(GiB)

      UserData: !Base64 |           #構築後に実行するコマンド
        #!/bin/bash
        sudo hostnamectl set-hostname TEST-LINUX-INSTANCE   #hostname 変更コマンド

※【UserData: !Base64】構文を使用する事で、インスタンス構築後に指定したコマンドを実行する事が出来ます。
 今回はホストネームの変更を実施しています。

  • Elastic IP アドレス作成
  EipTestServer:         #リソースの名前【EipFileServer】
    Type: AWS::EC2::EIP         #Elastic IP アドレスを作成するタイプを指定【AWS::EC2::EIP】
    Properties:
      InstanceId: !Ref TestEC2Instance  #【!Ref】で割り当てるインスタンス指定

最後に

AWS CloudFormation テンプレートファイルを理解するには、最初から大規模な構成を作成しようとせずに、小さい単位で構築を進め理解を深める事が習得への近道になると思います。