こんにちは!EC部の篠﨑です。
今日は個人的によくやるCloudFormationの小技を紹介していきます。
ほんのちょっと小慣れ感が出せると思いますので、これからCloudFormation使っていくぜという方の参考になれば幸いです。
- Output/ImportValue
- Importした値をSubでくっつける
- パラメーターの値をSubでくっつけてImport
- AWS CLIを使ってスタックデプロイをするときのパラメータファイルを少し楽して作成する
- スタック作成失敗時に毎回スタックの削除をしないためにロールバックを無効にする
- おわりに
Output/ImportValue
こちらはおなじみの方も多いかと思いますが、スタック間で値の受け渡しを行うものです。
例えば、EC2インスタンスを構築するスタックとInstance Profileを構築するスタックが異なる場合、以下のような書き方をします。
↓Instance Profileテンプレート
Resources: InstanceProfile: Type: "AWS::IAM::InstanceProfile" DeletionPolicy: "Delete" Properties: # ~~ # 詳細省略 # ~~ Outputs: InstanceProfile: Value: !Ref InstanceProfile Export: Name: instance-profile-name
↓EC2インスタンステンプレート
Resources: Ec2Instance: Type: AWS::EC2::Instance Properties: AvailabilityZone: aa-example-1a ImageId: ami-1234567890abcdef0 # Instance Profileの名前をインポート IamInstanceProfile: !ImportValue instance-profile-name # ~~ # 詳細省略 # ~~
Importした値をSubでくっつける
ImportValueで取得した値を使って、Refで利用したい場合に利用します。
例えば、EC2からS3オブジェクトへのアクセスが必要なケースを考えます。 EC2へアタッチするInstance ProfileとS3バケットのテンプレートが異なる場合、ロール記載のCloudFormationテンプレートにS3バケットARNをImportして記載します。
↓S3バケットテンプレート
Resources: ArtifactBucket: Type: AWS::S3::Bucket Properties: BucketName: !Sub "bucket-${AWS::AccountId}" Outputs: BucketArn: Value: !GetAtt S3Bucket.Arn Export: Name: arn-s3-bucket
↓EC2 Instance Profileテンプレート
Resources: EC2Role: Type: "AWS::IAM::Role" DeletionPolicy: "Delete" Properties: # ~~ # 詳細省略 # ~~ Policies: - PolicyName: policy-test PolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Action: - "s3:Get*" - "s3:List*" Resource: # バケットARN - !ImportValue arn-s3-bucket # バケット内オブジェクトのARN - !Sub - "${BucketArn}/*" - BucketArn: {'Fn::ImportValue': 'arn-s3-bucket'}
パラメーターの値をSubでくっつけてImport
例えば、環境ごとにInstance Profileを作成し、それぞれの環境ごとにEC2インスタンスのテンプレートをInstance Profileとは別で作成するとします。 Instance Profileのテンプレートでは環境それぞれに以下のようなキーでOutputをすることとします。
- instance-profile-prd
- instance-profile-stg
- instance-profile-dev
EC2(Instance Profile含む)のテンプレートは環境ごとに作成したくないので、同じテンプレートでどうにかしたいときにはEC2のテンプレートは以下のようにします。
Parameters: Environment: Type: String AllowedValues: - prd - dev - stg Resources: Ec2Instance: Type: AWS::EC2::Instance Properties: AvailabilityZone: aa-example-1a ImageId: ami-1234567890abcdef0 IamInstanceProfile: { "Fn::ImportValue": {"Fn::Sub": "instance-profile-${Environment}"}} # ~~ # 詳細省略 # ~~
これで全て同じテンプレートが使えてすっきりですね!
AWS CLIを使ってスタックデプロイをするときのパラメータファイルを少し楽して作成する
AWS CLIを使ってCloudFormationスタックのデプロイをする方法は日高さんが書いてくれていますので、詳細についてはこちらをご確認ください。
JSONファイルでパラメータを指定するのですが、パラメータファイルを作るのが面倒です。 そこで、テンプレートファイルにDefault値が付いている場合はコマンドを使って少し楽しましょう。 使うのはAWS CLIとjqコマンドです。
aws cloudformation validate-template \ --template-body file://{ファイル名} \ |jq '.Parameters[]|[{ "ParameterKey": .ParameterKey, "ParameterValue": .DefaultValue}]' \ |jq -s -c add| jq . > resource-params.json
テンプレートでDefaultを指定していない場合、以下コマンドでチョットだけ楽できるかもしれないです。
aws cloudformation validate-template \ --template-body file://{ファイル名} \ |jq '.Parameters[]|[{ "ParameterKey": .ParameterKey, "ParameterValue": ""}]' \ |jq -s -c add \ | jq . > resource-params.json
ちなみにvalidate-template
コマンドを使うことによって、deploy
コマンドでデプロイする際に--capability
オプションの要否確認やフォーマットチェックをしてくれます。
deployコマンドを使う前に一回やっておくと手戻りが減ります。
スタック作成失敗時に毎回スタックの削除をしないためにロールバックを無効にする
CloudFormationスタックを作成して、失敗したらスタックを削除してもう一回、、また失敗したからもう一回削除して、、、 特にCloudFormationスタックの作成をして検証するときこんな感じになってませんか????
せっかくAWS CLIでやっているのに、結局コンソールで毎回削除していたり、、、、ということになりかねません。 嫌ですね~
ということで、そんなことを回避するためにスタックを作成するときに「ロールバックしない」を選択してスタックの作成をしてみましょう。 そうすると、スタックを毎回削除して~~~ということがなくなります。
コンソールでは、「スタックの失敗オプション」で[正常にプロビジョニングされたリソースの保持]にチェックを入れます。
AWS CLIでデプロイする場合は--disable-roleback
オプションを追加します。
AWS CLIでやる場合は特に、スタックが失敗した場合、テンプレートの修正をしてそのままもう一回デプロイコマンドを叩くとスタックのアップデートが走ります。 コンソールでの場合は、テンプレート修正後、「更新」からアップデートが可能です。
おわりに
できなくても困らないですが、あると便利だなぁというものを載せてみました。
Output/ImportValueはスタックの密結合にもつながるので、なんでもかんでもやればいいというわけでもなかったり、時と場合によって使っていただけるとよいかなと思います!
CloudFormationマスターになりたいぜという方はぜひ利用してみてください!
篠﨑 勇輔(書いた記事を見る)
クラウドインテグレーション部 SA1課