Open12
AWS CDK で Fargate Application を Blue/Green Deployment する L3 Construct を作る際のメモ
Why?
CDK Pipelines をこれまで利用していたが、 Blue/Green Deployment したいのと V2 CodePipeline を利用したいので自作することにした。
References
- https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_codepipeline-readme.html
- https://github.com/aws/aws-cdk/issues/1559
- https://aws.amazon.com/blogs/devops/blue-green-deployments-using-aws-cdk-pipelines-and-aws-codedeploy/
- https://github.com/tsukuboshi/cdk-microservices-bluegreendeployment-template
- https://github.com/classmethod/icasu-cdk-ecs-fargate-sample/tree/main/packages/iac
Construct library repository は cdk-pipelines-github を参考にして projen を使って作る。
リポジトリは il-m-yamagishi/aws-cdk-appdp。
Requirements
- GitHub Actions は利用しなくても良い形にする(AWS 完結が嬉しい)
- VPC などの stateful resources は別の CDK で事前にデプロイし、必要な分は fromLookUp などを使って参照する。この Construct では関与しない
- 日々のデプロイを行うのはあくまで Fargate タスクだけ
- Multi-platform(amd64/arm64v8) 対応する
- Docker Hub 公式 image みたいに同じタグに複数の platform 入れたいけど難しい? -> ECR 対応してそう
- Fargate Spot 対応する
- Spot は ARM64 対応していないので注意 -> 2024/09 対応された
- dev, staging, production 全部で使えるようにする
- Manual Approve を optional で入れられるようにする
- Hot-swap deployment も視野(must ではない)
- アプリケーションリポジトリとインフラリポジトリが異なっていても同じでも、どちらでも可
- めんどそうなら同じのみの制限としても良い
- 1 つのリポジトリで複数のコンテナ image がビルドされることを想定
- Dockerfile や multi-stage build でどれをビルドして、どの TaskDefinition でどのビルドを使うか指定出来るようにする
- 古いタグを消せるように https://techblog.kayac.com/ecrm-oss
- Slack, ChatWork へのイベント通知
- CircuitBraker 対応
- Source はひとまず GitHub だけで良い
デプロイインフラの初期化と更新
- 手動で cdk deploy を行うことで初期化開始
- CodePipeline の作成
- ECR の作成
- CodeBuild の作成
- CodeDeploy の作成
- Fargate Application の作成
実際のアプリケーションデプロイ
- GitHub リポジトリへの特定のブランチまたはタグのプッシュがトリガーとなって CodePipeline が動きだす
- ECR に commit ハッシュのタグでビルドして push
-
リモートキャッシュ が適切に利用されること
- 毎回 php extension のビルドが走るとめっちゃ遅いので
- ベース image を Docker Hub から持ってくると Rate limit に引っかかったりトラブル発生時にめんどくさいため
- Pull-through cache の利用も視野(ベース image を Docker Hub にしなければいいので must ではない)
- SOCI 対応も視野
- Trivy か ECR のデフォルトスキャン機能を使って脆弱性検知
-
リモートキャッシュ が適切に利用されること
- Manual approve する
- CodeDeploy で Blue/Green Deployment(ecspresso にする可能性もあり?)
- https://gallery.ecr.aws/docker/library/docker CodeBuild のビルドイメージこれの dind にする?
- ARM 対応わかりやすい 円安に負けない!共通バックエンドAPIサーバーARM対応プロジェクト - Uzabase for Engineers
- Pushing a multi-architecture image to an Amazon ECR private repository - Amazon ECR multi-arch manifest の push 方法(ECR 対応している)
- Cache storage backends | Docker Docs
- class AssetImage · AWS CDK
- aws-fargate-seekable-oci-toolbox/soci-codepipeline/multiarch-cloudformation.yaml at main · aws-samples/aws-fargate-seekable-oci-toolbox SOCI 対応 CodeBuild
- aws-codebuild-docker-images/al2/x86_64/standard/5.0/Dockerfile at master · aws/aws-codebuild-docker-images 今の CodeBuild の Docker version
- cdk-microservices-bluegreendeployment-template/lib/cdk-microservices-bluegreendeployment-template-stack.ts at main · tsukuboshi/cdk-microservices-bluegreendeployment-template
Multi-arch build と Remote cache を考慮した docker build コマンドは理想形としてはこう(まだ動作確認してない)
- 前提: ctr, soci, docker buildx 0.12+ が動くこと
- 環境変数:
REPOSITORY_URI
,COMMIT_ID
,PASSWORD
// 準備
$ docker buildx create --driver=docker-container --use --bootstrap \
--platform linux/amd64,linux/arm64 \
--driver-opt image=public.ecr.aws/vend/moby/buildkit:buildx-stable-1
$ export CPU_ARCH=amd64
$ docker buildx build \
--tag ${REPOSITORY_URI}:${COMMIT_ID}-${CPU_ARCH} \
--cache-from type=registry,ref=${REPOSITORY_URI}:cache-${CPU_ARCH} \
--cache-to mode=max,image-manifest=true,oci-mediatypes=true,type=registry,ref=${REPOSITORY_URI}:cache-${CPU_ARCH} \
--output type=docker,dest=./image-${CPU_ARCH}.tar \
--platform linux/${CPU_ARCH}
--build-arg ... \
--target api \
.
$ ctr image import ./image-${CPU_ARCH}.tar
$ soci create ${REPOSITORY_URI}:${COMMIT_ID}-${CPU_ARCH}
$ ctr image push --user AWS:${PASSWORD} ${REPOSITORY_URI}:${COMMIT_ID}-${CPU_ARCH}
$ soci push --user AWS:${PASSWORD} ${REPOSITORY_URI}:${COMMIT_ID}-${CPU_ARCH}
$ export CPU_ARCH=arm64
// 上と同じコマンドを叩きなおす
$ docker manifest create --amend ${REPOSITORY_URI}:${COMMIT_ID} \
${REPOSITORY_URI}:${COMMIT_ID}-amd64 \
${REPOSITORY_URI}:${COMMIT_ID}-arm64
$ docker manifest push --purge ${REPOSITORY_URI}:${COMMIT_ID}
CodeBuild で ECR に新しい image を push して、 SSM に新しいタグ登録して、それ契機で別の CodeBuild を起動させて ecspresso で CodeDeploy を自動生成してもらうのがベストアンサー説ある?
- image build は自動で、デプロイは手動(ChatOps 等)にする?
- dev 環境はデプロイ自動(Rolling-update 可)、 staging/prod 環境は手動にしたい
Fargate Spot Graviton 対応が入ったのでやはりマルチプラットフォームビルドは重要。