🦅

複数コンテナ持ちのECSサービス(タスク)のBlue/GreenデプロイをCodeSeriesでやってみた

に公開

ECSのBlue/GreenデプロイをCodeSeriesでやってる公式ドキュメントやブログはそれなりに見つかるが、複数コンテナ持ちパターンで分かりやすいモノは見つからなかったので、その備忘録

構成図

手順

前提

ECSのBlue/GreenデプロイをCodeSeriesで実施すること自体は、以下ハンズオン資料と公式チュートリアルを見ればこと足りるので、コンテナが1つパターンの基本的なパイプラインは組めてることが前提の手順とする

1.ビルドプロジェクトでバッチ設定を実施する

設定が必須なのはバッチ用のサービスロールのみ
特に拘りがなければ、環境設定で使ってる既存のIAMロールを設定しとけばOK

バッチ設定のパラメータ詳細は以下参照
https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/create-project-console.html#create-project-console-batch-config

2. パイプラインのビルドステージの設定を変更する

ビルドタイプをバッチビルドに設定
「出力アーティファクト」に任意の名前をビルド/デプロイするコンテナの数の分だけ入力
ここで入力した「出力アーティファクト名」は後で利用する為、控えておく

3. パイプラインのデプロイステージの設定を変更する

「入力アーティファクト」と「入力アーティファクトが持つイメージ詳細」に手順2で入力した「出力アーティファクト名」を追加する
「タスク定義のプレースホルダー文字」にコンテナを識別できる任意の文字列を入力する
ここで入力した「タスク定義のプレースホルダー文字」は後で利用する為、控えておく

4. taskdef.jsonを変更する

containerDefinitionsのimageに手順3で入力した「タスク定義のプレースホルダー文字」を入力する

taskdef.jsonの例

{
    "containerDefinitions": [
        {
            "name": "app",
            "image": "<IMAGE_NAME_APP>",
            "cpu": 0,
            "portMappings": [
                {
                    "containerPort": 9000,
                    "hostPort": 9000,
                    "protocol": "tcp"
                }
            ],
            "essential": true,
            "environment": [],
            "mountPoints": [
                {
                    "sourceVolume": "app",
                    "containerPath": "/app/public",
                    "readOnly": false
                }
            ],
            "volumesFrom": [],
            "linuxParameters": {
                "initProcessEnabled": true
            },
            "workingDirectory": "/app",
            "logConfiguration": {
                "logDriver": "awslogs",
                "options": {
                    "awslogs-group": "/aws/ecs/hogehoge",
                    "awslogs-region": "ap-northeast-1",
                    "awslogs-stream-prefix": "admin"
                }
            }
        },
        {
            "name": "nginx",
            "image": "<IMAGE_NAME_NGINX>",
            "cpu": 0,
~ Snip ~ 

5. buildspec.ymlを変更する

batchセクションを追加する
バッチビルドタイプによって入力が必要なパラメータに違いがあるので、ここではコンテナを並列でビルドできるbuild-listを選択
build-listセクションに必要なパラメータは以下

  • identifier
    • 手順2で入力した「出力アーティファクト名」を設定すること
  • env
    • variables
      • REPOSITORY_URI
        • ビルドしたコンテナのpush先のレポジトリURLを入力
      • DOCKERFILE_PATH
        • Dockerfileのパスを入力
          • トップディレクトリからの相対パスで入力すること

buildspec.ymlの例

version: 0.2
batch:
  build-list:
    - identifier: nginx
      env:
        variables:
          REPOSITORY_URI: XXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/hogehoge/nginx
          DOCKERFILE_PATH: ./nginx/Dockerfile
    - identifier: app
      env:
        variables:
          REPOSITORY_URI: XXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/hogehoge/app
          DOCKERFILE_PATH: ./app/Dockerfile
phases:
  pre_build:
    commands:
      - echo Logging in to Amazon ECR...
      - aws --version
      - aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $(echo ${CODEBUILD_BUILD_ARN} | cut -f 5 -d :).dkr.ecr.ap-northeast-1.amazonaws.com
      - REPOSITORY_URI=${REPOSITORY_URI}
      - DOCKERFILE_PATH=${DOCKERFILE_PATH}
      - COMMIT_HASH=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7)
      - IMAGE_TAG=${COMMIT_HASH:=latest}
  build:
    commands:
      - echo Build started on `date`
      - echo Building the Docker image...
      - docker build -f $DOCKERFILE_PATH -t $REPOSITORY_URI:latest .
      - docker tag $REPOSITORY_URI:latest $REPOSITORY_URI:$IMAGE_TAG
  post_build:
    commands:
      - echo Build completed on `date`
      - echo Pushing the Docker images...
      - docker push $REPOSITORY_URI:latest
      - docker push $REPOSITORY_URI:$IMAGE_TAG
      - printf '{"ImageURI":"%s"}' $REPOSITORY_URI:$IMAGE_TAG > imageDetail.json
artifacts:
  files: imageDetail.json

batchセクションのパラメータ詳細は以下参照
https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/batch-build-buildspec.html

留意点

どれか一つのコンテナの変更であっても、全てのコンテナのビルド/デプロイが走ります。
※厳密にいうと、ソースに指定してるブランチの変更があれば、そこの変更がどこであれ、全てのコンテナのビルド/デプロイが走る。
Lambda使ってこねくり回すとかCodeSeries辞めるとかしないと、多分どうしようもない
全てのコンテナのビルド/デプロイが走ること自体に大きなデメリットはないので、強い思いがないのであれば、そういうもんと割り切るのが良いと思ってる

Discussion