💭

[AWS] CloudFormation 使ってみた

2022/06/20に公開

CloudFormation?

ECSとか作る時、今までAWSのコンソールGUIでポチポチと設定して作成していた。
CloudFormationは、各種リソース設定をテンプレートファイルに記述してコマンド等で一括構築できる。

コスト

CloudFormationは無料。

用語

  • テンプレート : 設計図となるファイル。yaml 形式と json 形式がある
  • リソース : 個々のAWSサービス。EC2とかVPCとか
  • スタック : テンプレートから作成されるリソース群

テンプレートファイル

以下解説はyaml。

冒頭は定型文

バージョンとか。

AWSTemplateFormatVersion: '2010-09-09'
Description: 'スタックの説明'

パラメータ

他の部分で、 組み込み関数を使い、 !Ref ParamName!Sub ${ParamName} みたいな形で参照できる。

Parameters:
  <パラメータ名>:
    Type: String | Number | etc.
    Description: パラメータの説明
    Default: デフォルト値

マッピング

連想配列のようなパラメータ。

Mappings:
  <マッピング名>:
    <トップレベルキー>:
      <セカンドレベルキー>: マッピング値

出力

構築成功した時に、他のyamlで参照するためのリソースIDとかを出力。
出力内容は、後述の !Ref , !GetAtt 等の組み込み関数を使う。

Outputs:
  <出力名>:
    Description: 出力内容の説明
    Value: 出力内容

リソース

メインの部分。構築するリソース(サービス)を列挙する。

  • <リソース論理ID> : わかりやすいリソース名称。例: MyVPC
  • <リソースタイプ> : 例: AWS::EC2::VPC
Resources:
  <リソース論理ID>:
    Type: <リソースタイプ>
    Properties:
      # ...

Parameters ファイル

Gitでアップロードしたくないセンシティブ情報群や他スタックの出力から受け継ぐ情報は、別のyamlファイル(例: ecs.params.yaml )として作成し、 .gitignore に含めておく。
構文は以下。
ParameterKey は、対応するテンプレートファイル内のパラメータ名と一致させる。
ParameterValue の型は string のみ?

Parameters:
- ParameterKey: '<パラメータ名>'
  ParameterValue: '<パラメータ値>'

スタックの作成

AWS CLI をインストールしておく。

$ aws cloudformation create-stack \
  --stack-name <スタック名> \
  --template-body file://<現在ディレクトリ>/<テンプレートファイル>.yaml \
  --cli-input-yaml file://<現在ディレクトリ>/<Parametersファイル>.yaml \
  --capabilities CAPABILITY_NAMED_IAM

スタック作成進行状況は AWS コンソールで確認。

スタックの削除

$ aws cloudformation delete-stack --stack-name <スタック名>

参考: よく使う組み込み関数

参考:組み込み関数リファレンス

  • !Ref <パラメータ名> : パラメータ値を返す
  • !Ref <リソース論理ID> : リソースによって物理IDとかARNとか違うものを返す。後述。
  • !Sub '<文字列>' : 文字列内にある ${パラメータ名} ${リソース論理ID} を実際の値に置き換えた文字列を返す。
  • !GetAtt <リソース論理ID>.<属性> : リソースの属性の取得。よく使うのは Amazon Resource Name (ARN) の取得。(例: !GetAtt MyECS.Arn
  • !FindInMap [ <マッピング名>, <トップレベルキー>, <セカンドレべルキー> ]

参考: !Ref で返される値

リソースにより、物理IDだったり、Resource Name だったり、Amazon Resource Name (ARN) だったり(Resource Nameとは別物?)。

参考: AWS リソースおよびプロパティタイプのリファレンス
(各リソースページ内の Return values -> Ref に記載あり)

よく使うもの抜粋:

返値 リソースタイプ
物理ID subnet-XXXXX AWS::EC2::VPC
AWS::EC2::RouteTable
AWS::EC2::Route
AWS::EC2::Subnet
AWS::EC2::SecurityGroup (VpcId 指定した場合)
AWS::EC2::SpotFleet
AWS::CloudFront::Distribution
(ディストリビューションID?)
リソース名 mystack-igw-XXXXX AWS::EC2::InternetGateway
AWS::EC2::KeyPair
AWS::ECS::Cluster
AWS::IAM::InstanceProfile
AWS::IAM::Role
AWS::IAM::Policy
ARN arn:aws:s3:region:account:XXX AWS::ECS::TaskDefinition
AWS::ECS::Service

参考: !Sub の活用

リテラルブロックで、組み込みシェルスクリプトを見やすくする。

UserData:
  Fn::Base64:
    !Sub |
      #!/bin/bash -xe
      yum update -y aws-cfn-bootstrap
      /opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource LaunchConfig --configsets wordpress_install --region ${AWS::Region}
      /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource WebServerGroup --region ${AWS::Region}

参考: !FindInMap の活用

インスタンスタイプによって使用するAMIを変える。
例えば、t4g は ARM 用 AMI、t3a は x86 用 AMI

Mappings:
  AWSInstanceTypeToAMI:
    t4g.micro:
      AMI: ami-049f231a6d31cfc28
    t3a.micro:
      AMI: ami-0f87d679e2fccd272
Resources:
  SpotFleet:
    Type: AWS::EC2::SpotFleet
    Properties:
      SpotFleetRequestConfigData:
        LaunchSpecifications:
        - ImageId: !FindInMap [ AWSInstanceTypeToAMI, !Ref InstanceType, AMI ]

Discussion