AWS::Include Transformを使ってCloudFormationのテンプレートをキレイに整理しよう!!
CX事業本部@大阪の岩田です。
CloudFormationのAWS:Include
を使うと、CloudFormationのテンプレート内に別テンプレートの中身を読み込むことができます。私も以下の記事を参考にSwaggerの定義を分離するのに愛用しています。
CloudFromationのAWS::Includeを利用してAWS SAMからインラインSwaggerを分離して管理する
このAWS:Include、恥ずかしながらリソースのプロパティを定義する際にしか利用できないと思いこんでいたのですが、実はもっと色々な場所で利用できることに気付きました。ご存知の人も多いかもしれませんが、改めてご紹介します。
AWS:Includeとは??
S3上に置かれたファイルの中身をCloudFormationのテンプレート内に読み込むためのマクロです。公式ドキュメントに記載されているように、プログラミング言語における include
、copy
、import
といった構文をイメージすると分かり良いと思います。前述の中山のブログが執筆された時点ではAWS CLIによるpackageが未対応だったのですが、今は普通に対応しているので、S3にアップロードする手間をあまり意識することなく利用できます。
AWS:Includeの利用例
実際のテンプレートを見て頂くのが早いと思います。以下のように
- テンプレートの最上位
- Resourcesの直下
- リソース定義の直下
- リソースのProperties指定
色んな場所にAWS:Includeを置くことができます
AWSTemplateFormatVersion: '2010-09-09' # 最上位にも置けるし Fn::Transform: Name: AWS::Include Parameters: Location: description.yml Resources: # Resources直下にも置けるし Fn::Transform: Name: AWS::Include Parameters: Location: dynamodb.yml TestBucket1: Type: AWS::S3::Bucket # 各リソース定義の直下もOK Fn::Transform: Name: AWS::Include Parameters: Location: del_policy.yml TestBucket2: Type: AWS::S3::Bucket Properties: # Propertiesの指定にも使えるし Fn::Transform: Name: AWS::Include Parameters: Location: tags.yml TestBucket3: Type: AWS::S3::Bucket Fn::Transform: Name: AWS::Include Parameters: Location: del_policy.yml Properties: WebsiteConfiguration: IndexDocument: index.html # 1つのリソースに複数回Includeを使ったり # PropertiesをマージしたりしてもOK Fn::Transform: Name: AWS::Include Parameters: Location: tags.yml
Includeしている各YAMLファイルは以下の通りです
Description: 'Include Test'
TestTable: Type: "AWS::DynamoDB::Table" Properties: AttributeDefinitions: - AttributeName: "id" AttributeType: "N" KeySchema: - AttributeName: "id" KeyType: "HASH" BillingMode: PAY_PER_REQUEST
DeletionPolicy: Delete
Tags: - Key: SomeKey Value: SomeVal
dynamodb.yml
ではリソースの定義を丸々記述しています。このようにDynamoDB用のテンプレート、Lambda用のテンプレート...といった形でサービス単位である程度テンプレートを分けておくと保守性を高く保ちやすくなります(あまり分けすぎでも逆にややこしくなるのでケースバイケースですが)。また、tags.yml
のように各リソースで共通設定するプロパティだけ切り出せば、冗長な記述を削減することも可能です。
Packageしてみる
先程のテンプレートに対してcloudformationのpackageコマンドを実行してみます。これでinclude対象に指定された各ファイルがS3にアップロードされ、デプロイ用のテンプレートファイルが出力されます。
$ aws cloudformation package --template-file include_test.yml --s3-bucket <適当なS3バケット> --output-template-file output.yml
出力されたファイルはこちらです。
AWSTemplateFormatVersion: '2010-09-09' Fn::Transform: Name: AWS::Include Parameters: Location: s3://<package時に指定したS3バケット>/b7a2955ca33cb3908c36b49284fd487a Resources: Fn::Transform: Name: AWS::Include Parameters: Location: s3://<package時に指定したS3バケット>/44f286194fbdc0705011eba5aa2e8c47 TestBucket1: Type: AWS::S3::Bucket Fn::Transform: Name: AWS::Include Parameters: Location: s3://<package時に指定したS3バケット>/3b8fa7b7a78df4b066b7b7a3851c4802 TestBucket2: Type: AWS::S3::Bucket Properties: Fn::Transform: Name: AWS::Include Parameters: Location: s3://<package時に指定したS3バケット>/4c8b60a22160fe0bb6a822088ccddb71 TestBucket3: Type: AWS::S3::Bucket Fn::Transform: Name: AWS::Include Parameters: Location: s3://<package時に指定したS3バケット>/3b8fa7b7a78df4b066b7b7a3851c4802 Properties: WebsiteConfiguration: IndexDocument: index.html Fn::Transform: Name: AWS::Include Parameters: Location: s3://<package時に指定したS3バケット>/4c8b60a22160fe0bb6a822088ccddb71
デプロイしてみる
packageしたテンプレートを使ってスタックを作成してみましょう
$ aws cloudformation deploy --template-file output.yml --stack-name <適当なスタック名> --capabilities CAPABILITY_IAM
無事にデプロイできました!
AWS:Includeで各テンプレートをIncludeした最終的なテンプレートが「処理されたテンプレートの表示」から確認できます。JSON形式で出力されているので、YAMLに変換すると以下のようになります。
AWSTemplateFormatVersion: '2010-09-09' Description: Include Test Resources: TestBucket2: Type: AWS::S3::Bucket Properties: Tags: - Key: SomeKey Value: SomeVal TestBucket3: Type: AWS::S3::Bucket Properties: WebsiteConfiguration: IndexDocument: index.html Tags: - Key: SomeKey Value: SomeVal DeletionPolicy: Delete TestBucket1: Type: AWS::S3::Bucket DeletionPolicy: Delete TestTable: Type: AWS::DynamoDB::Table Properties: AttributeDefinitions: - AttributeName: id AttributeType: N KeySchema: - AttributeName: id KeyType: HASH BillingMode: PAY_PER_REQUEST
Includeしたファイルの中身がマージされて、1つのテンプレートに統合されていることが分かります。
まとめ
CloudFormationのAWS:Include
は色んな場所で利用できますというご紹介でした。ある程度インフラの規模が大きくなってくるとCloudFormationのテンプレートも自然と肥大化し、保守性が低くなってしまいます。AWS:Include
をうまく活用することで、読みやすい範囲でテンプレートを分割したり、何度も繰り返す共通プロパティを一元管理するといったことが可能になるので、良ければ利用を検討してみて下さい。