前回は、CloudFormationを実際に動かして、YAMLでAWSリソースを作成してみました。
今回は、もう少しCloudFormation Templateの中身について詳しく見ていきます。
CloudFormation Templateには、いくつかの「セクション」があります。
例えば、以下のようなテンプレートです。
AWSTemplateFormatVersion: '2010-09-09'
Description: Sample CloudFormation Template
Parameters:
Environment:
Type: String
Default: dev
Resources:
SampleBucket:
Type: AWS::S3::Bucket
Outputs:
BucketName:
Value: !Ref SampleBucket
初めて見ると、
AWSTemplateFormatVersionって何?
Parametersには何を書くの?
ResourcesにはAWSのリソースを全部書くの?
Outputsって何のためにあるの?
となると思います。
そこで今回は、CloudFormation Templateの各セクションについて、
- 何のために存在するのか
- どのような値を設定できるのか
- 実際にどう考えて設定するのか
という順番で見ていきます。
CloudFormation Templateの全体像
まずはCloudFormation Templateの全体像を見てみましょう。
CloudFormation Templateには、主に以下のセクションがあります。
AWSTemplateFormatVersion: '2010-09-09'
Description: ...
Metadata:
...
Parameters:
...
Mappings:
...
Conditions:
...
Transform:
...
Resources:
...
Outputs:
...
ただし、すべてのセクションを書く必要があるわけではありません。
例えば、最小限のCloudFormation Templateなら、
Resources:
SampleBucket:
Type: AWS::S3::Bucket
だけでも動作します。
つまり、最初からすべてのセクションを覚える必要はありません。
まずは、
Parameters
↓
Resources
↓
Outputs
という3つを理解するところから始めると分かりやすいです。
① AWSTemplateFormatVersion
最初に登場するのが、
AWSTemplateFormatVersion: '2010-09-09'
です。
これはCloudFormation Templateの形式を指定するための項目です。
現在利用されている値は、
AWSTemplateFormatVersion: '2010-09-09'
です。
ここで少し不思議なのが、
「2010年って古くない?」
という点です。
この値は「2010年に作成されたTemplate」という意味ではありません。
CloudFormationのテンプレート形式を示すバージョン値です。
また、このセクションは必須ではありません。
そのため、
Resources:
SampleBucket:
Type: AWS::S3::Bucket
のようにAWSTemplateFormatVersionを省略してもTemplateを作成できます。
どう考える?
基本的には、
CloudFormation Templateを書くなら、とりあえず
'2010-09-09'を指定する
くらいで問題ありません。
値を自分で設計するものではないので、ここで悩む必要はありません。
② Description
次に、
Description: Sample CloudFormation Template
です。
これはTemplateの説明を書くためのセクションです。
例えば、
Description: Development environment for sample application
と書けば、
「サンプルアプリケーションの開発環境」
という説明になります。
日本語も記述できますが、チーム開発では英語で統一するケースもあります。
Descriptionには何を書く?
ここは、
「このTemplateは何を作るためのものなのか?」
を考えます。
例えば、
Description: Web application infrastructure
ならWebアプリケーション用のインフラ、
Description: Production environment
なら本番環境用、
Description: S3 bucket for application logs
ならアプリケーションログ保存用のS3バケット、
ということが分かります。
DescriptionはAWSリソースの設定値というより、Templateの目的を人間に伝えるための情報と考えると分かりやすいです。
③ Metadata
Metadataというセクションもあります。
Metadata:
...
Metadataは、Templateに関する追加情報を記述するために使用します。
例えば、CloudFormationのパラメータ入力画面をカスタマイズするために利用できます。
代表的な用途として、
Metadata:
AWS::CloudFormation::Interface:
ParameterGroups:
- Label:
default: Environment Settings
Parameters:
- Environment
のような設定があります。
これによってCloudFormationのパラメータ入力画面を整理できます。
ただし、最初の段階ではMetadataを無理に覚える必要はありません。
どう考える?
Metadataは、
「CloudFormationがAWSリソースを作るための設定」というより、「Templateに付随する補足情報」
と考えるとよいでしょう。
④ Parameters
ここから重要になってきます。
Parameters:
Environment:
Type: String
Default: dev
Parametersは、Stackを作成するときに外部から値を渡すための仕組みです。
例えば、
Parameters:
Environment:
Type: String
Default: dev
とすると、Stack作成時にEnvironmentという値を指定できます。
例えば、
Environment = dev
や、
Environment = prod
といった値です。
Parametersには何を入れる?
ここが重要です。
Parametersを考えるときは、
「Templateの中で、環境によって変わる値は何か?」
と考えます。
例えば、
開発環境
↓
dev
本番環境
↓
prod
で値が変わるのであれば、
Parameters:
Environment:
Type: String
Default: dev
のようにできます。
Parametersの代表的なType
Parametersでは、入力値の型を指定できます。
例えば、
Parameters:
Environment:
Type: String
なら文字列です。
他にも、
Type: Number
なら数値、
Type: List<AWS::EC2::AvailabilityZone::Name>
ならAvailability Zoneのリスト、
などがあります。
AWSリソースを選択させるためのAWS固有のParameter Typeもあります。
例えば、
Type: AWS::EC2::KeyPair::KeyName
とすれば、EC2のKey Pairを選択するParameterにできます。
Parametersを考えるときのポイント
Parametersを設計するときは、
Templateを書く
↓
環境によって値が変わる?
↓
YES
↓
Parameterにする
と考えると分かりやすいです。
例えば、EC2のインスタンスタイプが環境によって、
dev → t3.micro
prod → t3.large
と変わるなら、Parameterにする方法があります。
Parameters:
InstanceType:
Type: String
Default: t3.micro
そしてResource側で、
Resources:
SampleInstance:
Type: AWS::EC2::Instance
Properties:
InstanceType: !Ref InstanceType
とします。
こうすると、
Templateそのものを変更せず、Stack作成時の値だけ変更する
という使い方ができます。
⑤ Mappings
Mappingsは、固定的な対応表をTemplate内に定義するためのセクションです。
例えば、
Mappings:
EnvironmentMap:
dev:
InstanceType: t3.micro
prod:
InstanceType: t3.large
とすると、
dev
└─ t3.micro
prod
└─ t3.large
という対応関係を作れます。
Parametersとの違い
ここは初心者が混乱しやすいポイントです。
ざっくり分けると、
Parameters
Stack作成時にユーザーから値を受け取る
Mappings
Templateの中にあらかじめ対応表を持っておく
という違いです。
例えば、
Parameters:
Environment:
Type: String
で、
dev
prod
をユーザーから受け取ります。
そして、
Mappings:
EnvironmentMap:
dev:
InstanceType: t3.micro
prod:
InstanceType: t3.large
で、
dev → t3.micro
prod → t3.large
という対応関係を定義できます。
⑥ Conditions
Conditionsは、条件によってResourceや設定を切り替えるためのセクションです。
例えば、
本番環境の場合だけCloudWatch Alarmを作成したい
というケースがあります。
その場合、
Conditions:
IsProduction: !Equals
- !Ref Environment
- prod
のような条件を作れます。
そしてResource側で、
Resources:
ProductionAlarm:
Type: AWS::CloudWatch::Alarm
Condition: IsProduction
と指定します。
これによって、
Environment = dev
↓
Alarmを作らない
Environment = prod
↓
Alarmを作る
という制御ができます。
Conditionsを考えるときのポイント
Conditionsは、
「環境や設定によって、Resourceを作る・作らないを切り替えたいか?」
と考えると分かりやすいです。
例えば、
開発環境
→ 監視不要
本番環境
→ 監視が必要
ならConditionsを使う候補になります。
⑦ Transform
Transformは、Templateを処理するための仕組みです。
例えば、AWS SAMを利用する場合、
Transform: AWS::Serverless-2016-10-31
のように指定します。
Transformを利用すると、CloudFormation Templateを拡張したり、特定の構文を変換したりできます。
ただし、通常のCloudFormationを学ぶ段階では、まず後回しにして問題ありません。
どう考える?
Transformは、
「CloudFormation Templateをそのまま使うのではなく、追加の変換処理を入れたい」
ときに登場するもの、と考えておけば十分です。
⑧ Resources
そして、CloudFormationで最も重要なのがResourcesです。
Resources:
SampleBucket:
Type: AWS::S3::Bucket
ここに、実際にAWS上へ作成するリソースを定義します。
例えばS3なら、
Resources:
SampleBucket:
Type: AWS::S3::Bucket
EC2なら、
Resources:
SampleInstance:
Type: AWS::EC2::Instance
Lambdaなら、
Resources:
SampleFunction:
Type: AWS::Lambda::Function
という形になります。
Resourcesを考えるときのポイント
ここでは、
「このシステムを動かすために、AWS上に何が必要なのか?」
と考えます。
例えばWebアプリケーションなら、
Webアプリケーション
↓
必要なAWSリソースを考える
VPC
├─ Subnet
├─ Route Table
└─ Internet Gateway
ALB
EC2
RDS
というように、必要なAWSリソースを洗い出します。
その後、
Resources:
VPC:
Type: AWS::EC2::VPC
WebServer:
Type: AWS::EC2::Instance
Database:
Type: AWS::RDS::DBInstance
のようにTemplateへ落とし込んでいきます。
つまり、Resourcesを書く前に、
「AWS上にどんな構成を作りたいのか」
を考えることが重要です。
ResourceのProperties
ResourceにはPropertiesという設定があります。
例えばS3バケットなら、
Resources:
SampleBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: sample-example-bucket
とできます。
ここで、
Type: AWS::S3::Bucket
が、
何を作るのか
を表しています。
一方、
Properties:
BucketName: sample-example-bucket
は、
そのリソースをどのような設定で作るのか
を表します。
Propertiesには何を入れる?
ここで重要なのは、
ResourceによってPropertiesに指定できる値が違う
ということです。
例えばS3バケットとEC2インスタンスでは、必要な設定が当然異なります。
S3なら、
Properties:
BucketName: ...
EC2なら、
Properties:
ImageId: ...
InstanceType: ...
SubnetId: ...
というように、それぞれ設定項目が異なります。
そのため、
「Propertiesには何を書けばいいの?」
となった場合は、CloudFormationの各Resource Typeのドキュメントを確認します。
⑨ Outputs
最後にOutputsです。
Outputs:
BucketName:
Value: !Ref SampleBucket
Outputsは、Stack作成後に外部へ出したい情報を定義する場所です。
例えば、
作成したS3バケットの名前を確認したい
という場合、
Outputs:
BucketName:
Value: !Ref SampleBucket
とできます。
Stackを作成すると、Outputsから、
BucketName
↓
作成されたS3バケット名
を確認できます。
Outputsを考えるときのポイント
Outputsでは、
「このStackを作ったあと、外部から知りたい情報は何か?」
と考えます。
例えば、
作成したVPCのID
作成したSubnetのID
作成したALBのDNS名
作成したS3バケット名
作成したLambdaのARN
などです。
特に、別のStackや外部システムから利用する値を出したい場合に便利です。
実際にはどういう順番でTemplateを考える?
ここまで各セクションを説明しました。
では、実際にCloudFormation Templateを書くとき、どのような順番で考えればよいのでしょうか。
個人的には、以下の順番で考えると分かりやすいです。
① 何を作りたい?
↓
② 必要なAWSリソースは?
↓
③ Resourceを定義
↓
④ 環境によって変わる値は?
↓
⑤ Parametersを定義
↓
⑥ 条件によって変える必要は?
↓
⑦ Conditions / Mappingsを検討
↓
⑧ 作成後に必要な情報は?
↓
⑨ Outputsを定義
最初から、
「Parametersには何を書こう?」
と考える必要はありません。
まず「何を作りたいか」を考える
例えば、
EC2を1台作りたい
とします。
まずは必要なものを考えます。
EC2を作りたい
↓
AMIが必要
↓
Instance Typeが必要
↓
Subnetが必要
↓
Security Groupが必要
すると、必要なResourceが見えてきます。
EC2
├─ Security Group
└─ Subnet
既存のVPCやSubnetを使うのであれば、それらをCloudFormationで作る必要はありません。
逆に、新しくネットワーク環境も作るのであれば、
VPC
├─ Subnet
├─ Route Table
└─ Internet Gateway
↓
EC2
のようにResourceが増えます。
次に「何が変わるか」を考える
Resourceが決まったら、
「この値は環境によって変わる?」
と考えます。
例えば、
dev
InstanceType = t3.micro
prod
InstanceType = t3.large
なら、InstanceTypeをParameterにする候補になります。
Parameters:
InstanceType:
Type: String
Default: t3.micro
一方、
どの環境でも必ず同じ値
なのであれば、必ずしもParameterにする必要はありません。
この考え方が重要です。
何でもParameterにすればいいわけではありません。
最後に「何を知りたいか」を考える
Resourceを作ったあと、
「作成されたResourceの何を知りたい?」
を考えます。
例えばALBを作ったのであれば、
ALBのDNS名
を知りたいかもしれません。
S3なら、
バケット名
EC2なら、
Instance ID
などです。
必要であればOutputsに追加します。
実践:S3バケットを作るTemplate
ここまでの考え方を使って、S3バケットを作ってみます。
まず、
S3バケットを作りたい
と考えます。
必要なResourceは、
S3 Bucket
です。
次に、
バケット名を環境によって変更したい
とします。
そこでParameterを定義します。
Parameters:
Environment:
Type: String
Default: dev
そしてResourceを定義します。
Resources:
SampleBucket:
Type: AWS::S3::Bucket
最後に、
作成されたバケット名を確認したい
のでOutputsを追加します。
Outputs:
BucketName:
Value: !Ref SampleBucket
最終的には、
AWSTemplateFormatVersion: '2010-09-09'
Description: Sample S3 Bucket
Parameters:
Environment:
Type: String
Default: dev
Resources:
SampleBucket:
Type: AWS::S3::Bucket
Outputs:
BucketName:
Value: !Ref SampleBucket
となります。
ただし、この例ではEnvironmentをParameterとして定義しているものの、Resource側ではまだ利用していません。
つまり、
Environment
↓
Parameterとして受け取る
↓
Resourceで利用していない
という状態です。
このようなParameterは意味がないので、実際のTemplateでは、
「本当にParameterとして外から値を受け取る必要があるのか?」
を考える必要があります。
Templateを設計するときの考え方
ここまでを整理すると、CloudFormation Templateは以下のように考えると分かりやすいです。
┌─────────────────────────┐
│ 何を作りたい? │
└────────────┬────────────┘
↓
┌─────────────────────────┐
│ Resources │
│ AWSリソースを定義する │
└────────────┬────────────┘
↓
┌─────────────────────────┐
│ 環境によって変わる? │
└────────────┬────────────┘
↓
Yes ───────→ Parameters
│
↓
┌─────────────────────────┐
│ 条件によって変わる? │
└────────────┬────────────┘
↓
Yes ───────→ Conditions
│
↓
┌─────────────────────────┐
│ 固定の対応表が必要? │
└────────────┬────────────┘
↓
Yes ───────→ Mappings
│
↓
┌─────────────────────────┐
│ 作成後に知りたい値は? │
└────────────┬────────────┘
↓
Outputs
このように考えると、CloudFormationの各セクションを暗記する必要がなくなります。
すべてのセクションを使う必要はない
最後に、もう一つ覚えておきたいことがあります。
CloudFormation Templateを作るときに、
AWSTemplateFormatVersion:
Description:
Metadata:
Parameters:
Mappings:
Conditions:
Transform:
Resources:
Outputs:
を全部書く必要はありません。
例えば、
Resources:
SampleBucket:
Type: AWS::S3::Bucket
だけでも立派なCloudFormation Templateです。
最初は、
Resources
を理解する。
↓
Templateの中で変更したい値が出てきたら、
Parameters
を使う。
↓
条件分岐が必要になったら、
Conditions
を使う。
↓
固定の対応表が必要なら、
Mappings
を使う。
↓
作成したResourceの情報を外へ渡したければ、
Outputs
を使う。
というように、必要になったタイミングでセクションを追加していくのがおすすめです。
まとめ
CloudFormation Templateは、単なる「AWSリソース一覧」ではありません。
Templateの中には、
Templateの説明
↓
入力値
↓
条件や対応表
↓
作成するAWSリソース
↓
作成後に外へ渡す情報
という情報を定義できます。
特に最初は、以下の3つを押さえておけば十分です。
| セクション | 役割 | 考えること |
|---|---|---|
| Parameters | 外部から値を受け取る | 環境によって変わる値は? |
| Resources | AWSリソースを作る | 何を作りたい? |
| Outputs | 作成した値を外へ出す | 作成後に何を知りたい? |
そして、Templateを書くときは、
「どんなAWS環境を作りたいのか?」
から考えることが重要です。
いきなりYAMLを書き始めるのではなく、
作りたいシステム
↓
必要なAWSリソース
↓
環境によって変わる値
↓
条件分岐
↓
外部へ渡したい値
という順番で考えていくと、CloudFormation Templateを設計しやすくなります。


コメント