「CloudFormationテンプレート見てもちんぷんかんぷんだ…」
前回の記事でCloudFormationに関するキーワードや大まかな利用の流れを説明をしましたが、いざテンプレート作成に取り掛かってみると様々なセクションがあり、どこが設定必要な項目でどんな設定ができるのかよく分からない…
こんにちは。クラウドソリューショングループのshimizuyです。
今回は「テンプレート編」と題して、CloudFormationのサンプルテンプレートを元に各セクションの概要やどんな設定ができるのかを中心に説明していきます。
CloudFormationの概要から確認したい方は前回の記事をご参照ください!
前回の記事:初学者のためのCloudFormation超入門(概要理解編)
目次
- 1. CloudFormationテンプレートとは?
- 2. テンプレートの構成要素は?
- 2-1. AWSTemplateFormatVersion(任意)
- 2-2. Description(任意)
- 2-3. Parameters(任意)
- 2-4. Metadata(任意)
- 2-5. Rules(任意)
- 2-6. Mappings(任意)
- 2-7. Conditions(任意)
- 2-8. Transform(任意)
- 2-9. Resources(必須)
- 2-10. Outputs(任意)
- 3. おわりに
1. CloudFormationテンプレートとは?
CloudFormation テンプレートは、AWS上に構築するインフラストラクチャを説明する JSON または YAML 言語でフォーマットされたテキストファイルです。要は設計書ですね。
テンプレートを作成・変更するにはVSCodeなどの任意のエディタツール、または CloudFormation Designer を使用する方法があります。
一応 CloudFormation Designer について簡単に説明すると、CloudFormation テンプレートを作成・表示・変更するためのグラフィックツールで、ドラッグ アンド ドロップ インターフェイスを使用してテンプレート リソースを図示し、統合された JSON および YAML エディターを使用して詳細を編集できます。興味のある方はこちらでテンプレート作成にチャレンジしてみてもいいかもしれません。
2. テンプレートの構成要素は?
さて、CloudFormationテンプレートはいくつかのセクションと呼ばれる要素で構成されています。それらのセクションを組み合わせることで、CloudFormationテンプレートはAWSのリソースを定義し、それを元にインフラストラクチャを自動的に作成・更新・削除するための設計図として機能しているわけですね。
/* yaml */
AWSTemplateFormatVersion: "2010-09-09"
Description:
String
Parameters:
set of parameters
Metadata:
template metadata
Rules:
set of rules
Mappings:
set of mappings
Conditions:
set of conditions
Transform:
set of transforms
Resources:
set of resources
Outputs:
set of outputs
CloudFormationテンプレートは上記の10のセクションで構成されています。
実際に必須となるセクションはResourcesのみで、他のセクションは必要に応じて記述していく形になります。
以下でそれぞれのセクションの用途や記述例を確認していきましょう!
2-1. AWSTemplateFormatVersion(任意)
AWSTemplateFormatVersion
セクションは、テンプレートのフォーマットバージョンを指定する任意の項目です。
最新のテンプレートの形式バージョンは2010-09-09
で、現時点で唯一の有効な値となっています。
また、値を指定しない場合、CloudFormationは最新のテンプレートの形式バージョンを使用します。
/* yaml */
AWSTemplateFormatVersion: 2010-09-09
2-2. Description(任意)
Description
セクションには、テンプレートに関する説明文を含めることができます。
注意点として、スタックの更新時にDescription
セクション単独での更新はできません。Description
セクションを更新する際は、リソースの追加、変更、または削除する変更を含める場合にのみ可能となっています。
また、記述する際は必ずAWSTemplateFormatVersion
セクションの後に記述する必要があります。
/* yaml */
Description: AWS CloudFormation Sample Template
2-3. Parameters(任意)
Parameters
セクションを設定すると、スタック作成時にテンプレートに対してカスタム値を受け渡すことができます。
/* yaml */
Parameters:
EnvId:
Description: "Environment ID"
ConstraintDescription: EnvId is only Strings
Type: String
Default: "dev"
KeyName:
Description: "EC2 key pair name"
Default: "ec2-key"
Type: String
InstanceType:
Description: "EC2 instance type"
Type: String
Default: "t2.micro"
AllowedValues:
- "t2.micro"
- "m5.large"
- "c5.xlarge"
ConstraintDescription: "Please specify a valid instance type."
上記のように記述することで、これらのパラメータはコンソールで以下のように表示されます。
ここで入力されたパラメータの値はResource
のプロパティで使用されます。
2-4. Metadata(任意)
Metadata
セクションは、テンプレート自体に関する情報やリソースに関する追加の情報を提供するために使用され、スタックのデプロイや更新時には無視され、テンプレートの実行には影響しないようになってます。
使い道としては大きく分けて以下の3つがあげられます。
AWS::CloudFormation::Init
AWS::CloudFormation::Interface
AWS::CloudFormation::Designer
個人的にはその中でもParameters
セクションのインプット項目の順序入れ替えたりジャンルごとにまとめる用途でAWS::CloudFormation::Interface
をよく使用しています。
/* yaml */
Metadata:
AWS::CloudFormation::Interface:
ParameterGroups:
-
Label:
default: "Setting for EC2"
Parameters:
- InstanceType
- KeyName
-
Label:
default: "Setting for Other"
Parameters:
- EnvId
先ほどParameters
セクションで例に出したコードに加えて、上記のMetadataを追記すると、以下のようにラベル付きでインプット項目がまとめられ、より見やすい状態になったのではないでしょうか?
上記ではAWS::CloudFormation::Interface
の使用例をあげましたが、他にも、EC2インスタンス内でのパッケージのインストールやファイルの作成、サービスの開始などのスクリプトを記述するAWS::CloudFormation::Init
やAWS CloudFormation デザイナーにおけるリソースのレイアウトに関する情報を記述する AWS::CloudFormation::Designer
があります。
2-5. Rules(任意)
Rules
セクションは、スタックの作成または更新時にテンプレートに渡されるパラメータまたはパラメータの組み合わせが特定の条件を満たしているか検証するために使用されます。
たとえば、あるパラメータが数値型である場合、その値が0以上であることを確認するルールを作成できます。また、2つのパラメータが関連している場合(パラメータAがtrueの場合にのみパラメータBが設定可能など)、その組み合わせを検証するルールが作成できます。
/* yaml */
Parameters:
Number:
Description: An input parameter of type number.
Type: Number
Rules:
NumberRule:
Assertions:
- Assert: !And [!Equals [!Ref MyNumber, 0], !Not [!If [!Equals [!Ref MyNumber, 0], true, false]]]
AssertDescription: Number must be greater than or equal to 0.
上記の例では、Parameters
セクションでNumberという名前の数値型パラメータを定義しています。
次に、NumberRuleという名前のルールを作成し、その中でNumberが0以上であることを確認しています。
もしMyNumberが0未満であれば、スタックの作成または更新は中止され、AssertDescriptionで指定したエラーメッセージが表示される仕様になっています!
2-6. Mappings(任意)
Mappings
セクションは、キーと名前付きの値が対応付けられたグループ化機能となります。
たとえば、特定の条件(リージョンや環境など)に基づいて異なる値を用いたい場合に使用されます。
/* yaml */
Mappings:
EnvMap:
dev:
InstanceType: t2.micro
prd:
InstanceType: m5.large
上記の例では、この例では、EnvMapというマッピングが作成され、それぞれの環境(ここではdevとprd)に対して、InstanceTypeというキーでインスタンスタイプが対応付けられています。
また、マッピングから値を取得するためには、以下のようにFn::FindInMap
関数を使用します。
/* yaml */
Parameters:
EnvId:
Type: String
Default: dev
AllowedValues:
- dev
- prd
Resources:
myEC2Instance:
Type: "AWS::EC2::Instance"
Properties:
ImageId: ami-0ff8a91507f77f867
InstanceType: !FindInMap [EnvMap, !Ref EnvId, InstanceType]
Mappings
セクションが上手く活用できれば、環境やリージョンごとにテンプレートを作成する必要がなくなり、テンプレートの再利用性と可読性が向上します!
2-7. Conditions(任意)
Conditions
セクションは、特定の条件下でどのようなアクション(リソースの作成、プロパティの設定など)を行うかを設定し、制御することができます。
たとえば、条件を作成し、リソースや出力に関連付けることで、条件が true の場合にのみ CloudFormation がリソースまたは出力を作成するようにできます。すごくざっくり言えばif文のような機能ですね!
(出力に関しての詳細はOutputs
セクションで説明します)
/* yaml */
Parameters:
EnvId:
Default: test
Type: String
AllowedValues:
- prd
- test
Conditions:
CreatePrdResources: !Equals [ !Ref EnvId, prd ]
Resources:
EC2Instance:
Type: "AWS::EC2::Instance"
Condition: CreatePrdResources
Properties:
# ...
この例では、EnvIdという入力パラメーターが存在します。本番環境用のスタックを作成する場合は prd を、テスト環境用のスタックを作成する場合は test をここに指定します。CreatePrdResources 条件は、EnvId パラメーターが prd と等しい場合に true として評価されます。このサンプルテンプレートでは、EC2Instance リソースを CreatePrdResources 条件に関連付けているため、EnvType パラメーターが prd と等しい場合にのみリソースが作成されるというわけです!
2-8. Transform(任意)
Transform
セクションでは、CloudFormationがテンプレートを処理するために使用するマクロを1つ以上指定することができます。と言われても少しイメージが付きづらいですよね…。
/* yaml */
Transform: 'AWS::Serverless-2016-10-31'
Resources:
MyLambdaFunction:
Type: 'AWS::Serverless::Function'
Properties:
Handler: index.handler
Runtime: nodejs14.x
CodeUri: s3://my-bucket/my-function-code.zip
こちらの例では、AWS::Serverless-2016-10-31
というマクロを使用しており、これはLambda関数やAPI GatewayなどのAWSリソースを簡単に記述するためのものになっています。
勘のいい方はお気づきかもしれませんが、すごーくざっくり言うとライブラリやフレームワークに近い機能ですね。
細かい使用感や効果は使用するマクロによっても変わってきますのでユースケースに合わせて公式を確認するようにしましょう!
参考:変換のリファレンス
2-9. Resources(必須)
Resources
セクションは、スタックに含めるAWSリソースを宣言するためのCloud Formation唯一の必須セクションです。これまでのセクションはResources
セクションをベースとして色々機能していきます。
基本的な構文は以下の通りです。
/* yaml */
Resources:
Logical ID:
Type: Resource type
Properties:
Set of properties
ここでいくつかポイントがあるのですが、
- Logical IDはテンプレート内で一意である必要があります。
- Resource typeは宣言しているリソースのタイプを識別します。例えば、AWS::EC2::InstanceはEC2インスタンスを宣言します。
- Propertiesはリソースに対して指定できる追加オプションです。例えば、EC2インスタンスごとに、そのインスタンスのAMI IDを指定する必要があります。
小ネタですが、CloudFormationテンプレートでEC2インスタンスのUserDataなんかも設定することができるので、思った以上に色々とカスタマイズできそうでちょっとワクワクしますね!
いよいよ次で最後のセクションです…!
2-10. Outputs(任意)
Outputs
セクションは、スタックの作成や更新が完了した後に、そのスタックに関する特定の情報を提供するためのものです。具体的には、以下の3つの主な用途があります:
1. 他のスタックにインポート: Outputs
セクションで定義した値は、他のCloudFormationスタックから参照できます。これにより、一つのスタックが別のスタックと情報を共有することが可能になります。例えば、あるスタックで作成したS3バケットの名前を出力として定義し、その名前を別のスタックで参照することができるようになります。
2. スタック呼び出しの応答として値を返す: スタック作成や更新のAPI呼び出しに対する応答として、Outputs
セクションで定義した値を返すことができます。これにより、API呼び出しを行ったユーザーやアプリケーションがスタック作成や更新の結果を得ることが可能になります。
3. CloudFormationコンソールで表示: CloudFormationコンソールで、各スタックのOutputs
セクションで定義した値を表示することができます。
/* yaml */
Resources:
MyBucket:
Type: 'AWS::S3::Bucket'
Outputs:
BucketName:
Description: 'The name of the newly created S3 bucket'
Value: !Ref MyBucket
Export:
Name: MyExportedBucketName
上記のテンプレートでは、Resources
セクションで作成したS3バケット(MyBucket)をOutputs
セクションで出力していて、出力値は!Ref MyBucket
という組み込み関数を使用してバケット名を取得しています。最後に、この出力値をMyExportedBucketNameという名前でエクスポートしていますね。
これによって、他のスタックはFn::ImportValue MyExportedBucketName
という組み込み関数を使用してこのバケット名(MyBucket)を参照することができるわけですね!
3. おわりに
この記事ではCloudFormationテンプレートの各セクションの概要をサンプルコードを用いて説明をしてきました。
各セクションがどんな時に利用されるのか?どのように記述されるのか?など少しでも分かりやすく説明できていれば幸いです。
今後の記事では、これまでの説明を元に実際のテンプレート作成をしつつ、CloudFormationテンプレートを運用していく上でのコツなどを説明していければと思いますので、ぜひ次回以降もご覧ください!