はじめに
AWS CDK でインフラを管理し、コンテナ実行基盤やバッチ実行基盤を組み合わせている構成では、デプロイ手順が増えがちです。
この記事は、実コードや実環境の値は含めず、複数の AWS リソースをまとめて扱うデプロイ作業を一般化したメモです。
たとえば、1 回のリリースで必要になる操作はこれくらいあります。
- アプリケーションイメージを build する
- コンテナレジストリへ push する
- CDK で必要なスタックを deploy する
- アプリケーション実行基盤へ新しいバージョンを反映する
- 必要に応じてジョブ実行基盤のバージョンを更新する
- 必要に応じてデータ更新処理を実行する
- 環境ごとの設定値や context を切り替える
- production 相当の環境だけ明示確認する
全部を README に書くだけだと、操作漏れや環境取り違えが起きます。
そこで、よく使う操作を Bash の deploy wizard に集約しました。
目的
wizard の目的は「何でも自動化すること」ではありません。
狙いは次です。
- 環境ごとの操作入口を揃える
- infra deploy と application deploy を分ける
- 危険な操作には確認を入れる
-
.envのローカル設定でクラウド認証を壊さない - version tag と CDK context を揃える
- よく使う運用コマンドを迷わず実行できる
コマンド入口
root の package.json から呼べるようにします。
以下は架空のディレクトリ名・環境名を使った例です。
{
"scripts": {
"deploy:wizard": "bash tools/deploy/wizard.sh",
"deploy:wizard:dev": "bash tools/deploy/wizard.sh --env dev",
"deploy:wizard:stg": "bash tools/deploy/wizard.sh --env stg",
"deploy:wizard:prod": "bash tools/deploy/wizard.sh --env prod",
"deploy:wizard:dev:migrate": "bash tools/deploy/wizard.sh --env dev migrate",
"deploy:wizard:dev:seed": "bash tools/deploy/wizard.sh --env dev seed"
}
}
開発者はまず pnpm deploy:wizard を覚えればよい形にします。
環境選択
対話実行では環境を選びます。
環境名はプロジェクトごとに違うので、ここでは dev / stg / prod という一般的な名前にしています。
select_env() {
echo "環境を選択してください:"
echo " 1) dev"
echo " 2) stg"
echo " 3) prod"
echo " 4) dev + stg"
read -p "選択 [1-4]: " choice
case "$choice" in
1) ENV_TARGETS=("dev") ;;
2) ENV_TARGETS=("stg") ;;
3) ENV_TARGETS=("prod") ;;
4) ENV_TARGETS=("dev" "stg") ;;
*) exit 1 ;;
esac
}
dev + stg のように複数環境へ順番に反映する選択肢も用意しておくと、検証環境の同期が楽になります。
production 相当の操作は明示確認する
production 相当の環境では、ただの [Y/n] では弱いので、環境名を入力させます。
confirm_prod() {
echo "production 相当の環境への操作です。"
read -p "確認: \"prod\" と入力してください: " answer
if [[ "$answer" != "prod" ]]; then
echo "キャンセルしました"
exit 0
fi
}
この手の確認は地味ですが、環境取り違えの最後の防波堤になります。
.env がクラウド認証を壊さないようにする
ローカル開発では .env にエミュレータやモックサービス向けの値が入ることがあります。
CLOUD_ACCESS_KEY_ID=local
CLOUD_SECRET_ACCESS_KEY=local
CLOUD_ENDPOINT_URL=http://localhost:4566
これをクラウド環境への deploy 時にそのまま読んでしまうと、認証や deploy コマンドが壊れます。
aws-vault などで認証済みの場合は、認証情報を退避してから .env を読み、認証情報だけ戻します。
if [ -f "$PROJECT_ROOT/.env" ] && [ -n "${AWS_VAULT:-}" ]; then
SAVED_KEY_ID="${AWS_ACCESS_KEY_ID:-}"
SAVED_SECRET="${AWS_SECRET_ACCESS_KEY:-}"
SAVED_TOKEN="${AWS_SESSION_TOKEN:-}"
set -a
source "$PROJECT_ROOT/.env"
set +a
export AWS_ACCESS_KEY_ID="$SAVED_KEY_ID"
export AWS_SECRET_ACCESS_KEY="$SAVED_SECRET"
export AWS_SESSION_TOKEN="$SAVED_TOKEN"
fi
deploy action を分ける
全部を毎回 full deploy すると遅いです。
よく使う操作を分けます。
1) application deploy
build / push -> 実行基盤へ反映
2) infrastructure deploy
CDK による基盤・設定の反映
3) full deploy
infrastructure deploy + application deploy + 必要な後続処理
4) data migration
実行前に内容と対象環境を確認する
5) service restart
必要な実行単位だけ再起動する
6) job runner update
ジョブ実行基盤のバージョンを更新する
7) logs / status / seed などの運用ツール
この分岐があるだけで、普段の反映がかなり速くなります。
CDK deploy の範囲も分ける
CDK stack が増えてくると、毎回全 stack を deploy するのは重くなります。
application runtime のみ:
コンテナレジストリ
アプリケーション実行基盤
ジョブ実行基盤
スケジュール・イベント系リソース
全 stack:
ネットワーク
データストア
認証・認可
セキュリティ境界
application runtime
select_cdk_scope() {
echo "CDK deploy 範囲:"
echo " 1) application runtime のみ"
echo " 2) 全 stack"
read -p "選択 [1-2]: " choice
case "$choice" in
1) ACTION="cdk_deploy_runtime" ;;
2) ACTION="cdk_deploy_all" ;;
esac
}
ネットワークやデータストアを触る deploy と、アプリ実行基盤だけの deploy を分けておくと、心理的にも安全です。
まとめ
CDK で複数の AWS リソースをまとめて管理している構成では、デプロイ手順が増えます。
README に手順を書くことも大事ですが、毎回の操作は script に寄せた方が楽です。
やってよかったことは次です。
- 環境選択を wizard にする
- production 相当の環境だけ強い確認を入れる
-
.envとクラウド認証情報の衝突を避ける - account id などの環境依存値は必要なタイミングで補完する
- deploy action を分ける
- CDK deploy の範囲を分ける
- version tag と CDK context を git sha で揃える
- 更新対象を選べるようにする
- ローカルエミュレータの bootstrap は別 script にする
デプロイは「気合いで手順を守る」より、「間違いにくい入口を作る」方が長く効きます。