Ubuntu Server 16.04 LTS(HVM) 起動のCloudFormationテンプレート

EC2起動の時に選択肢に表示されるUbuntu起動のテンプレートです.
CloudFormationのメタデータ取得や変更検知、状態通知などを行うヘルパースクリプトのインストールに手間取ったのであげておきます.
pipでインストールしてるので長くなっちゃってますが、wgetでファイル取って来る方法も取れそうです.

参考:

AWSTemplateFormatVersion: '2010-09-09'
Description: CFn template for ubuntu
Parameters:
  InstanceType:
    Description: EC2 instance type
    Type: String
    Default: t2.nano
    AllowedValues:
      - t2.nano 
    ConstraintDescription: must be a valid EC2 instance type.
  KeyName: 
    Description: Name of an existing Amazon EC2 key pair for SSH access
    Type: AWS::EC2::KeyPair::KeyName
  SSHLocation:
    Description: The IP address range that can be used to SSH to the EC2 instances
    Type: String
    MinLength: 9
    MaxLength: 18
    AllowedPattern: (\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/(\d{1,2})
    ConstraintDescription: must be a valid IP CIDR range of the form x.x.x.x/x.  
Mappings:
  AWSRegion2AMI:
    ap-northeast-1: 
      ubuntu: ami-ea4eae8c
Resources:
  ServerInstance:
    Type: AWS::EC2::Instance
    Metadata:
      Comment: Simple example for cfn-init
      AWS::CloudFormation::Init:
        config:
          packages:
            apt:
              httpd: [] 
          files:
            /etc/cfn/cfn-hup.conf:  # CFn側の変更検知のための設定
              content: !Sub |
                [main]
                stack=${AWS::StackId}
                region=${AWS::Region}
              mode: '000400'
              owner: root
              group: root
            /etc/cfn/hooks.d/cfn-auto-reloader.conf:  # 自動で更新を実行するための設定
              content: !Sub |
                [cfn-auto-reloader-hook]
                triggers=post.update
                path=Resources.DeepLeargingServerInstance.Metadata.AWS::CloudFormation::Init
                action=/usr/local/bin/cfn-init -s ${AWS::StackId} -r ServerInstance --region ${AWS::Region}
                runas=root
          services:
            sysvinit:
              cfn-hup:
                enabled: 'true'
                ensureRunning: 'true'
                files:
                  - /etc/cfn/cfn-hup.conf
                  - /etc/cfn/hooks.d/cfn-auto-reloader.conf
    Properties:
      ImageId: !FindInMap [AWSRegion2AMI, !Ref 'AWS::Region', ubuntu]      
      InstanceType: !Ref 'InstanceType'
      SecurityGroups:
        - !Ref 'ServerSecurityGroup'
      KeyName: !Ref 'KeyName'
      UserData: !Base64
        Fn::Sub: |
          #!/bin/bash -xe
          apt-get update
          # python 2.7, pipインストール
          apt-get -y install build-essential
          apt-get -y install python-dev python-pip
          # aws-cloudformation-bootstrapのインストール
          pip install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-latest.tar.gz
          # cfn-hupの設定
          cp -a /usr/local/init/ubuntu/cfn-hup /etc/init.d/cfn-hup
          chmod u+x /etc/init.d/cfn-hup
          update-rc.d cfn-hup defaults  # シンボリックリンク作成
          service cfn-hup start
          # メタデータからのファイルとパッケージのロード
          /usr/local/bin/cfn-init -v --stack ${AWS::StackName} --resource ServerInstance --region ${AWS::Region}
          # cfn-init から取得したの状態の通知
          /usr/local/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource ServerInstance --region ${AWS::Region}
    CreationPolicy:
      ResourceSignal:
        Timeout: PT10M
  ServerSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Enable HTTP access via port 22
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: '22'
          ToPort: '22'
          CidrIp: !Ref 'SSHLocation'
Outputs:
  WebsiteURL:
    Description: Application URL(Not Work, Just Sample)
    Value: !Sub 'http://${ServerInstance.PublicDnsName}'

続きを読む

CloudFormationウォークスルーにYAMLで入門してみる

AWSリソースの構築を自動化できるCloud Formationについて学んで見ます.

まずは既存のVPC内にSG切ってインスタンス立てて…ぐらいができればいいんだけど…と思っていたのですが、

ウォークスルー: スタックの更新

がある程度まとまってたので、とりあえず走らせて見て、何が起きてるかを学んでくことにしようと思います.

下準備: JSON => YAMLへの変換

このウォークスルーではスタック(CloudFormationで構築されるひとかたまり)を作成したのち、それを更新していく…というチュートリアルですが、一番上のセクション「単純なアプリケーション」に下地となるテンプレートが記載されているのでそれをコピーして進める…

前にこれをJSONからYAMLへ変換します (JSONしんどいため&コメントつけられるようにするため)

AWS CloudFormation Template FlipというツールがAWSから公開されているので、pipでインストールします.

pip install cfn-flip

次に下地となる、「単純なアプリケーション」セクションの一番下にある、長ーいJSONをwalkthrough01.jsonなど適当な名前でローカルに保存して、下記のコマンドを実行します.

cfn-flip -c walkthrough01.json walkthrough01.yaml

するとYAMLへ変換されたファイルが生成されます.

この際、通常のJSON => YAMLの変換だけでなく、組み込み関数宣言部Fn::が短縮形!に変換されます. (3文字減るだけですが…ドキュメントをでは短縮形が併記されています)
また、-c, --cleanオプションをつけると、Fn::Join からFn::Subへと書き換えてくれます. 文字列を連結する際[]で括らなくても良くなるようで、見やすかったのでこちらで進めていきます.

(最初は関数って何してんのと思ったのですが、ユーザーの入力受け取ったり文字列を結合したりできる、といった感じなのでひとまずそのまま進めれば大丈夫です. )

生成されたテンプレートはこんな感じです(長いですねー…)

walkthrough01.yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: 'AWS CloudFormation Sample Template: Sample template that can be used
  to test EC2 updates. **WARNING** This template creates an Amazon Ec2 Instance. You
  will be billed for the AWS resources used if you create a stack from this template.'
Parameters:
  InstanceType:
    Description: WebServer EC2 instance type
    Type: String
    Default: m1.small
    AllowedValues:
      - t1.micro
      - t2.micro
      - t2.small
      - t2.medium
      - m1.small
      - m1.medium
      - m1.large
      - m1.xlarge
      - m2.xlarge
      - m2.2xlarge
      - m2.4xlarge
      - m3.medium
      - m3.large
      - m3.xlarge
      - m3.2xlarge
      - c1.medium
      - c1.xlarge
      - c3.large
      - c3.xlarge
      - c3.2xlarge
      - c3.4xlarge
      - c3.8xlarge
      - g2.2xlarge
      - r3.large
      - r3.xlarge
      - r3.2xlarge
      - r3.4xlarge
      - r3.8xlarge
      - i2.xlarge
      - i2.2xlarge
      - i2.4xlarge
      - i2.8xlarge
      - hi1.4xlarge
      - hs1.8xlarge
      - cr1.8xlarge
      - cc2.8xlarge
      - cg1.4xlarge
    ConstraintDescription: must be a valid EC2 instance type.
Mappings:
  AWSInstanceType2Arch:
    t1.micro:
      Arch: PV64
    t2.micro:
      Arch: HVM64
    t2.small:
      Arch: HVM64
    t2.medium:
      Arch: HVM64
    m1.small:
      Arch: PV64
    m1.medium:
      Arch: PV64
    m1.large:
      Arch: PV64
    m1.xlarge:
      Arch: PV64
    m2.xlarge:
      Arch: PV64
    m2.2xlarge:
      Arch: PV64
    m2.4xlarge:
      Arch: PV64
    m3.medium:
      Arch: HVM64
    m3.large:
      Arch: HVM64
    m3.xlarge:
      Arch: HVM64
    m3.2xlarge:
      Arch: HVM64
    c1.medium:
      Arch: PV64
    c1.xlarge:
      Arch: PV64
    c3.large:
      Arch: HVM64
    c3.xlarge:
      Arch: HVM64
    c3.2xlarge:
      Arch: HVM64
    c3.4xlarge:
      Arch: HVM64
    c3.8xlarge:
      Arch: HVM64
    g2.2xlarge:
      Arch: HVMG2
    r3.large:
      Arch: HVM64
    r3.xlarge:
      Arch: HVM64
    r3.2xlarge:
      Arch: HVM64
    r3.4xlarge:
      Arch: HVM64
    r3.8xlarge:
      Arch: HVM64
    i2.xlarge:
      Arch: HVM64
    i2.2xlarge:
      Arch: HVM64
    i2.4xlarge:
      Arch: HVM64
    i2.8xlarge:
      Arch: HVM64
    hi1.4xlarge:
      Arch: HVM64
    hs1.8xlarge:
      Arch: HVM64
    cr1.8xlarge:
      Arch: HVM64
    cc2.8xlarge:
      Arch: HVM64
  AWSRegionArch2AMI:
    us-east-1:
      PV64: ami-50842d38
      HVM64: ami-08842d60
      HVMG2: ami-3a329952
    us-west-2:
      PV64: ami-af86c69f
      HVM64: ami-8786c6b7
      HVMG2: ami-47296a77
    us-west-1:
      PV64: ami-c7a8a182
      HVM64: ami-cfa8a18a
      HVMG2: ami-331b1376
    eu-west-1:
      PV64: ami-aa8f28dd
      HVM64: ami-748e2903
      HVMG2: ami-00913777
    ap-southeast-1:
      PV64: ami-20e1c572
      HVM64: ami-d6e1c584
      HVMG2: ami-fabe9aa8
    ap-northeast-1:
      PV64: ami-21072820
      HVM64: ami-35072834
      HVMG2: ami-5dd1ff5c
    ap-southeast-2:
      PV64: ami-8b4724b1
      HVM64: ami-fd4724c7
      HVMG2: ami-e98ae9d3
    sa-east-1:
      PV64: ami-9d6cc680
      HVM64: ami-956cc688
      HVMG2: NOT_SUPPORTED
    cn-north-1:
      PV64: ami-a857c591
      HVM64: ami-ac57c595
      HVMG2: NOT_SUPPORTED
    eu-central-1:
      PV64: ami-a03503bd
      HVM64: ami-b43503a9
      HVMG2: ami-b03503ad
Resources:
  WebServerInstance:
    Type: AWS::EC2::Instance
    Metadata:
      Comment: Install a simple PHP application
      AWS::CloudFormation::Init:
        config:
          packages:
            yum:
              httpd: []
              php: []
          files:
            /var/www/html/index.php:
              content: '<?php

                echo ''<h1>AWS CloudFormation sample PHP application</h1>'';

                ?>

                '
              mode: '000644'
              owner: apache
              group: apache
            /etc/cfn/cfn-hup.conf:
              content: !Sub '[main]

                stack=${AWS::StackId}

                region=${AWS::Region}

                '
              mode: '000400'
              owner: root
              group: root
            /etc/cfn/hooks.d/cfn-auto-reloader.conf:
              content: !Sub '[cfn-auto-reloader-hook]

                triggers=post.update

                path=Resources.WebServerInstance.Metadata.AWS::CloudFormation::Init

                action=/opt/aws/bin/cfn-init -s ${AWS::StackId} -r WebServerInstance  --region     ${AWS::Region}

                runas=root

                '
          services:
            sysvinit:
              httpd:
                enabled: 'true'
                ensureRunning: 'true'
              cfn-hup:
                enabled: 'true'
                ensureRunning: 'true'
                files:
                  - /etc/cfn/cfn-hup.conf
                  - /etc/cfn/hooks.d/cfn-auto-reloader.conf
    Properties:
      ImageId: !FindInMap [AWSRegionArch2AMI, !Ref 'AWS::Region', !FindInMap [AWSInstanceType2Arch,
          !Ref 'InstanceType', Arch]]
      InstanceType: !Ref 'InstanceType'
      SecurityGroups:
        - !Ref 'WebServerSecurityGroup'
      UserData: !Base64
        Fn::Sub: '#!/bin/bash -xe

          yum install -y aws-cfn-bootstrap

          # Install the files and packages from the metadata

          /opt/aws/bin/cfn-init -v          --stack ${AWS::StackName}         --resource
          WebServerInstance          --region ${AWS::Region}

          # Start up the cfn-hup daemon to listen for changes to the Web Server metadata

          /opt/aws/bin/cfn-hup || error_exit ''Failed to start cfn-hup''

          # Signal the status from cfn-init

          /opt/aws/bin/cfn-signal -e $?          --stack ${AWS::StackName}         --resource
          WebServerInstance          --region ${AWS::Region}

          '
    CreationPolicy:
      ResourceSignal:
        Timeout: PT5M
  WebServerSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Enable HTTP access via port 80
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: '80'
          ToPort: '80'
          CidrIp: 0.0.0.0/0
Outputs:
  WebsiteURL:
    Description: Application URL
    Value: !Sub 'http://${WebServerInstance.PublicDnsName}'

起動

ともあれ、生成されたテンプレートを元に「初期スタックの作成」を参考にしてCloudFormationをマネジメントコンソールから起動して見ます.
するとデフォルトVPC内にインスタンスが立ち上がっていることが確認できるかと思います.
CloudFormationコンソールの[Output]タブに表示されたアドレスへアクセスすると、AWS CloudFormation sample PHP applicationというメッセージが表示されているかと思います.

テンプレートを読む

一旦起動し終わったところで、どんな構造になっているか読んでいきたいと思います.
長いようでやってることはシンプルなテンプレートなので、そんに項目数は多くないかと思います.

YAMLの最上位には

  • AWSTemplateFormatVersion
  • Description
  • Parameters
  • Mappings
  • Resources
  • Outputs

が並んでいました. それぞれ、

項目 内容
AWSTemplateFormatVersion テンプレートフォーマットのバージョン、基本固定?
Description テンプレートの説明文
Parameters CloudFormation実行時にユーザーが与えるパラメーター
Mappings 与えらた条件に応じて変更される値の定義
Resources 起動されるAWSリソースの設定
Outputs 起動完了後に出力されるメッセージ

といった感じです. Version, Description, Outputは簡単そうなので脇に置いて、残りについて見ていきたいと思います.

Parameters

実行するユーザーが与えるパラメータです.
テンプレートでは下記の通り.

Parameters:
  InstanceType:                               # 項目名
    Description: WebServer EC2 instance type  # 説明
    Type: String                              # 入力される値の型
    Default: m1.small                         # デフォルト値
    AllowedValues:                            # 受け付ける値
      - t1.micro
      # ...
      # 中略
      # ...
    ConstraintDescription: must be ...        # 入力値違反時のエラーメッセージ

これが反映されるとCloudFormation起動画面ではこんな感じになります.

Screen Shot 2017-09-07 at 11.42.15.png

Prameters 以下にセレクトボックスができているのがわかります.
AllowedValueの他にも、AllowedPatternで正規表現で入力値を規定することができます(SSHアクセスを許可するIPアドレスレンジを入力させたいときなど)

Mappings

CloudFormationが実行される条件に応じて、この次のResourcesを変更したいときに利用するための値のマッピングです.

Mappings:
  AWSInstanceType2Arch:
    t1.micro:
      Arch: PV64
      # ...
      # 中略
      # ...
  AWSRegionArch2AMI:
    us-east-1:
      PV64: ami-50842d38
      HVM64: ami-08842d60
      HVMG2: ami-3a329952
      # ...
      # 後略
      # ...

今回はParameterでユーザーから与えられたインスタンスタイプに応じて仮想化の方式を決定したり、実行されたリージョン(+インスタンスタイプ)に応じて選択するAMIを決定しています.

(ParameterとMappingがこのサンプルテンプレートを長くしちゃってる原因、ですね…)

Resources

CloudFormationの本体部分になる、起動されるリソースの設定です.

Resources:
  WebServerInstance:
  # ...
  # 中略
  # ...
  WebServerSecurityGroup:
  # ...
  # 後略
  # ...

と今回はEC2インスタンスとセキュリティグループの2つになります.
ここではEC2の設定について、読んでいこうと思います.
(VPCとサブネットは指定しないとデフォルトが選択される模様)

EC2

ここが一番重たい…気がします.

  WebServerInstance:          # 項目名
    Type: AWS::EC2::Instance    # リソースタイプ
    Metadata:                   # 追加コメントの記載や起動スクリプトの定義や
      # ...
      # 中略
      # ...
    Properties:                 # EC2自身の起動パラメータ
      # ...
      # 中略
      # ...
    CreationPolicy:             # CloudFormation側とのやりとりの設定
      # ...
      # 後略
      # ...

と大きく分けて4つ、要素があります.
Typeはそのままであり、CreationPolicyはこのテンプレートではシンプルなので、ここではMetadataとPropatiesの2つについて見ていきます.

Metadata
    Metadata:
      Comment: Install a simple PHP application
      AWS::CloudFormation::Init:  # 起動スクリプトの設定
        config:
          packages:  # 利用するパッケージ、今回はyumでapacheとphpをインストール
            yum:
              httpd: []
              php: []
          files:     # 設置する設定ファイル類
            /var/www/html/index.php:  # デモ用phpファイル
              content:  # 略
              mode: '000644'
              owner: apache
              group: apache
            /etc/cfn/cfn-hup.conf:  # Stackを通じてEC2のアップデートをするための設定
              content: !Sub '[main]  # !Subで文字列の結合

                stack=${AWS::StackId}  # Stack IDの取得

                region=${AWS::Region}  # リージョンの取得

                '
              mode: '000400'
              owner: root
              group: root
            /etc/cfn/hooks.d/cfn-auto-reloader.conf:  # 同じくアップデートのための設定
              content:  # 略
          services:
            sysvinit:
              httpd:
                enabled: 'true'
                ensureRunning: 'true'
              cfn-hup:
                enabled: 'true'
                ensureRunning: 'true'
                files:
                  - /etc/cfn/cfn-hup.conf
                  - /etc/cfn/hooks.d/cfn-auto-reloader.conf

ドキュメントにあるように、実装の詳細をコメントとして含めたり、AWS::CloudFormation::Initを利用した起動スクリプトの設定ができる箇所になります。

AWS::CloudFormation::Initではyumなどによるインストール、設定ファイルの配置、起動するサービスの選択ができます. 今回はApacheと、CloudFormationスタックを通してEC2の方に変更を反映するためのエージェント(cfn-hup)の設定をしている形になります. ウォークスルーを進めると早速index.phpファイルを変更しスタックをアップデートするのですが、その際CloudFormation側からインスタンス内のindex.phpファイルを触りに行くのにこれを通じて行う、ようです.

参考: cfn-hup

また!Subという組み込み関数を用いて文字列の連結を行なっています.

Properties

EC2本体の設定値やスクリプトの実行を行ないます.

    Properties:
      ImageId: !FindInMap [AWSRegionArch2AMI, !Ref 'AWS::Region', !FindInMap [AWSInstanceType2Arch,
          !Ref 'InstanceType', Arch]]  # AMIのID取得、Mappingsで設定した値を利用
      InstanceType: !Ref 'InstanceType'
      SecurityGroups:
        - !Ref 'WebServerSecurityGroup'
      UserData: !Base64  # スクリプト実行
        Fn::Sub: '#!/bin/bash -xe

          yum install -y aws-cfn-bootstrap

          # Metadataからのファイルとパッケージのインストール

          /opt/aws/bin/cfn-init -v          --stack ${AWS::StackName}         --resource
          WebServerInstance          --region ${AWS::Region}

          # cfn-hup daemon の起動とStackの変更のリッスン開始

          /opt/aws/bin/cfn-hup || error_exit ''Failed to start cfn-hup''

          # インスタンスの状態をCloudFormation側へ通知

          /opt/aws/bin/cfn-signal -e $?          --stack ${AWS::StackName}         --resource
          WebServerInstance          --region ${AWS::Region}

          '

!RefでParameterで指定された値を受け取り、!FindInMapでMappingで設定した値を取得し、EC2の設定パラメータを指定しています. (こうすることでどのリージョンでも起動可能)

また、UserDataにCloudFormation起動時に実行するスクリプトを渡しています. Metadataで記載したファイルやパッケージもここで読み込まれ、インストールが実行されます.

(UserData側に全てインストール項目記載しても良さそうですが、後からスタックを通しての変更ができない、テンプレートの見通しが悪くなる等々デメリットがあるのだと思います.

(追記)改行など整えたもの

自動変換の際、改行を表現するのに1行あける、ということがされていましたが、YAMLでは|が置かれた後の属性は改行を評価する、ということになっているそうです.
これを用いるともう少しスッキリ書けます

リソースのプロパティの追加のSSHによるアクセス追加の部分を加えてあります.

AWSTemplateFormatVersion: '2010-09-09'
Description: 'AWS CloudFormation Sample Template: Sample template that can be used
  to test EC2 updates. **WARNING** This template creates an Amazon Ec2 Instance. You
  will be billed for the AWS resources used if you create a stack from this template.'
Parameters:
  InstanceType:
    Description: WebServer EC2 instance type
    Type: String
    Default: m1.small
    AllowedValues:
      - t1.micro
      - t2.micro
      - t2.small
      - t2.medium
      - m1.small
      - m1.medium
      - m1.large
      - m1.xlarge
      - m2.xlarge
      - m2.2xlarge
      - m2.4xlarge
      - m3.medium
      - m3.large
      - m3.xlarge
      - m3.2xlarge
      - c1.medium
      - c1.xlarge
      - c3.large
      - c3.xlarge
      - c3.2xlarge
      - c3.4xlarge
      - c3.8xlarge
      - g2.2xlarge
      - r3.large
      - r3.xlarge
      - r3.2xlarge
      - r3.4xlarge
      - r3.8xlarge
      - i2.xlarge
      - i2.2xlarge
      - i2.4xlarge
      - i2.8xlarge
      - hi1.4xlarge
      - hs1.8xlarge
      - cr1.8xlarge
      - cc2.8xlarge
      - cg1.4xlarge
    ConstraintDescription: must be a valid EC2 instance type.
  KeyName: 
    Description: Name of an existing Amazon EC2 key pair for SSH access
    Type: AWS::EC2::KeyPair::KeyName
  SSHLocation:
    Description: The IP address range that can be used to SSH to the EC2 instances
    Type: String
    MinLength: 9
    MaxLength: 18
    Default: 192.168.0.1/32
    AllowedPattern: (\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/(\d{1,2})
    ConstraintDescription: must be a valid IP CIDR range of the form x.x.x.x/x.  
Mappings:
  AWSInstanceType2Arch:
    t1.micro:
      Arch: PV64
    t2.micro:
      Arch: HVM64
    t2.small:
      Arch: HVM64
    t2.medium:
      Arch: HVM64
    m1.small:
      Arch: PV64
    m1.medium:
      Arch: PV64
    m1.large:
      Arch: PV64
    m1.xlarge:
      Arch: PV64
    m2.xlarge:
      Arch: PV64
    m2.2xlarge:
      Arch: PV64
    m2.4xlarge:
      Arch: PV64
    m3.medium:
      Arch: HVM64
    m3.large:
      Arch: HVM64
    m3.xlarge:
      Arch: HVM64
    m3.2xlarge:
      Arch: HVM64
    c1.medium:
      Arch: PV64
    c1.xlarge:
      Arch: PV64
    c3.large:
      Arch: HVM64
    c3.xlarge:
      Arch: HVM64
    c3.2xlarge:
      Arch: HVM64
    c3.4xlarge:
      Arch: HVM64
    c3.8xlarge:
      Arch: HVM64
    g2.2xlarge:
      Arch: HVMG2
    r3.large:
      Arch: HVM64
    r3.xlarge:
      Arch: HVM64
    r3.2xlarge:
      Arch: HVM64
    r3.4xlarge:
      Arch: HVM64
    r3.8xlarge:
      Arch: HVM64
    i2.xlarge:
      Arch: HVM64
    i2.2xlarge:
      Arch: HVM64
    i2.4xlarge:
      Arch: HVM64
    i2.8xlarge:
      Arch: HVM64
    hi1.4xlarge:
      Arch: HVM64
    hs1.8xlarge:
      Arch: HVM64
    cr1.8xlarge:
      Arch: HVM64
    cc2.8xlarge:
      Arch: HVM64
  AWSRegionArch2AMI:
    us-east-1:
      PV64: ami-50842d38
      HVM64: ami-08842d60
      HVMG2: ami-3a329952
    us-west-2:
      PV64: ami-af86c69f
      HVM64: ami-8786c6b7
      HVMG2: ami-47296a77
    us-west-1:
      PV64: ami-c7a8a182
      HVM64: ami-cfa8a18a
      HVMG2: ami-331b1376
    eu-west-1:
      PV64: ami-aa8f28dd
      HVM64: ami-748e2903
      HVMG2: ami-00913777
    ap-southeast-1:
      PV64: ami-20e1c572
      HVM64: ami-d6e1c584
      HVMG2: ami-fabe9aa8
    ap-northeast-1:
      PV64: ami-21072820
      HVM64: ami-35072834
      HVMG2: ami-5dd1ff5c
    ap-southeast-2:
      PV64: ami-8b4724b1
      HVM64: ami-fd4724c7
      HVMG2: ami-e98ae9d3
    sa-east-1:
      PV64: ami-9d6cc680
      HVM64: ami-956cc688
      HVMG2: NOT_SUPPORTED
    cn-north-1:
      PV64: ami-a857c591
      HVM64: ami-ac57c595
      HVMG2: NOT_SUPPORTED
    eu-central-1:
      PV64: ami-a03503bd
      HVM64: ami-b43503a9
      HVMG2: ami-b03503ad
Resources:
  WebServerInstance:
    Type: AWS::EC2::Instance
    Metadata:
      Comment: Install a simple PHP application
      AWS::CloudFormation::Init:
        config:
          packages:
            yum:
              httpd: []
              php: []
          files:
            /var/www/html/index.php:
              content: |
                <?php
                echo '<h1>AWS CloudFormation sample PHP application</h1>';
                echo 'Updated virsions via UpdateStack';
                ?>
              mode: '000644'
              owner: apache
              group: apache
            /etc/cfn/cfn-hup.conf:
              content: !Sub |
                [main]
                stack=${AWS::StackId}
                region=${AWS::Region}
              mode: '000400'
              owner: root
              group: root
            /etc/cfn/hooks.d/cfn-auto-reloader.conf:
              content: !Sub |
                [cfn-auto-reloader-hook]
                triggers=post.update
                path=Resources.WebServerInstance.Metadata.AWS::CloudFormation::Init
                action=/opt/aws/bin/cfn-init -s ${AWS::StackId} -r WebServerInstance --region ${AWS::Region}
                runas=root
          services:
            sysvinit:
              httpd:
                enabled: 'true'
                ensureRunning: 'true'
              cfn-hup:
                enabled: 'true'
                ensureRunning: 'true'
                files:
                  - /etc/cfn/cfn-hup.conf
                  - /etc/cfn/hooks.d/cfn-auto-reloader.conf
    Properties:
      ImageId: !FindInMap [AWSRegionArch2AMI, !Ref 'AWS::Region', !FindInMap [AWSInstanceType2Arch,
          !Ref 'InstanceType', Arch]]
      InstanceType: !Ref 'InstanceType'
      SecurityGroups:
        - !Ref 'WebServerSecurityGroup'
      KeyName: !Ref 'KeyName'
      UserData: !Base64
        Fn::Sub: |
          #!/bin/bash -xe
          yum install -y aws-cfn-bootstrap
          # Install the files and packages from the metadata
          /opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource WebServerInstance --region ${AWS::Region}
          # Start up the cfn-hup daemon to listen for changes to the Web Server metadata
          /opt/aws/bin/cfn-hup || error_exit ''Failed to start cfn-hup''
          # Signal the status from cfn-init
          /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource WebServerInstance --region ${AWS::Region}
    CreationPolicy:
      ResourceSignal:
        Timeout: PT5M
  WebServerSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Enable HTTP access via port 80
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: '80'
          ToPort: '80'
          CidrIp: 0.0.0.0/0
        - IpProtocol: tcp
          FromPort: '22'
          ToPort: '22'
          CidrIp: !Ref 'SSHLocation'
Outputs:
  WebsiteURL:
    Description: Application URL
    Value: !Sub 'http://${WebServerInstance.PublicDnsName}'

phpのところで、''で括られていた箇所を'に直していますが、これもYAMLの規定で、文字列中でシングルクォーテーションのエスケープには2つ連ねる、というのを変換のスクリプトが利用していたからでした.


なかなか手が出せなかったCloudFormationだったのですが、ウォークスルーの一番最初の部分について、ドキュメント読み読み進めて見ました.

ウォークスルーでいきなりこの長さはちょっとしんどいですね…

続きを読む

[JAWS-UG CLI] CloudFormation:#7 テンプレートの作成 (デザイナの利用)

デザイナーによるテンプレート作成の例

ウォークスルー: AWS CloudFormation デザイナー を使用して基本的なウェブサーバーを作成します。: http://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/working-with-templates-cfn-designer-walkthrough-createbasicwebserver.html

ステップ3まで実施します。

スクリーンショット 2017-06-12 17.32.57.png

テンプレートの作成結果例

テンプレートの例
{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Metadata": {
        "AWS::CloudFormation::Designer": {
            "2e84feb3-cb7f-47d8-a50b-73d6e89de7bc": {
                "size": {
                    "width": 710,
                    "height": 220
                },
                "position": {
                    "x": 100,
                    "y": 130
                },
                "z": 0,
                "embeds": [
                    "25d45e53-d776-4534-b244-b9a49c15b6ff",
                    "09677cca-68f1-478f-842e-32018f9bf5fa",
                    "4a16106f-3988-4902-ba28-2fcf5bc1d48d"
                ]
            },
            "09677cca-68f1-478f-842e-32018f9bf5fa": {
                "size": {
                    "width": 140,
                    "height": 140
                },
                "position": {
                    "x": 180,
                    "y": 200
                },
                "z": 1,
                "parent": "2e84feb3-cb7f-47d8-a50b-73d6e89de7bc",
                "embeds": [
                    "5227546f-a488-4322-b146-17e159d2657f"
                ]
            },
            "5227546f-a488-4322-b146-17e159d2657f": {
                "size": {
                    "width": 60,
                    "height": 60
                },
                "position": {
                    "x": 228,
                    "y": 236
                },
                "z": 2,
                "parent": "09677cca-68f1-478f-842e-32018f9bf5fa",
                "embeds": [],
                "dependson": [
                    "1e86fca9-84d1-4d05-9e68-efb1df27d4c5"
                ],
                "isrelatedto": [
                    "25d45e53-d776-4534-b244-b9a49c15b6ff"
                ]
            },
            "25d45e53-d776-4534-b244-b9a49c15b6ff": {
                "size": {
                    "width": 60,
                    "height": 60
                },
                "position": {
                    "x": 480,
                    "y": 180
                },
                "z": 1,
                "parent": "2e84feb3-cb7f-47d8-a50b-73d6e89de7bc",
                "embeds": []
            },
            "0e5d222f-40cb-4c52-b251-80c744846be5": {
                "size": {
                    "width": 60,
                    "height": 60
                },
                "position": {
                    "x": 880,
                    "y": 220
                },
                "z": 0,
                "embeds": []
            },
            "5637b4f3-df45-40fb-a91d-dae734a3abdd": {
                "source": {
                    "id": "0e5d222f-40cb-4c52-b251-80c744846be5"
                },
                "target": {
                    "id": "2e84feb3-cb7f-47d8-a50b-73d6e89de7bc"
                },
                "z": 0
            },
            "75da879a-0efa-427e-8071-077ba3a16212": {
                "source": {
                    "id": "0e5d222f-40cb-4c52-b251-80c744846be5"
                },
                "target": {
                    "id": "2e84feb3-cb7f-47d8-a50b-73d6e89de7bc"
                },
                "z": 0
            },
            "4a16106f-3988-4902-ba28-2fcf5bc1d48d": {
                "size": {
                    "width": 140,
                    "height": 140
                },
                "position": {
                    "x": 650,
                    "y": 170
                },
                "z": 1,
                "parent": "2e84feb3-cb7f-47d8-a50b-73d6e89de7bc",
                "embeds": [
                    "1e86fca9-84d1-4d05-9e68-efb1df27d4c5"
                ],
                "dependson": [
                    "09677cca-68f1-478f-842e-32018f9bf5fa"
                ]
            },
            "1e86fca9-84d1-4d05-9e68-efb1df27d4c5": {
                "size": {
                    "width": 60,
                    "height": 60
                },
                "position": {
                    "x": 700,
                    "y": 240
                },
                "z": 2,
                "parent": "4a16106f-3988-4902-ba28-2fcf5bc1d48d",
                "embeds": [],
                "references": [
                    "0e5d222f-40cb-4c52-b251-80c744846be5"
                ],
                "dependson": [
                    "0e5d222f-40cb-4c52-b251-80c744846be5"
                ]
            },
            "a1cc9b57-b454-483b-8e86-4e4e0cd9cacb": {
                "source": {
                    "id": "1e86fca9-84d1-4d05-9e68-efb1df27d4c5"
                },
                "target": {
                    "id": "0e5d222f-40cb-4c52-b251-80c744846be5"
                },
                "z": 3
            },
            "522ea7e3-d856-43d9-97c0-ab3da44fc19c": {
                "source": {
                    "id": "5227546f-a488-4322-b146-17e159d2657f"
                },
                "target": {
                    "id": "1e86fca9-84d1-4d05-9e68-efb1df27d4c5"
                },
                "z": 4
            },
            "b617925c-337f-46dc-bf6c-d8d61ff8d687": {
                "source": {
                    "id": "4a16106f-3988-4902-ba28-2fcf5bc1d48d"
                },
                "target": {
                    "id": "09677cca-68f1-478f-842e-32018f9bf5fa"
                },
                "z": 5
            },
            "b8d8deca-616b-4d76-8797-873228e79f9d": {
                "source": {
                    "id": "1e86fca9-84d1-4d05-9e68-efb1df27d4c5"
                },
                "target": {
                    "id": "0e5d222f-40cb-4c52-b251-80c744846be5"
                },
                "z": 3
            },
            "25d0fe02-7713-433a-88a0-7f85890eb289": {
                "source": {
                    "id": "1e86fca9-84d1-4d05-9e68-efb1df27d4c5"
                },
                "target": {
                    "id": "0e5d222f-40cb-4c52-b251-80c744846be5"
                },
                "z": 4
            },
            "f818e69a-a5cb-4569-92b0-a5bbab980380": {
                "source": {
                    "id": "4a16106f-3988-4902-ba28-2fcf5bc1d48d"
                },
                "target": {
                    "id": "09677cca-68f1-478f-842e-32018f9bf5fa"
                },
                "z": 3
            }
        }
    },
    "Resources": {
        "VPC": {
            "Type": "AWS::EC2::VPC",
            "Properties": {
                "EnableDnsSupport": "true",
                "EnableDnsHostnames": "true",
                "CidrBlock": "10.0.0.0/16"
            },
            "Metadata": {
                "AWS::CloudFormation::Designer": {
                    "id": "2e84feb3-cb7f-47d8-a50b-73d6e89de7bc"
                }
            }
        },
        "PublicSubnet": {
            "Type": "AWS::EC2::Subnet",
            "Properties": {
                "VpcId": {
                    "Ref": "VPC"
                },
                "CidrBlock": "10.0.0.0/24"
            },
            "Metadata": {
                "AWS::CloudFormation::Designer": {
                    "id": "09677cca-68f1-478f-842e-32018f9bf5fa"
                }
            }
        },
        "WebServerInstance": {
            "Type": "AWS::EC2::Instance",
            "Properties": {
                "InstanceType": {
                    "Ref": "InstanceType"
                },
                "ImageId": {
                    "Fn::FindInMap": [
                        "AWSRegionArch2AMI",
                        {
                            "Ref": "AWS::Region"
                        },
                        {
                            "Fn::FindInMap": [
                                "AWSInstanceType2Arch",
                                {
                                    "Ref": "InstanceType"
                                },
                                "Arch"
                            ]
                        }
                    ]
                },
                "KeyName": {
                    "Ref": "KeyName"
                },
                "NetworkInterfaces": [
                    {
                        "GroupSet": [
                            {
                                "Ref": "WebServerSecurityGroup"
                            }
                        ],
                        "AssociatePublicIpAddress": "true",
                        "DeviceIndex": "0",
                        "DeleteOnTermination": "true",
                        "SubnetId": {
                            "Ref": "PublicSubnet"
                        }
                    }
                ],
                "UserData": {
                    "Fn::Base64": {
                        "Fn::Join": [
                            "",
                            [
                                "#!/bin/bash -xen",
                                "yum install -y aws-cfn-bootstrapn",
                                "# Install the files and packages from the metadatan",
                                "/opt/aws/bin/cfn-init -v ",
                                "         --stack ",
                                {
                                    "Ref": "AWS::StackName"
                                },
                                "         --resource WebServerInstance ",
                                "         --configsets All ",
                                "         --region ",
                                {
                                    "Ref": "AWS::Region"
                                },
                                "n",
                                "# Signal the status from cfn-initn",
                                "/opt/aws/bin/cfn-signal -e $? ",
                                "         --stack ",
                                {
                                    "Ref": "AWS::StackName"
                                },
                                "         --resource WebServerInstance ",
                                "         --region ",
                                {
                                    "Ref": "AWS::Region"
                                },
                                "n"
                            ]
                        ]
                    }
                }
            },
            "Metadata": {
                "AWS::CloudFormation::Designer": {
                    "id": "5227546f-a488-4322-b146-17e159d2657f"
                },
                "AWS::CloudFormation::Init": {
                    "configSets": {
                        "All": [
                            "ConfigureSampleApp"
                        ]
                    },
                    "ConfigureSampleApp": {
                        "packages": {
                            "yum": {
                                "httpd": []
                            }
                        },
                        "files": {
                            "/var/www/html/index.html": {
                                "content": {
                                    "Fn::Join": [
                                        "n",
                                        [
                                            "<h1>Congratulations, you have successfully launched the AWS CloudFormation sample.</h1>"
                                        ]
                                    ]
                                },
                                "mode": "000644",
                                "owner": "root",
                                "group": "root"
                            }
                        },
                        "services": {
                            "sysvinit": {
                                "httpd": {
                                    "enabled": "true",
                                    "ensureRunning": "true"
                                }
                            }
                        }
                    }
                }
            },
            "DependsOn": [
                "PublicRoute"
            ]
        },
        "WebServerSecurityGroup": {
            "Type": "AWS::EC2::SecurityGroup",
            "Properties": {
                "VpcId": {
                    "Ref": "VPC"
                },
                "GroupDescription": "Allow access from HTTP and SSH traffic",
                "SecurityGroupIngress": [
                    {
                        "IpProtocol": "tcp",
                        "FromPort": "80",
                        "ToPort": "80",
                        "CidrIp": "0.0.0.0/0"
                    },
                    {
                        "IpProtocol": "tcp",
                        "FromPort": "22",
                        "ToPort": "22",
                        "CidrIp": {
                            "Ref": "SSHLocation"
                        }
                    }
                ]
            },
            "Metadata": {
                "AWS::CloudFormation::Designer": {
                    "id": "25d45e53-d776-4534-b244-b9a49c15b6ff"
                }
            }
        },
        "InternetGateway": {
            "Type": "AWS::EC2::InternetGateway",
            "Properties": {},
            "Metadata": {
                "AWS::CloudFormation::Designer": {
                    "id": "0e5d222f-40cb-4c52-b251-80c744846be5"
                }
            }
        },
        "EC2VPCG1BZXP": {
            "Type": "AWS::EC2::VPCGatewayAttachment",
            "Properties": {
                "InternetGatewayId": {
                    "Ref": "InternetGateway"
                },
                "VpcId": {
                    "Ref": "VPC"
                }
            },
            "Metadata": {
                "AWS::CloudFormation::Designer": {
                    "id": "5637b4f3-df45-40fb-a91d-dae734a3abdd"
                }
            }
        },
        "EC2VPCGO08Z": {
            "Type": "AWS::EC2::VPCGatewayAttachment",
            "Properties": {
                "InternetGatewayId": {
                    "Ref": "InternetGateway"
                },
                "VpcId": {
                    "Ref": "VPC"
                }
            },
            "Metadata": {
                "AWS::CloudFormation::Designer": {
                    "id": "75da879a-0efa-427e-8071-077ba3a16212"
                }
            }
        },
        "PublicRouteTable": {
            "Type": "AWS::EC2::RouteTable",
            "Properties": {
                "VpcId": {
                    "Ref": "VPC"
                }
            },
            "Metadata": {
                "AWS::CloudFormation::Designer": {
                    "id": "4a16106f-3988-4902-ba28-2fcf5bc1d48d"
                }
            },
            "DependsOn": [
                "PublicSubnet"
            ]
        },
        "PublicRoute": {
            "Type": "AWS::EC2::Route",
            "Properties": {
                "DestinationCidrBlock": "0.0.0.0/0",
                "RouteTableId": {
                    "Ref": "PublicRouteTable"
                },
                "GatewayId": {
                    "Ref": "InternetGateway"
                }
            },
            "Metadata": {
                "AWS::CloudFormation::Designer": {
                    "id": "1e86fca9-84d1-4d05-9e68-efb1df27d4c5"
                }
            },
            "DependsOn": [
                "InternetGateway"
            ]
        },
        "EC2SRTA3CLE1": {
            "Type": "AWS::EC2::SubnetRouteTableAssociation",
            "Properties": {
                "RouteTableId": {
                    "Ref": "PublicRouteTable"
                },
                "SubnetId": {
                    "Ref": "PublicSubnet"
                }
            },
            "Metadata": {
                "AWS::CloudFormation::Designer": {
                    "id": "f818e69a-a5cb-4569-92b0-a5bbab980380"
                }
            }
        }
    },
    "Parameters": {
        "InstanceType": {
            "Description": "WebServer EC2 instance type",
            "Type": "String",
            "Default": "t2.micro",
            "AllowedValues": [
                "t1.micro",
                "t2.micro",
                "t2.small",
                "t2.medium",
                "m1.small",
                "m1.medium",
                "m1.large",
                "m1.xlarge",
                "m2.xlarge",
                "m2.2xlarge",
                "m2.4xlarge",
                "m3.medium",
                "m3.large",
                "m3.xlarge",
                "m3.2xlarge",
                "c1.medium",
                "c1.xlarge",
                "c3.large",
                "c3.xlarge",
                "c3.2xlarge",
                "c3.4xlarge",
                "c3.8xlarge",
                "c4.large",
                "c4.xlarge",
                "c4.2xlarge",
                "c4.4xlarge",
                "c4.8xlarge",
                "g2.2xlarge",
                "r3.large",
                "r3.xlarge",
                "r3.2xlarge",
                "r3.4xlarge",
                "r3.8xlarge",
                "i2.xlarge",
                "i2.2xlarge",
                "i2.4xlarge",
                "i2.8xlarge",
                "d2.xlarge",
                "d2.2xlarge",
                "d2.4xlarge",
                "d2.8xlarge",
                "hi1.4xlarge",
                "hs1.8xlarge",
                "cr1.8xlarge",
                "cc2.8xlarge",
                "cg1.4xlarge"
            ],
            "ConstraintDescription": "must be a valid EC2 instance type."
        },
        "KeyName": {
            "Description": "Name of an EC2 KeyPair to enable SSH access to the instance.",
            "Type": "AWS::EC2::KeyPair::KeyName",
            "ConstraintDescription": "must be the name of an existing EC2 KeyPair."
        },
        "SSHLocation": {
            "Description": " The IP address range that can be usedto access the web server using SSH.",
            "Type": "String",
            "MinLength": "9",
            "MaxLength": "18",
            "Default": "0.0.0.0/0",
            "AllowedPattern": "(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/(\d{1,2})",
            "ConstraintDescription": "must be a valid IP CIDR range of the form x.x.x.x/x."
        }
    },
    "Mappings": {
        "AWSInstanceType2Arch": {
            "t1.micro": {
                "Arch": "PV64"
            },
            "t2.micro": {
                "Arch": "HVM64"
            },
            "t2.small": {
                "Arch": "HVM64"
            },
            "t2.medium": {
                "Arch": "HVM64"
            },
            "m1.small": {
                "Arch": "PV64"
            },
            "m1.medium": {
                "Arch": "PV64"
            },
            "m1.large": {
                "Arch": "PV64"
            },
            "m1.xlarge": {
                "Arch": "PV64"
            },
            "m2.xlarge": {
                "Arch": "PV64"
            },
            "m2.2xlarge": {
                "Arch": "PV64"
            },
            "m2.4xlarge": {
                "Arch": "PV64"
            },
            "m3.medium": {
                "Arch": "HVM64"
            },
            "m3.large": {
                "Arch": "HVM64"
            },
            "m3.xlarge": {
                "Arch": "HVM64"
            },
            "m3.2xlarge": {
                "Arch": "HVM64"
            },
            "c1.medium": {
                "Arch": "PV64"
            },
            "c1.xlarge": {
                "Arch": "PV64"
            },
            "c3.large": {
                "Arch": "HVM64"
            },
            "c3.xlarge": {
                "Arch": "HVM64"
            },
            "c3.2xlarge": {
                "Arch": "HVM64"
            },
            "c3.4xlarge": {
                "Arch": "HVM64"
            },
            "c3.8xlarge": {
                "Arch": "HVM64"
            },
            "c4.large": {
                "Arch": "HVM64"
            },
            "c4.xlarge": {
                "Arch": "HVM64"
            },
            "c4.2xlarge": {
                "Arch": "HVM64"
            },
            "c4.4xlarge": {
                "Arch": "HVM64"
            },
            "c4.8xlarge": {
                "Arch": "HVM64"
            },
            "g2.2xlarge": {
                "Arch": "HVMG2"
            },
            "r3.large": {
                "Arch": "HVM64"
            },
            "r3.xlarge": {
                "Arch": "HVM64"
            },
            "r3.2xlarge": {
                "Arch": "HVM64"
            },
            "r3.4xlarge": {
                "Arch": "HVM64"
            },
            "r3.8xlarge": {
                "Arch": "HVM64"
            },
            "i2.xlarge": {
                "Arch": "HVM64"
            },
            "i2.2xlarge": {
                "Arch": "HVM64"
            },
            "i2.4xlarge": {
                "Arch": "HVM64"
            },
            "i2.8xlarge": {
                "Arch": "HVM64"
            },
            "d2.xlarge": {
                "Arch": "HVM64"
            },
            "d2.2xlarge": {
                "Arch": "HVM64"
            },
            "d2.4xlarge": {
                "Arch": "HVM64"
            },
            "d2.8xlarge": {
                "Arch": "HVM64"
            },
            "hi1.4xlarge": {
                "Arch": "HVM64"
            },
            "hs1.8xlarge": {
                "Arch": "HVM64"
            },
            "cr1.8xlarge": {
                "Arch": "HVM64"
            },
            "cc2.8xlarge": {
                "Arch": "HVM64"
            }
        },
        "AWSRegionArch2AMI": {
            "us-east-1": {
                "PV64": "ami-1ccae774",
                "HVM64": "ami-1ecae776",
                "HVMG2": "ami-8c6b40e4"
            },
            "us-west-2": {
                "PV64": "ami-ff527ecf",
                "HVM64": "ami-e7527ed7",
                "HVMG2": "ami-abbe919b"
            },
            "us-west-1": {
                "PV64": "ami-d514f291",
                "HVM64": "ami-d114f295",
                "HVMG2": "ami-f31ffeb7"
            },
            "eu-west-1": {
                "PV64": "ami-bf0897c8",
                "HVM64": "ami-a10897d6",
                "HVMG2": "ami-d5bc24a2"
            },
            "eu-central-1": {
                "PV64": "ami-ac221fb1",
                "HVM64": "ami-a8221fb5",
                "HVMG2": "ami-7cd2ef61"
            },
            "ap-northeast-1": {
                "PV64": "ami-27f90e27",
                "HVM64": "ami-cbf90ecb",
                "HVMG2": "ami-6318e863"
            },
            "ap-southeast-1": {
                "PV64": "ami-acd9e8fe",
                "HVM64": "ami-68d8e93a",
                "HVMG2": "ami-3807376a"
            },
            "ap-southeast-2": {
                "PV64": "ami-ff9cecc5",
                "HVM64": "ami-fd9cecc7",
                "HVMG2": "ami-89790ab3"
            },
            "sa-east-1": {
                "PV64": "ami-bb2890a6",
                "HVM64": "ami-b52890a8",
                "HVMG2": "NOT_SUPPORTED"
            },
            "cn-north-1": {
                "PV64": "ami-fa39abc3",
                "HVM64": "ami-f239abcb",
                "HVMG2": "NOT_SUPPORTED"
            }
        }
    },
    "Outputs": {
        "URL": {
            "Value": {
                "Fn::Join": [
                    "",
                    [
                        "http://",
                        {
                            "Fn::GetAtt": [
                                "WebServerInstance",
                                "PublicIp"
                            ]
                        }
                    ]
                ]
            },
            "Description": "Newly created application URL"
        }
    }
}

続きを読む

【AWS】CloudFormation

はじめに

タダです。

AWS認定資格の試験勉強のためにCloudFormationの情報をまとめた自分用メモになります。
あくまで個人用のメモになるので、その点はご了承ください。
※違う内容書いているなどありましたらご指摘いただけると幸いです。
※随時アップデートがあれば更新していきます。

CloudFormationとは

AWSリソースを作成したり、管理するのが役立つツールです。JSONやYAML形式でリソース定義できる

CloudFormationを使う主なメリットは以下の通り

  • AWSリソース管理が簡略化
  • インフラリソースを素早く展開/複製
  • インフラリソースの制御や変更も簡単

Elatic Beanstalkとの違い

  • Elatic Beanstalkはアプリを簡単にデプロイ及び実行できる環境を提供する

    • アプリのライフサイクルを管理するためのサービス
  • CloudFormationはAWSリソースの作成をサポートする
    • Elatic Beanstalkもサポートしている

CloudFormationの概念

  • テンプレート

    • YAMLまたはJSON形式のテキストファイルでAWSリソース作成のための設計図

      • 5種類の要素で構成される

        • テンプレートパラメータのオプションリスト
        • 出力値のオプションリスト
        • 静的な設定値を見るのに使用するデータテーブルのオプションリスト
        • AWS リソースとそれらの設定値のリスト
        • テンプレートファイルフォーマットのバージョン番号
    • 具体的には以下のようなものがテンプレート例
{
  "AWSTemplateFormatVersion" : "2010-09-09",
  "Description" : "A sample template",
  "Resources" : {
    "MyEC2Instance" : {
      "Type" : "AWS::EC2::Instance",
      "Properties" : {
        "ImageId" : "ami-2f726546",
        "InstanceType" : "t1.micro",
        "KeyName" : "testkey",
        "BlockDeviceMappings" : [
          {
            "DeviceName" : "/dev/sdm",
            "Ebs" : {
              "VolumeType" : "io1",
              "Iops" : "200",
              "DeleteOnTermination" : "false",
              "VolumeSize" : "20"
            }
          }
        ]
      }
    }
  }
}
  • スタック

    • CloudFormationの関連リソースは、スタックと呼ばれます。これを作成、変更、更新することでリソース制御を行う
    • スタックの更新には2つの方式がある
      • 直接更新(in place)と変更セットの作成(blue-green)と実行
  • 変更セット
    • スタックの更新をおこなう時の概要が変更セットと呼び、影響度を確認するためのスタック

変更セットについて

変更セットの作成

更新元のスタックをもとに変更セットを作成します
Cloudformation -> [Actions],[Create Change Set For Current Stack]を選択
その他のパラメーターは、スタックを作成するのと同じ操作で行う
CLIだと、以下のように実行する

aws cloudformation create-change-set --stack-name arn:aws:cloudformation:us-east-1:123456789012:stack/SampleStack/1a2345b6-0000-00a0-a123-00abc0abc000
--change-set-name SampleChangeSet --use-previous-template --parameters ParameterKey="InstanceType",UsePreviousValue=true ParameterKey="KeyPairName",UsePreviousValue=true ParameterKey="Purpose",ParameterValue="production"

変更セットの実行

変更セットに記述された変更をスタックに加えるには、変更セットを実行する
※変更セットを実行するとスタックに関連付けられた変更セットは削除される点は注意。
CLIだと、以下のように実行する

aws cloudformation execute-change-set --change-set-name arn:aws:cloudformation:us-east-1:123456789012:changeSet/SampleChangeSet/1a2345b6-0000-00a0-a123-00abc0abc000

CloudFormationのベストプラクティス

  • スタックは共通リソースの所有者でグルーピング

    • リソース利用の制限は行わないようにする
  • クロススタック参照で共有リソースをエクスポート
    • ネットワークリソース系
  • アクセス制限はIAMで
  • スタックの制限は200なので、注意
  • テンプレートの再利用
  • 他のスタックにネストされたテンプレートの参照
  • テンプレートに認証情報を埋め込まない
    • 埋め込んでもNoEchoプロパティを使う
  • cfn-init ヘルパースクリプトと AWS::CloudFormation::Init を使ってEC2にソフトウェアをインストールする
  • ヘルパースクリプトは常に最新のものを使う
  • テンプレートを使用する前に検証する
    • aws cloudformation validate-template
  • CloudFormationで全てのリソースを管理する
  • スタックを更新する前に変更セットを作成する
  • CloudTrailとロギング
  • コードの確認とリビジョン管理
  • Elastic Compute Cloudのパッケージは最新化する

CloudFormationのテンプレート

JSONかYAMLのどちらかでテンプレートを作成します。

テンプレートのセクション

  • Format Version(任意)

    • テンプレートバージョンを指定する
  • Desription(任意)
    • 説明文
  • Metadata(任意)
    • テンプレートに関する追加情報を提供するオブジェクト
  • Parameters(任意)
    • テンプレートに渡すことができる値を指定する

      • データ型、デフォルト値、最大最小値など型が設定可能
    • テンプレートのResources、Outputsセクションのパラメーターを参照できる
  • Mappings(任意)
    • 条件パラメーター値の指定に使用できる、キーと関連する値のマッピング(検索テーブルに類似したもの)
  • Conditions(任意)
    • 特定のリソースが作成されるかどうかや、スタックの作成または更新中に特定のリソースプロパティが値を割り当てられるかどうかを制御する条件を定義する
  • Transform(任意)
    • サーバレスアプリケーションの場合、使用するAWS SAMのバージョンを指定する
  • Resources(必須)
    • スタックで作成するリソースとそのプロパティを指定する

      • EC2やELBやRDSなど起動するサービスを指定し、リソース毎に決められたプロパティを指定する
  • Outputs(任意)
    • スタックのプロパティを確認すると返される値について説明する
  • Function
    • パラメータの参照やMapの参照などの際はFunctionを使う(Parameterの取得に利用するRef関数もFunctionの一つ)

      • Ref: パラメータの参照
      • Fn::Base64 : 文字列をBase64でエンコードする
      • Fn::FindInMap : Mapから値を取り出す
      • Fn::GetAtt :リソースに付随する値を取得する
      • Fn::GetAZs : 指定したリージョンのAZを取得する
  • 疑似パラメータ参照
    • 予め定義されたパラメータ群をRef関数で参照できる

      • AWS::Region,AWS::StackId,AWS::StackNameなど

スタックの出力値のエクスポート

  • スタック間で情報を共有するにはスタックの出力値をエクスポートする

    • 同じAWSアカウントとリージョンの他のスタックは、エクスポートされた値をインポートできる
    • WebサーバのサブネットやSecurityGroup IDをエクスポートする単一ネットワーキングスタックがあったとして、Webサーバのあるスタックは、それらのネットワーキングしリソースをインポートできる

テンプレート作成ツール

  • CloudFormer

    • 構築済みの環境からテンプレートを作成するWebツール
  • CloudFormation Designer
    • テンプレート内のリソースを可視化
  • Hava
  • Cloudcraft

CloudFormationの運用

  • 個別テンプレート、1スタック
  • 個別テンプレート、個別スタック
  • スタック間の連携

CloudFormationのリソースについて

リソース属性

CreationPolicy

  • CloudFormationが指定数の成功シグナルを受信するかまたはタイムアウト期間が超過するまでは、ステータスが作成完了にならないようにする

    • AutoScalingCreationPolicy
    • ResourceSignal

DeletionPolicy

  • スタックが削除された際にリソースを保持または (場合によっては) バックアップできる

    • Retain

      • スタック削除したくない場合は指定する

DependsOn

  • 特定のリソースが他のリソースに続けて作成されるように指定できる

UpdatePolicy属性

  • CloudFormationがAWS::AutoScaling::AutoScalingGroup リソースに対する更新を処理する方法を指定できる

    • AutoScalingReplacingUpdate

      • AutoScaling グループの置き換え更新を処理する方法を指定する時に使う
    • AutoScalingRollingUpdate
      • ローリング更新を使う場合指定する
    • AutoScalingScheduledAction
      • スケジュールされたアクションが関連付けられているAutoScalingグループを含むスタックを更新する時に使う

CloudFormationヘルパースクリプト

スタック作成の時にEC2インスタンスでソフトウェアをインストールしたりサービスを開始したりするために使用できるPythonヘルパースクリプトのセットがある

  • cfn-init

    • リソースメタデータの取得と解釈、パッケージのインストール、ファイルの作成およびサービスの開始で使用される
  • cfn-signal
    • スタック内の他のリソースと準備できたアプリケーションを同期できる
  • cfn-getmetadata
    • リソースに定義されたすべてのメタデータ、またはリソースメタデータの特定のキーやサブツリーへのパスを簡単に取得できる
  • cfn-hup
    • メタデータへの更新を確認し、変更が検出された時にカスタムフックを実行するデーモン

参考情報

サービス概要
よくある質問
ドキュメント
SlideShare

更新日時

  • 2017/04/30 初回投稿

続きを読む