ECSのローリングアップデートとブルー/グリーンデプロイで利用するファイルを比較してみた

2023.02.23

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、つくぼし(tsukuboshi0755)です!

ECSのデプロイタイプには、ローリングアップデートとブルーグリーンデプロイの2種類が存在します。

各々のデプロイタイプにおいて、CodePipelineでCI/CDを実装した場合に、デプロイ時に利用するファイルが異なります。

今回は上記の設定ファイルについて、どのような相違点があるか比較してみます!

そもそもECSデプロイタイプとは?

以下の記事にまとめているので、ぜひご参照ください!

ECSデプロイタイプ別設定ファイルの違い

先にECSのローリングアップデートとブルー/グリーンデプロイで必要な設定ファイル一覧を、以下にまとめます。

ファイル種別 ローリングアップデート ブルー/グリーンデプロイ
Dockerファイル Dockerfile Dockerfile
ビルド仕様ファイル buildspec.yaml buildspec.yaml
イメージ定義ファイル imagedefinitions.json imageDetail.json
タスク定義ファイル (不要) taskdef.json
アプリケーション仕様ファイル (不要) appspec.yaml

なお、Dockerファイル/ビルド仕様ファイルは、ビルドステージで使用するファイルです。

一方で、イメージ定義ファイル/タスク定義ファイル/アプリケーション仕様ファイルは、デプロイステージで使用するファイルとなります。

上記の内、デプロイタイプの違いにより相違が生じるファイルについて、以下で挙げます。

※Dockerファイルについては、基本的にデプロイタイプの違いにより相違が生じるファイルではないため、今回は割愛します。


1.イメージ定義ファイルの名前/内容

ECSと連携するCodePipelineのデプロイステージには、イメージ定義ファイルが必要です。

ローリングアップデートとブルー/グリーンデプロイでは、イメージ定義ファイルの名前及び内容が異なります。

ローリングアップデートの場合

イメージ定義ファイルとして、コンテナ名とイメージURIが記載されているimagedefinitions.jsonというファイルが必要になります。

CodePipelineにビルドステージが存在しない場合は、事前に以下のようなimagedefinitions.jsonを作成し、ソースステージで指定したリポジトリにプッシュする必要があります。

imagedefinitions.json

[
    {
        "name": "sample-webserver",
        "imageUri": "XXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/sample-ecs-repo:latest"
    }
]

一方でCodePipelineにビルドステージが存在する場合は、以下のようなimagedefinitions.jsonを出力するコマンドと、imagedefinitions.jsonを出力アーティファクトに含める記述を、ビルド仕様ファイルに追加する必要があります。

printf '[{"name":"sample-webserver","imageUri":"XXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/sample-ecs-repo:latest"}]' > imagedefinitions.json
artifacts:
  files:
    - imagedefinitions.json

ブルー/グリーンデプロイの場合

イメージ定義ファイルとして、イメージURIが記載されているimageDetail.jsonというファイルが必要になります。

CodePipelineにビルドステージが存在しない場合は、事前に以下のようなimageDetail.jsonを作成し、ソースステージで指定したリポジトリにプッシュする必要があります。

imageDetail.json

{
    "ImageURI": "XXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/sample-ecs-repo:latest"
}

一方でCodePipelineにビルドステージが存在する場合は、以下のようなimageDetail.jsonを出力するコマンドと、imageDetail.jsonを出力アーティファクトに含める記述を、ビルド仕様ファイルに追加する必要があります。

printf '{"ImageURI":"XXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/sample-ecs-repo:latest"}' > imageDetail.json
artifacts:
  files:
    - imageDetail.json


2.タスク定義ファイルの有無

デプロイステージにおけるCodePipelineアクションプロバイダーにCodeDeployToECSを使用する場合、起動されるECSタスク情報が記載されているタスク定義ファイルが必要です。

ローリングアップデートの場合

プロバイダーにECSを使用するため、タスク定義ファイルは必要ありません。

ブルー/グリーンデプロイの場合

プロバイダーにCodeDeployToECSを使用するため、以下のようなタスク定義ファイルtaskdef.jsonを事前に作成し、ソースステージで指定したリポジトリにプッシュする必要があります。

taskdef.json

{
  "taskRoleArn": "arn:aws:iam::XXXXXXXXXXXX:role/ecsTaskRole",
  "executionRoleArn": "arn:aws:iam::XXXXXXXXXXXX:role/ecsTaskExecutionRole",
  "containerDefinitions": [
      {
          "name": "sample-webserver",
          "image": "<IMAGE1_NAME>",
          "essential": true,
          "portMappings": [
              {
                  "hostPort": 80,
                  "protocol": "tcp",
                  "containerPort": 80
              }
          ]
      }
  ],
  "requiresCompatibilities": [
      "FARGATE"
  ],
  "networkMode": "awsvpc",
  "cpu": "256",
  "memory": "512",
  "family": "sample-family"
}

なおプロバイダーにCodeDeployToECSを指定している場合、タスク定義ファイルにIMAGE1_NAMEというプレースホルダーテキストを記載する事で、イメージ定義ファイルから取得したイメージURIに自動で置き換えられます。


3.アプリケーション仕様ファイルの有無

デプロイステージにおけるCodePipelineアクションプロバイダーとしてCodeDeployToECSを使用する場合、デプロイ設定を管理するアプリケーション仕様ファイルが必要です。

ローリングアップデートの場合

プロバイダーにECSを使用するため、アプリケーション仕様ファイルは必要ありません。

ブルー/グリーンデプロイの場合

プロバイダーにCodeDeployToECSを使用するため、以下のようなアプリケーション仕様ファイルappspec.yamlを事前に作成し、ソースステージで指定したリポジトリにプッシュする必要があります。

appspec.yaml

version: 0.0
Resources:
  - TargetService:
      Type: AWS::ECS::Service
      Properties:
        TaskDefinition: <TASK_DEFINITION>
        LoadBalancerInfo:
          ContainerName: "sample-webserver"
          ContainerPort: 80
        PlatformVersion: "1.4.0"

なおプロバイダーにCodeDeployToECSを指定している場合、アプリケーション仕様ファイルにTASK_DEFINITIONというプレースホルダーテキストを記載する事で、作成されたタスク定義のARNに自動で置き換えられます。


4.ビルド仕様ファイルの内容

デプロイステージにおけるCodePipelineアクションプロバイダーにCodeBuildを使用する場合、ビルド設定を管理するビルド仕様ファイルが必要です。

ローリングアップデートの場合

事前に以下のようなbuildspec.yamlを作成し、ソースステージで指定したリポジトリにプッシュする必要があります。

buildspec.yaml

version: 0.2

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 $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com
      - 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 -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
      - echo Writing image definitions file...
      - printf '[{"name":"%s","imageUri":"%s"}]' $CONTAINER_NAME $REPOSITORY_URI:$IMAGE_TAG > imagedefinitions.json
artifacts:
    files: 
      - imagedefinitions.json

なおREPOSITORY_URI及びCONTAINER_NAMEについては、CodeBuild環境変数として別途指定する事で、値を動的に変更可能です。

ブルー/グリーンデプロイの場合

事前に以下のようなbuildspec.yamlを作成し、ソースステージで指定したリポジトリにプッシュする必要があります。

buildspec.yaml

version: 0.2
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 $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com
      - 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 -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:$IMAGE_TAG
      - docker push $REPOSITORY_URI:latest
      - echo Writing image detail file...
      - printf '{"ImageURI":"%s"}' $REPOSITORY_URI:$IMAGE_TAG > imageDetail.json
      - echo Rewriting task definitions file...
      - sed -i -e "s#<TASK_FAMILY>#$TASK_FAMILY#" taskdef.json
      - sed -i -e "s#<TASK_ROLE_ARN>#$TASK_ROLE_ARN#" taskdef.json
      - sed -i -e "s#<EXECUTION_ROLE_ARN>#$EXECUTION_ROLE_ARN#" taskdef.json
      - sed -i -e "s#<CONTAINER_NAME>#$CONTAINER_NAME#" taskdef.json
      - echo Rewriting appspec file...
      - sed -i -e "s#<CONTAINER_NAME>#$CONTAINER_NAME#" appspec.yaml
artifacts:
    files:
      - imageDetail.json
      - taskdef.json
      - appspec.yaml

なおREPOSITORY_URIについては、CodeBuild環境変数として別途指定する事で、値を動的に変更可能です。

またTASK_ROLE_ARNEXECUTION_ROLE_ARNCONTAINER_NAMETASK_FAMILYについては、CodeBuild環境変数として別途指定し、sedコマンドを用いてビルド中にタスク定義ファイル及びアプリケーション仕様ファイルを書き換える事で、値を動的に変更可能になるように記載しています。

もし他の値(例:タスク定義のログ設定)を動的に変更可能にしたい場合も、ビルド仕様ファイルにsedコマンドによる書き換え処理を追記する事で実現可能です。

以下は上記のビルド仕様ファイルを用いる場合のタスク定義ファイル及びアプリケーション仕様ファイルの例です。

以下2つを事前に作成し、ソースステージで指定したリポジトリにプッシュする必要があります。

taskdef.json

{
    "taskRoleArn": "<TASK_ROLE_ARN>",
    "executionRoleArn": "<EXECUTION_ROLE_ARN>",
    "containerDefinitions": [
        {
            "name": "<CONTAINER_NAME>",
            "image": "<IMAGE1_NAME>",
            "essential": true,
            "portMappings": [
                {
                    "hostPort": 80,
                    "protocol": "tcp",
                    "containerPort": 80
                }
            ]
        }
    ],
    "requiresCompatibilities": [
        "FARGATE"
    ],
    "networkMode": "awsvpc",
    "cpu": "256",
    "memory": "512",
    "family": "<TASK_FAMILY>"
}

appspec.yaml

version: 0.0
Resources:
  - TargetService:
      Type: AWS::ECS::Service
      Properties:
        TaskDefinition: <TASK_DEFINITION>
        LoadBalancerInfo:
          ContainerName: <CONTAINER_NAME>
          ContainerPort: 80
        PlatformVersion: "1.4.0"


最後に

今回はECSのローリングアップデートとブルー/グリーンデプロイで利用するファイルについて、比較してみました。

ECSのデプロイタイプが変わるだけで、必要な設定ファイルが結構異なる事が分かるかと思います。

特にローリングアップデートからブルー/グリーンデプロイの切り替え、及びその逆を検討している方は、設定ファイルにどのような違いがあるか把握しておきましょう。

以上、つくぼし(tsukuboshi0755)でした!

参考文献