はじめに
今回は、AWS CloudFormationテンプレートを使用した、CLIコマンドでのインフラ環境構築手順についてまとめてみました。
- 単一スタックの場合
- クロススタックの場合
- ネストスタックの場合
1. 単一スタックの場合
テンプレートおよび手動デプロイに関してはこちらの記事をご参照ください。
①スタックのデプロイ
aws cloudformation deployコマンドを使用します。
引数に「template-file」と「stack-name」の指定が必須となります。
その他にも複数のオプションを設定することが可能です。
例:
--no-execute-changeset: 変更セットだけ作成してデプロイせずに差分確認が可能
--capabilities: IAMリソース操作が含まれる場合に明示的に許可するために必要
--parameter-overrides: スタックテンプレートの入力パラメータを指定するために必要
--s3-bucket: 51,200バイトを超えるサイズのテンプレートをデプロイする場合には必要(超えない場合はそのままAPIで送信されるため、テンプレートファイル保存用のs3バケットは作成されない)
詳しくは公式ドキュメントをご参照ください。
aws cloudformation deploy \
--template-file test.yaml \
--stack-name test-stack \
--profile project-a-dev
- この
deployコマンドは、内部で変更セットを作成 → 適用までをセットで自動的に行います - スタックが存在しなければ新規作成、あれば更新を自動で判断して行います
※似たコマンドに、create-stackがありますが、こちらは単純に「スタックを作成する」コマンドであるため、更新の際は別コマンドupdate-stackが必要になり、使い分ける必要があります。
※deployコマンドでの更新時は、update-stackが内部的に実行されています。
実務ではdeployコマンドのみに統一するのが推奨されています。
②スタックの更新
デプロイ同様、aws cloudformation deployコマンドを使用します。
もしくは、事前に
-
--no-execute-changesetオプションで実行 - 作成された変更セットを
aws cloudformation describe-change-setで差分を確認 - 問題なければ
aws cloudformation execute-change-setで反映
するとより安全です。
※Replacement(既存インスタンスの削除→置き換え)が発生するかどうかの確認は重要です
③スタックの削除
aws cloudformation delete-stackコマンドを使用します。
引数に「stack-name」の指定が必須となります。
スタック配下のリソースがすべて削除対象ですが、
・S3バケットが空でない
・DeletionPolicy: Retainが設定されている
場合など、削除が失敗してしまうため注意が必要です。
また、削除は非同期(すぐ終わらない)のため、CI/CDやスクリプトを使用した自動構成の環境下では、確実に削除完了を待つためaws cloudformation delete-stackコマンドの使用後に続けてaws cloudformation wait stack-delete-completeコマンドを使用するのがおすすめです。
④手動で変更/削除してしまった場合
以下の手順で差分を確認することができます。
1. ドリフト検知を開始
aws cloudformation detect-stack-drift \
--stack-name test-stack \
--profile project-a-dev
するとドリフトIDが出力されます。
{
"StackDriftDetectionId": "abc123-xxxx"
}
2. 検知完了まで待つ
先ほど取得したIDを使用して以下のコマンドを実行します。
aws cloudformation describe-stack-drift-detection-status \
--stack-drift-detection-id abc123-xxxx \
--profile project-a-dev
結果が表示されます。
・DETECTION_IN_PROGRESS:実行中
・DETECTION_COMPLETE:完了
・DETECTION_FAILED:失敗
3. 差分(ドリフト結果)を取得
DETECTION_COMPLETEになったら以下のコマンドを実行し、テンプレートと実際のAWS環境の差分を確認します。
aws cloudformation describe-stack-resource-drifts \
--stack-name test-stack \
--profile project-a-dev
4. テンプレートに合わせ修正
基本は再デプロイすることでテンプレートに合わせます(上書き/修正される)
ただし、CLIではテンプレート自体に変更がない場合、変更セットを作成することができません。
AWSコンソールではドリフト結果から変更セットを作成する機能が提供されているため、現状はそちらを使用することになりそうです。
※ドリフト検知対象外のリソースも存在します
※手動での修正対応が必要になるケースも存在します
2. クロススタックの場合
テンプレートおよび手動デプロイに関してはこちらの記事をご参照ください。
①スタックのデプロイ
単一スタックの場合と同様にデプロイしますが、順番はExportしている側→Importしている側の順にデプロイします。
②スタックの更新
単一スタックの場合と同様に更新しますが、スタック間の依存関係に注意が必要です。
例:Export値が更新されたのにImport値は更新されていない(古い値を参照)
③スタックの削除
単一スタックの場合と同様に削除しますが、順番はImportしている側→Exportしている側の順に削除します。
3. ネストスタックの場合
テンプレートおよび手動デプロイに関してはこちらの記事をご参照ください。
①スタックのデプロイ
ネストスタックのCLIデプロイでは、packageコマンドを使用します。
詳しくはこちらの記事をご参照ください。
root.ymlを以下のように書き換えます。
AWSTemplateFormatVersion: "2010-09-09"
Description: Root Stack
Resources:
NetworkStack:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: network.yaml
AppStack:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: app.yaml
Parameters:
SubnetId: !GetAtt NetworkStack.Outputs.SubnetId
SecurityGroupId: !GetAtt NetworkStack.Outputs.SecurityGroupId
以下のようなスクリプトを作成します。
#!/bin/bash
set -euo pipefail
STACK_NAME="${1:-my-nested-stack}"
S3_BUCKET="${2}"
PROFILE="${3:-default}"
REGION=$(aws configure get region --profile "${PROFILE}")
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
# テンプレート保存用s3の作成
aws s3api create-bucket \
--bucket "${S3_BUCKET}" \
--region "${REGION}" \
--create-bucket-configuration LocationConstraint="${REGION}" \
--profile "${PROFILE}"
# packageコマンドの実行
aws cloudformation package \
--template-file "${SCRIPT_DIR}/root.yaml" \
--s3-bucket "${S3_BUCKET}" \
--output-template-file "${SCRIPT_DIR}/packaged.yaml" \
--profile "${PROFILE}"
# 生成されたテンプレートの実行
aws cloudformation deploy \
--template-file "${SCRIPT_DIR}/packaged.yaml" \
--stack-name "${STACK_NAME}" \
--profile "${PROFILE}"
スクリプトを実行します。
./deploy.sh <スタック名> <s3バケット名(世界で一意)> <awsプロファイル名>
②スタックの更新
単一スタックの場合と同様に更新します(root/親スタックが対象)
③スタックの削除
単一スタックの場合と同様に削除します(root/親スタックが対象)