#はじめに
前回の記事でCodeCommit, CodeBuild, CodePipelineを使って、AWSサービスのみでCI/CDパイプラインを構築しました。
今回は構築したパイプラインにBlue/Greenデプロイを追加して、CodeDeployから制御してみました。
ECS初心者向けの記事を何本か書いていますので、どれか参考になれば幸いです。
#Blue/Greenデプロイ
Blue/Greenデプロイは、アプリケーションやマイクロサービスの古いバージョン(Blue環境)からテスト済の新しいバージョン(Green環境)に、ユーザートラフィックを徐々に転送するリリースモデルで、両バージョンが稼働中の状態で実施するものです。
BlueからGreenへのトラフィックの転送が完了すると、Blueはロールバックに備えてスタンバイさせるか、あるいはプロダクションからプルして更新し、次回の更新の際にテンプレートとして使用することができます。
ECSやFargateでBlue/Greenデプロイを実行するために、CodeDeployを使用します。
##実装
前回の記事で作成したCI/CDパイプラインに以下の手順でBlue/Greenデプロイを追加します。
- IAMロールの作成
- ELBリスナーの作成
- サービスの作成
- buildspec.ymlの作成
- appspec.yamlの作成
- taskdef.jsonの作成
- Buildの編集
- Deployの編集
- パイプラインの実行
###IAMロールの作成
CodeDeploy - ECS
というユースケースを選択します。
この中にはAWSCodeDeployRoleForECS
というポリシー(中身は以下)が含まれています。
###ELBリスナーの作成
次にELBでリスナーを作成します。
リスナーは設定したプロトコルとポートを使用して接続リクエストをチェックするプロセスです。
リスナーに対して定義したルールによって、ELBが登録済みターゲットにリクエストをルーティングする方法が決まります。
また、検証テストを使用するECSデプロイには2番目のリスナー(テストリスナー)が必要です。
このリスナーは、更新されたアプリケーションにテストトラフィックを提供するために置き換えタスクセットで使用されます。
検証テストは、テストトラフィックに対して実行されます。
###サービスの作成
ECSクラスターecs-service
に新しくサービスを作成します。
タスク定義やクラスターを選択して、サービス名を設定します。
デプロイメントタイプ、デプロイメント設定、CodeDeployのサービスロールをそれぞれ選択します。
ELBの設定で、プロダクションリスナーポートやテストリスナーポートを選択します。
以上の設定でサービスを作成します。
ELBのリスナーの中身をみてみると、ターゲットグループが正しく設定されています。
また、CodeDeployを開くと作成したアプリケーションの中身も確認できます。
###buildspec.ymlの修正
artifactsの記述を修正します。
version: 0.2
phases:
pre_build:
commands:
- echo Logging in to Amazon ECR...
- aws --version
- echo $AWS_DEFAULT_REGION
- $(aws ecr get-login --region $AWS_DEFAULT_REGION --no-include-email)
- REPOSITORY_URI=<<account-id>>.dkr.ecr.ap-northeast-1.amazonaws.com/ecr-simplehttp
- 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`
- docker push $REPOSITORY_URI:latest
- docker push $REPOSITORY_URI:$IMAGE_TAG
- printf '[{"name":"simplehttp-container","imageUri":"%s"}]' $REPOSITORY_URI:$IMAGE_TAG > imagedefinitions.json
- printf '{"ImageURI":"%s"}' $REPOSITORY_URI:$IMAGE_TAG > imageDetail.json
artifacts:
files:
- 'image*.json'
- 'appspec.yaml'
- 'taskdef.json'
secondary-artifacts:
DefinitionArtifact:
files:
- appspec.yaml
- taskdef.json
ImageArtifact:
files:
- imageDetail.json
###appspec.yamlの作成
ルートディレクトリに新しくAppSpecファイルappspec.yaml
を作成します。
AppSpecファイルでは、ECSサービスの名前と、新しいタスクセットにトラフィックを送信するために使用されるコンテナ名とポートなどを指定します。
version: 0.0
Resources:
- TargetService:
Type: AWS::ECS::Service
Properties:
TaskDefinition: <TASK_DEFINITION>
LoadBalancerInfo:
ContainerName: "simplehttp-container"
ContainerPort: 8000
###taskdef.jsonの作成
ルートディレクトリにtaskdef.json
を作成し、タスク定義のJSONを貼り付けます。
imageの箇所を以下のように修正します。
"image": <IMAGE1_NAME>,
###Buildの編集
CodeDeployからBuildの出力アーティファクトにDefinitionArtifact
とImageArtifact
を追加します。
###Deployの編集
Deployについても修正します。
入力アーティファクトにDefinitionArtifact
とImageArtifact
を追加します。
その他にはCodeDeployアプリケーション名やデプロイグループの指定、DefinitionArtifactののファイル選択、ImageArtifactの選択などを行います。
###パイプラインの実行
パイプラインを実行すると、CodeDeployからトラフィック移行の進行状況を確認することができます。
トラフィックの移行が終わると置き換えタスクセットの方が100 %と表示されます。
#参考資料