CloudFormation 便利な使い方

CloudFormationによるIaCを始める方の助けになれば
2021.09.16

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは。
ご機嫌いかがでしょうか。
"No human labor is no human error" が大好きな ネクストモード株式会社 の吉井です。

CloudFormation で自身の管理する AWS を構成管理したい、IaC デビューしたいという要望は年々多くなってきています。
すでに使いこなしている方もいるとは思いますが、これから IaC デビューしたい方向けに私が普段から CloudFormation を便利に使うために気をつけていることを紹介します。

命名規則

まずテンプレートファイル名やスタック名、リソース名、Name タグ名などの命名規則を策定しておきましょう。
「AWSならこれ」というものはありません。自社メンバーと相談して「付けやすく判別しやすい」命名しておくと吉です。

弊社で使っているAWSリソースの命名規則を紹介します

テンプレートファイルはリソースのライフサイクル単位にする

CloudFormation は実行単位が基本的にファイルごとです。
1つのテンプレートファイルを実行すると書かれているリソースが作成/更新/削除されます。
リソースのライフサイクルを考慮してテンプレートファイルを作成します。

ライフサイクルは、リソースの作成~変更~削除までの一連の流れです。
共通のライフサイクルを持ったリソースをグループ化してテンプレートファイルに記載します。

VPC を作るとします。
ほとんどのケースでは、VPC を作るとサブネットやルートテーブル、Internet Gateway/NAT Gateway といったリソースを同時に作ります。
削除も同じタイミングになることが多いと思います。 VPC を削除して NAT Gateway だけ残すケースはそう多くないと思います。
これらは「ライフサイクルが共通化している」と言えます。

EC2 はどうでしょうか。
VPC を作ったからといって必ず EC2 を作るとは限りません。
EC2 の起動や停止は EC2 単体で考えればよく VPC とは「ライフサイクルが異なる」ことになります。

パラメーターの使用

テンプレート内で指定するシステム固有の値はパラメーターに記載します。
パラメーターを使う利点は以下です。

  • テンプレートファイルを複数リソース、複数アカウントで使いまわしが可能
  • 設定値の一覧性向上
  • 入力制限によるミス防止

パラメーターは AllowedPattern で入力値の制限が可能です。
CIDR が必要なところに文字が入らないように、選択できるインスタンスタイプを限定する、といった使い方が想定されます。

ファイルにベタ書きするほかに、AWS Systems Manager Parameter Store, Secrets Manager を使う方法もあります。

詳しくは公式ドキュメントを参照ください。
User Guide - Parameters

ゼロから作らない

世の中には CloudFormation テンプレートが溢れています。
ゼロから作らず公開されているテンプレートをカスタマイズしたほうが効率的です。

User Guide - Sample templates

クロススタック参照はほどほどに

あるスタック (テンプレートを実行して作成されたリソース群) のリソース ID を他のスタックから参照できる便利機能です。

例えば、以下のようなスタックがあるとします。

  • VPC
  • セキュリティグループ1
  • セキュリティグループ2

セキュリティグループを作成する度に VPC ID を指定するのは誤操作の元です。
VPC スタックで VPC ID を「my_vpc」としてエクスポートしておきます。
セキュリティグループ1 or 2 スタックでは VPC ID を指定する替わりに「my_vpc」をインポートして使用します。

一見すると便利ですが、留意点もあります。
参照(インポート)されているリソースは、インポートしている側でインポートを削除しないと変更ができないということです。
VPC のような一度作成したらそうそう削除しないリソースは問題無いかもしれませんが、
作成/変更/削除 が頻繁に発生するリソースを他に参照させてしまうと、構成変更の柔軟性が失われる可能性があります。

スタックのネストもほどほどに

パターン化されたリソース群を複数セット作成する要件がある際にはネストされたスタックはとても有用です。
ネスト内のあるリソースの更新が全てのセットに反映されるので構成管理上の優位性もあります。

ただやはり、柔軟性には欠けると思います。
構成がかっちり決まっているパターンだけネストされたスタックを使用しましょう。

「一度作ってしまったリソースを変更しにくい」という制約はクラウド時代にシステム構築において大きなマイナスになると考えます。
なるべくシンプルなテンプレートファイルにしたほうが結局は幸せだと思います。

ロールバックを上手に使い分ける

CloudFormation はスタックのプロビジョニング失敗時に

  • ロールバックをするかしないか
  • 全てをロールバックするか正常なリソースは残すか

が選択可能です。

スタックの多数のリソースが含まれている場合、失敗時に全てのリソースがロールバックされてしまうと、再実行に時間を要してしまいます。

その逆で、全てのリソースをロールバックさせたほうがリソースの依存関係で悩まなくていいという利点はあります。

bashでラッピングする

マネジメントコンロールからスタックを操作すると画面遷移が多く、作業としての効率が下がってしまいます。
一度で全てのリソースが完璧に作成されることは珍しく試行錯誤しながらスタックが完成していくことになると思います。

作業効率を上げるために bash で AWS CLI をラッピングします。
テンプレートファイル保管場所やスタック名、テンプレートファイル内で記述したパラメーターも指定します。

#!/usr/bin/bash
source ./commonenv

export TEMPLATEFILE=/path_to_template/template.json
export STACKNAME=my-new-stack
export VALUE1=anyvalue1
export VALUE2=anyvalue2

aws cloudformation deploy \
  --template-file ${TEMPLATEFILE}  \
  --stack-name ${STACKNAME} \
  --parameter-overrides Param1=${VALUE1} Param2=${VALUE2}

exit

VPC ID など複数のスタックから参照する変数は commonenv に記述しておきます。

commonenv

export VPC_CIDR="n.n.n.n"
export VPC_ID="xx"
export PUBLIC_SUBNET_AZA="aaa"
export PUBLIC_SUBNET_AZC="ccc"
export PUBLIC_SUBNET_AZD="ddd"

VSCodeで自動補完

CloudFormation テンプレートをなるべく低労力で書きたいと思います。
VSCode には様々な拡張があります。もちろん CloudFormation 向けの拡張も多く存在します。

そのなかでも補完機能とシンタックスチェックはぜひとも導入して欲しいと考えています。

AWS CloudFormation Template Schema
vscode-cfn-lint

マルチアカウント、マルチリージョン

マルチアカウントまたはマルチリージョンで一斉にリソースを作りたい場合は StackSets を利用します。
StackSets を利用すればスイッチロールをしたりリージョンを切り替えたりといった手間が不要になります。
※ 事前に各アカウントに StackSets 用の IAM ロールを作成しておきます。(ここだけスイッチロール等が必要です)

User Guide - StackSets concepts
CloudFormation StackSetsを試してみた
一発でGuardDutyを全リージョン有効化して通知設定するテンプレート作った

既存リソースをCloudFormationテンプレート化する方法はありますか?

CloudFormation を使い始める方の半分くらいはこの課題に頭を悩ますのではないでしょうか。
残念ながらこれを解決する完璧なソリューションは知りません。

ただ、高い精度で実現するツールが存在します。

Former2

Former2 の Web サイトに ReadOnly のクレデンシャルを登録しないといけませんが、それに抵抗がなければ便利なサービスであると思います。
セキュリティ上どう考えるかは自社のポリシーに沿ってもらえればと思います。

知らなかった事を後悔した。既存のリソースからCloudFormationのテンプレート生成 Former2 の紹介 #reinvent 2019

以上、吉井 亮 がお届けしました。