【初心者向け】CloudFormationテンプレートの読み方
こんにちは。深緑です。
最近は周りにCloudFormationを広めようと頑張っています。
今回はCloudFormationの初学者に向けて記事を書いてみます。
はじめに
本記事ではCloudFormationテンプレートの読み方について記載します。
個人的に初めてCloudFormationテンプレートを見た時、とっつきにくさを感じました。
独自の構造とプロビジョニングツール自体への理解不足から来るものと思いますが、
同じにように感じられる方もいる気がするので、
CloudFormationテンプレートはどのように読み進めるのかということを書いてみます。
- 本記事ではCloudFormationテンプレートをyaml形式で書いています。
- テンプレートの具体的な書き方はまでは触れません。
サンプルソース
DynamoDBテーブルとそのバックアップ・アラームをセットするCloudFormationです。
セクション
CloudFormationテンプレートにはセクションという区切りがあります。
AWS公式 - テンプレートの分析
取り急ぎ、パラメータ(Parameters)とリソース(Resources)セクションをとてもよく使うので、
これらを抑えてておきます。
パラメータ(Parameters)セクション
Parameters:
ProjectName:
Description: Project name
Type: String
EnvironmentName:
Description: Environment name
Type: String
Default: STG
AllowedValues:
- STG
- PRD
入力パラメータの定義です。
ここを定義しておくと、CloudFormationのテンプレートを実行する時にパラメータの入力を求めることができます。
パラメータの型・初期値・選択肢などが指定できます。
この例では文字列型しかありませんが、パラメタータとしてEC2のインスタンスIDが欲しい場合は、
Parameters:
InstanceId:
Type: AWS::EC2::Instance::Id
のようにして存在するEC2から選ぶ形式にすることもできます。
なお、Descriptionは現状日本語は使えないようです。
リソース(Resources)セクション
Resources:
# ------------------------------------------------------------#
# DynamoDB
# 参考
# https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/gettingstarted.templatebasics.html
# ------------------------------------------------------------#
DynamoDBTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: !Sub ${ProjectName}-${EnvironmentName}-DynamoDB-Table
AttributeDefinitions:
-
AttributeName: "Album"
AttributeType: "S"
-
AttributeName: "Artist"
AttributeType: "S"
KeySchema:
-
AttributeName: "Album"
KeyType: "HASH"
-
AttributeName: "Artist"
KeyType: "RANGE"
ProvisionedThroughput:
ReadCapacityUnits: "5"
WriteCapacityUnits: "5"
PointInTimeRecoverySpecification:
PointInTimeRecoveryEnabled: false
Tags:
- Key: Project
Value: !Ref ProjectName
- Key: Backup
Value: !Sub ${ProjectName}-${EnvironmentName}-DynamoDB-Backup
起動するインスタンスやサービスを記述するセクションです。
Properties
の中でインスタンス・サービスの設定を定義していきますが、
種類ごとに記載方法が異なるので都度AWS公式 - Template referenceを見るしかないでしょう。
出力(Outputs) ※今回は使いません。
本記事では使っていませんが、出力(Outputs)セクションもよく使います。
例えば本記事のテンプレートで作ったDynamoDBテーブルを他のテンプレートで使う場合、
出力セクションで関数の戻り値のようなものを定義します。
割と複雑なので別の機会に書くことにします。
値の参照 Ref関数・Sub関数・GetAtt関数
Ref・Sub関数関数を使うと、パラメータやリソースを変数のように参照できます。
AWS公式 - Ref関数
AWS公式 - Sub関数
パラメータ値の参照
パラメータをそのまま使う場合は、Ref関数を使います。
文字列結合する場合はSub関数を使います。
Tags:
- Key: Project
# パラメータをテーブルをそのまま使用
Value: !Ref ProjectName
- Key: Backup
# パラメータをテーブル名の一部として使用
Value: !Sub ${ProjectName}-${EnvironmentName}-DynamoDB-Backup
リソースの参照
リソースセクションで作ったリソースを他のリソースで使う場合は、大体Ref関数を使います。
テンプレート内でDynamoDBテーブルを作成し、そのテーブルに対してアラームを作る場合、
Ref関数で作ったDynamoDBテーブルを指定します。
DynamoDBAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmName: !Sub ${ProjectName}-${EnvironmentName}-DynamoDB-Write-Capacity-Alarm
Namespace: AWS/DynamoDB
ComparisonOperator: GreaterThanOrEqualToThreshold
Dimensions:
# テンプレート内で作成したテーブルの名前でメトリクスを絞り込む
- Name: TableName
Value: !Ref DynamoDBTable
EvaluationPeriods: 1
MetricName: ConsumedWriteCapacityUnits
Period: 300
Statistic: Average
Threshold: 1
Ref関数の注意事項
Ref関数は動きが微妙にわかりづらいです。
Ref関数の戻り値は型が固定ではないからです。
!Ref DynamoDBテーブル
ならテーブル名が返ります。
!Ref EC2インスタンス
ならインスタンスIDが返ります。
一部のリソースでは、リソースのコンテキストにおいて別の重要な意味を持つ識別子が返されます。たとえば、AWS::EC2::EIP リソースは IP アドレスを返し、AWS::EC2::Instance はインスタンス ID を返します。
For the resource with the logical ID myDynamoDBTable, Ref will return the DynamoDB table name.
hen you pass the logical ID of this resource to the intrinsic Ref function, Ref returns the instance ID. For example: i-1234567890abcdef0.
属性値の参照
作ったリソースから、インスタンスIDとかではなく特定の属性値を参照する場合は、GetAtt関数を使います。
AWS公式 - GetAtt関数
DynamoDBTagBasedBackupSelection:
Type: AWS::Backup::BackupSelection
Properties:
BackupPlanId: !Ref DynamoDBBackupPlan
BackupSelection:
SelectionName: !Sub ${ProjectName}-${EnvironmentName}-Backup-Selection
# リソースのARNを参照
IamRoleArn: !GetAtt DynamoDBBackupExecutionRole.Arn
ListOfTags:
- ConditionType: STRINGEQUALS
ConditionKey: Backup
ConditionValue: !Sub Backup-${ProjectName}
GetAtt関数で取れる属性の種類は、リソースの種類によって変わります。
例えば先述のDynamoDBテーブルですが、
!GetAtt DynamoDBTable.TableName
とかできそうですがこれはできません。
テーブル名はRef関数で取るのが正解です。
Ref関数で何が返り、GetAttで何が取れるかは各リソースのタイプの公式ページをみなくてはわかりません。
Ref関数・Sub関数・GetAtt関数の違いを理解する
まず、Ref関数・Sub関数・GetAtt関数の違いを覚えます。
次にRef関数はそのリソースのキーっぽいものを返す故にリソースから他のリソースが読めることと、
Sub関数は文字列結合に使えることを意識すると、
CloudFormationのテンプレートは読めるようになると思います。
まとめ
以上踏まえてテンプレートに繋がりの線を入れるとこのようになります。
本記事の内容が何かのきっかけになれば幸いです。
Discussion