Open12

AWS CDK で Fargate Application を Blue/Green Deployment する L3 Construct を作る際のメモ

やまゆやまゆ

Why?

CDK Pipelines をこれまで利用していたが、 Blue/Green Deployment したいのと V2 CodePipeline を利用したいので自作することにした。

References

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 対応する
  • 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 だけで良い

デプロイインフラの初期化と更新

  1. 手動で cdk deploy を行うことで初期化開始
  2. CodePipeline の作成
  3. ECR の作成
  4. CodeBuild の作成
  5. CodeDeploy の作成
  6. Fargate Application の作成

実際のアプリケーションデプロイ

  1. GitHub リポジトリへの特定のブランチまたはタグのプッシュがトリガーとなって CodePipeline が動きだす
  2. ECR に commit ハッシュのタグでビルドして push
    • リモートキャッシュ が適切に利用されること
      • 毎回 php extension のビルドが走るとめっちゃ遅いので
      • ベース image を Docker Hub から持ってくると Rate limit に引っかかったりトラブル発生時にめんどくさいため
    • Pull-through cache の利用も視野(ベース image を Docker Hub にしなければいいので must ではない)
    • SOCI 対応も視野
    • Trivy か ECR のデフォルトスキャン機能を使って脆弱性検知
  3. Manual approve する
  4. CodeDeploy で Blue/Green Deployment(ecspresso にする可能性もあり?)
やまゆやまゆ
  • CodeBuild の提供イメージの BuildKit が古いので、新しいのを自分で入れるかカスタムイメージを使う必要がある
  • CodeBuild Lambda は privileged に出来ないので docker build 出来ない -> BuildKit 以外で、 privilege いらないツールでの Dockerfile ビルドを行えれば可能性はある? Podman とか Buildah とか?
やまゆやまゆ

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 環境は手動にしたい