はじめに
AWS CDK でインフラを管理し、ECS で Web/API を動かし、Lambda container image で runner を動かす構成では、デプロイ手順が増えがちです。
たとえば、1 回のリリースで必要になる操作はこれくらいあります。
- Docker image を build する
- ECR に push する
- CDK deploy する
- ECS service を再デプロイする
- Lambda function の image tag を更新する
- DB migration を流す
- 環境ごとの suffix や context を切り替える
- 本番操作だけ明示確認する
全部を README に書くだけだと、操作漏れや環境取り違えが起きます。
そこで、よく使う操作を Bash の deploy wizard に集約しました。
目的
wizard の目的は「何でも自動化すること」ではありません。
狙いは次です。
- 環境ごとの操作入口を揃える
- infra deploy と code deploy を分ける
- 危険な操作には確認を入れる
-
.envのローカル設定で AWS 認証を壊さない - image tag と CDK context を揃える
- よく使う運用コマンドを迷わず実行できる
コマンド入口
root の package.json から呼べるようにします。
{
"scripts": {
"wizard": "bash infra/scripts/wizard.sh",
"wizard:dev": "bash infra/scripts/wizard.sh --env dev",
"wizard:sandbox": "bash infra/scripts/wizard.sh --env sandbox",
"wizard:prod": "bash infra/scripts/wizard.sh --env prod",
"wizard:dev:migrate": "bash infra/scripts/wizard.sh --env dev migrate",
"wizard:dev:seed": "bash infra/scripts/wizard.sh --env dev seed"
}
}
開発者はまず pnpm wizard を覚えればよい形にします。
環境選択
対話実行では環境を選びます。
select_env() {
echo "環境を選択してください:"
echo " 1) dev"
echo " 2) sstg"
echo " 3) prod"
echo " 4) dev + stg"
read -p "選択 [1-4]: " choice
case "$choice" in
1) ENV_TARGETS=("dev") ;;
2) ENV_TARGETS=("sandbox") ;;
3) ENV_TARGETS=("prod") ;;
4) ENV_TARGETS=("dev" "sandbox") ;;
*) exit 1 ;;
esac
}
dev + stg のように複数環境へ順番に反映する選択肢も用意しておくと、検証環境の同期が楽になります。
本番操作は明示確認する
本番環境では、ただの [Y/n] では弱いので、環境名を入力させます。
confirm_prod() {
echo "本番環境への操作です。"
read -p "確認: \"prod\" と入力してください: " answer
if [[ "$answer" != "prod" ]]; then
echo "キャンセルしました"
exit 0
fi
}
この手の確認は地味ですが、環境取り違えの最後の防波堤になります。
.env が AWS 認証を壊さないようにする
ローカル開発では .env に LocalStack 用の値が入ることがあります。
AWS_ACCESS_KEY_ID=test
AWS_SECRET_ACCESS_KEY=test
AWS_ENDPOINT_URL=http://localhost:4566
これを AWS デプロイ時にそのまま読んでしまうと、ECR push や CDK deploy が壊れます。
aws-vault などで認証済みの場合は、AWS 認証情報を退避してから .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) コード反映
image build/push -> ECS/Lambda 反映
2) CDK deploy
infra / runtime 設定の反映
3) full deploy
CDK + build/push + migration + app 反映
4) DB migration
5) ECS service restart
6) Lambda runner 更新
7) logs / status / seed などの運用ツール
この分岐があるだけで、普段の反映がかなり速くなります。
CDK deploy の範囲も分ける
CDK stack が増えてくると、毎回全 stack を deploy するのは重くなります。
Runtime 系のみ:
ECR
ECS
Lambda
EventBridge
Scheduler
全 stack:
VPC
RDS
Cognito
WAF
Runtime 系
select_cdk_scope() {
echo "CDK deploy 範囲:"
echo " 1) Runtime 系のみ"
echo " 2) 全 stack"
read -p "選択 [1-2]: " choice
case "$choice" in
1) ACTION="cdk_deploy_app" ;;
2) ACTION="cdk_deploy_all" ;;
esac
}
ネットワークや DB を触る deploy と、アプリ実行基盤だけの deploy を分けておくと、心理的にも安全です。
まとめ
CDK + ECS + Lambda runner の構成では、デプロイ手順が増えます。
README に手順を書くことも大事ですが、毎回の操作は script に寄せた方が楽です。
やってよかったことは次です。
- 環境選択を wizard にする
- 本番だけ強い確認を入れる
-
.envと AWS 認証情報の衝突を避ける - STS で account id を補完する
- deploy action を分ける
- CDK deploy の範囲を分ける
- image tag と CDK context を git sha で揃える
- Lambda runner の更新対象を選べるようにする
- LocalStack bootstrap は別 script にする
デプロイは「気合いで手順を守る」より、「間違いにくい入口を作る」方が長く効きます。