こんにちは、つくぼし(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 XXXXXXXXXXXX.dkr.ecr.ap-northeast-1.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_ARN
、EXECUTION_ROLE_ARN
、CONTAINER_NAME
、TASK_FAMILY
については、CodeBuild環境変数として別途指定し、sedコマンドを用いてビルド中にタスク定義ファイル及びアプリケーション仕様ファイルを書き換える事で、値を動的に変更可能になるように記載しています。
もし他の値(例:タスク定義のログ設定)を動的に変更可能にしたい場合も、ビルド仕様ファイルにsedコマンドによる書き換え処理を追記する事で実現可能です。
以下は上記のビルド仕様ファイルを用いる場合のタスク定義ファイル及びアプリケーション仕様ファイルの例です。
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)でした!