CloudFormation Templateを書いていると、
「この設定は書かなくてもいいの?」
という場面が出てきます。
例えば、S3バケットを作るだけなら、
Resources:
SampleBucket:
Type: AWS::S3::Bucket
だけでも作成できます。
では、Templateに書いていない設定はどうなるのでしょうか?
結論から言うと、省略した項目の扱いは、その項目によって異なります。
大きく分けると、以下の4パターンがあります。
① CloudFormation側でデフォルト値が設定される
② AWSリソース側のデフォルト動作になる
③ 任意項目なので設定されない
④ 必須項目なのでエラーになる
この違いを理解しておくことが重要です。
1. Templateで省略したからといって「空」になるわけではない
例えば、以下のTemplateを考えてみます。
Resources:
SampleBucket:
Type: AWS::S3::Bucket
このTemplateには、S3バケットの名前を指定するBucketNameがありません。
だからといって、
BucketName = 空
になるわけではありません。
CloudFormationは、S3バケット名を明示的に指定しなかった場合、物理リソース名を自動生成します。
そのため、実際には、
SampleBucket
↓
CloudFormation
↓
ランダムな名前を持つS3 Bucket
という動きになります。
つまり、
Templateに書いていない = 値が空
ではありません。
2. AWSリソース側のデフォルト値が使われる場合
CloudFormationのResourceには、さまざまなPropertiesがあります。
例えばEC2の場合、
Resources:
SampleInstance:
Type: AWS::EC2::Instance
Properties:
ImageId: ami-xxxxxxxx
としたとします。
InstanceTypeを指定していません。
この場合、
InstanceType:
が空になるわけではありません。
CloudFormationのResource仕様でデフォルト値が定義されている場合、そのデフォルト値が使用されます。
ただし、ここで注意したいのが、
「デフォルト値が存在するかどうかは、ResourceのPropertyによって異なる」
ということです。
そのため、
「省略したらいつもこの値になる」
と暗記するのではなく、使用するResourceのCloudFormationドキュメントを確認することが重要です。
3. Optionalな項目は設定されない
CloudFormationのResourceには、必須ではないPropertiesもたくさんあります。
例えばS3 Bucketには、さまざまな設定があります。
Resources:
SampleBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: sample-example
VersioningConfiguration:
Status: Enabled
この場合、
VersioningConfiguration:
を指定しなければ、バージョニングを有効化する設定そのものをTemplateから指定していないことになります。
つまり、
Template
↓
指定した設定だけをCloudFormationへ伝える
↓
指定していないOptionalな設定は
そのResourceの仕様に従う
というイメージです。
4. 必須項目を省略するとエラーになる
一方で、必須の項目を省略するとStackの作成に失敗します。
例えば、
Resources:
SampleInstance:
Type: AWS::EC2::Instance
のように、EC2 Instanceを作成するために必要な情報を何も指定しない場合、必要な情報が不足しているため作成できません。
Resourceによっては、必須のPropertiesがあります。
そのため、
「ResourcesにTypeを書けば、あとは全部自動で設定される」
というわけではありません。
Parametersを省略した場合
ここからは、Templateの各セクションごとに見てみます。
まずParametersです。
例えば、
Parameters:
Environment:
Type: String
Default: dev
とした場合、Stack作成時にEnvironmentを指定しなければ、
Environment = dev
が使われます。
これはDefaultを指定しているからです。
Defaultを指定しない場合
では、次のようにしたらどうでしょうか。
Parameters:
Environment:
Type: String
この場合、Defaultがありません。
そのため、Stack作成時に値を指定する必要があります。
Environment
↓
Stack作成時に入力
値を指定しないとStackの作成時に問題になります。
つまりParametersでは、
Defaultあり
↓
指定しなければDefault値
Defaultなし
↓
Stack作成時に値を指定
と考えると分かりやすいです。
Resourcesを省略した場合
CloudFormation Templateで最も重要なのがResourcesですが、Resourcesそのものは実質的に中心となるセクションです。
例えば、
Description: Sample Template
だけのTemplateでは、作成するAWSリソースがありません。
CloudFormationでは、Stack自体は作成できても、作成対象となるResourceがなければ意味のあるインフラは構築されません。
基本的には、
Resources:
...
を中心にTemplateを考えます。
ResourceのPropertiesを省略した場合
ここが一番重要です。
例えば、
Resources:
SampleBucket:
Type: AWS::S3::Bucket
のようにPropertiesそのものを省略できます。
これは、
「S3 BucketのPropertiesが全部空になる」
という意味ではありません。
CloudFormationは、指定されたResource Typeに基づいてリソースを作成します。
Propertiesを指定しなければ、指定していない項目については、そのResourceの仕様に従ったデフォルト動作になります。
例えば、
Resources:
SampleBucket:
Type: AWS::S3::Bucket
と、
Resources:
SampleBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: sample-example
では、どちらもS3 Bucketを作成します。
違いは、
1つ目
↓
BucketNameをCloudFormationに任せる
2つ目
↓
BucketNameを自分で指定する
という点です。
Outputsを省略した場合
Outputsも必須ではありません。
例えば、
Resources:
SampleBucket:
Type: AWS::S3::Bucket
だけでもStackは作成できます。
Outputsがないからといって、作成したS3 Bucketが削除されたり、利用できなくなったりするわけではありません。
単純に、
StackのOutputsとして外部に値を表示しない
というだけです。
「省略」と「空の値」は違う
ここは特に注意したいポイントです。
例えば、
Properties:
BucketName:
と書いた場合と、
Properties:
そのものを省略した場合では、同じ意味になるとは限りません。
さらに、
BucketName: ""
のように空文字を明示的に指定する場合もあります。
これらは、
① プロパティそのものを指定しない
② プロパティは指定するが値を空にする
③ プロパティに具体的な値を指定する
という異なる状態です。
例えば、
# ① 省略
Resources:
SampleBucket:
Type: AWS::S3::Bucket
# ② 空の値
Resources:
SampleBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: ""
# ③ 値を指定
Resources:
SampleBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: sample-example
この3つは同じ意味になるとは限りません。
特に②のような書き方は、Resourceによってはエラーになることもあります。
そのため、
「値を設定しないなら、とりあえず空文字にする」
という考え方は避けたほうが安全です。
不要な設定は、基本的には記述しないという考え方が分かりやすいです。
CloudFormationで省略した値を考えるときの順番
Templateを書くときに、
「このPropertyを書かなくても大丈夫かな?」
と思ったら、以下の順番で確認するとよいです。
① このPropertyは必須?
↓
Yes → 値を指定する
↓
No
↓
② デフォルト値がある?
↓
Yes → デフォルト値が使われる
↓
No
↓
③ 省略した場合のResourceの仕様を確認
つまり、
「省略したらどうなるか」を自分で推測しない
ことが重要です。
CloudFormationではResource Typeごとに仕様が決まっているため、AWS公式ドキュメントで確認します。
Templateをシンプルにするために省略する
では、なぜわざわざ設定を省略するのでしょうか?
理由の一つは、Templateをシンプルにできるからです。
例えば、
Resources:
SampleBucket:
Type: AWS::S3::Bucket
と、
Resources:
SampleBucket:
Type: AWS::S3::Bucket
Properties:
# ここに大量の設定を書く
では、前者のほうが何をしているのか分かりやすい場合があります。
AWSのデフォルト動作で問題ないのであれば、無理にすべての設定を書く必要はありません。
ただし「明示的に書く」ことにも意味がある
一方で、本番環境などでは、
「AWSのデフォルト値に任せるのではなく、設定を明示したい」
という場合もあります。
例えば、
Resources:
SampleBucket:
Type: AWS::S3::Bucket
Properties:
VersioningConfiguration:
Status: Enabled
のように、
「このS3バケットではバージョニングを有効にする」
ことをTemplate上で明示できます。
これには、
- Templateを見れば設定が分かる
- AWS側のデフォルト動作に依存しにくい
- コードレビューしやすい
- 環境構成を再現しやすい
というメリットがあります。
「全部書く」と「全部省略する」のどちらが正解?
どちらか一方が正解というわけではありません。
考え方としては、
AWSのデフォルト動作で問題ない
↓
省略する
環境として明確に指定したい
↓
明示する
と考えるとよいでしょう。
特に、
セキュリティに関係する設定
本番環境で重要な設定
チームとして明確にしておきたい設定
などは、デフォルトに任せずTemplate上で明示することを検討します。
まとめ
CloudFormation Templateでは、設定を省略した場合でも、必ずしも「空」になるわけではありません。
省略した設定は、大きく分けると、
Templateで省略
↓
┌──────────────────────┐
│ 必須項目? │
└──────────┬───────────┘
│
Yes │ No
│
↓
エラー Resourceの仕様へ
↓
┌──────────┴──────────┐
↓ ↓
デフォルト値あり デフォルトなし
↓ ↓
デフォルト値を使用 指定されない
というように考えられます。
そして、もう一つ重要なのが、
「省略する」ことと「空の値を設定する」ことは違う
ということです。
そのため、Templateを書くときは、
この設定は必要?
↓
必須なら書く
↓
任意なら
↓
デフォルトで問題ない?
↓
Yes → 省略
No → 明示的に設定
という考え方をすると整理しやすくなります。
CloudFormationを使い始めたばかりのうちは、「全部の設定を書く」のではなく、「何をAWSのデフォルトに任せ、何をTemplateで明示するのか」を考えることが重要です。

コメント