[AWS] CloudFormation 使ってみた
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