Amazon Web Services ブログ

AWS CodeDeploy が Amazon ECS の線形デプロイと Canary デプロイをサポートするようになりました



AWS CodeDeploy は、Elastic Container Service (Amazon ECS) のブルー/グリーンデプロイサポートを拡張し、AWS Fargate または Amazon Compute Cloud (Amazon EC2) でホストされるアプリケーションの Canary および線形デプロイを含めます。

ブルー/グリーンデプロイは、アプリケーションバージョンの変更による中断を最小限に抑えるために、AWS CodeDeploy が提供する安全なデプロイ戦略です。これは、グリーンと呼ばれる新しいアプリケーション環境と、ブルーと呼ばれるライブトラフィックを処理している現在のアプリケーションを作成することによって実現されます。これにより、ライブトラフィックがブルーからグリーンにルーティングされます。その後、ブルーのリソースがオフになる前に、グリーンの環境を監視およびテストするための一定期間が許可されます。

Amazon ECS のブルー/グリーンデプロイを最初に立ち上げた後、多くのお客様は、アプリケーションの更新によって一定期間にわたって変化するトラフィックの量を制御することに関心を示しました。  CodeDeploy を介した線形デプロイと Canary デプロイでは、新しいアプリケーションバージョンへのライブトラフィックの露出をトラフィック全体のパーセンテージに制限することで実現し、残りのトラフィックをルーティングする前にパフォーマンスを監視します。Amazon CloudWatch アラームを設定することもできます。問題が検出された場合、CodeDeploy は自動的にトラフィックルーティングを元のバージョンに戻します。  CodeDeploy は、ALB の加重ターゲットグループを使用してこれを実現します。

この記事では、Fargate でホストされる Amazon ECS の新しい線形デプロイと Canary デプロイを構成する方法を示します。

今日は次の内容を行います。

  1. CodeDeploy をコントローラとして ECS サービスを作成する
  2. 新しい線形構成を使用して新しいデプロイグループを作成する
  3. 1 分ごとにトラフィックの 10% をルーティングするためのプリセット線形デプロイ構成を使用して、CodeDeploy ブルー/グリーンデプロイをトリガーします。

現在、次の事前定義された線形および Canary デプロイ構成をご利用いただけます。  また、今日からカスタム定義の線形デプロイと Canary デプロイを作成することもできます。

デプロイ設定 説明
CodeDeployDefault.ECSCanary10Percent5Minutes 最初の増分でトラフィックの 10% をシフトします。残りの 90% は 5 分後にデプロイされます。
CodeDeployDefault.ECSCanary10Percent15Minutes 最初の増分でトラフィックの 10% をシフトします。残りの 90% は 15 分後にデプロイされます。
CodeDeployDefault.ECSLinear10PercentEvery1Minutes すべてのトラフィックがシフトされるまで、トラフィックの 10% を毎分シフトします。
CodeDeployDefault.ECSLinear10PercentEvery3Minutes すべてのトラフィックがシフトされるまで、トラフィックの 10% を 3 分ごとにシフトします。

それでは、始めましょう。

仮定

  • このブログ内で参照されるすべてのアクティビティとリソースは、AWS アカウント内や同じリージョン内で実行および作成されます。
  • Docker がローカル開発システムにインストールされます。こちらから Docker を入手
  • これを使用してコンテナイメージを Amazon ECR にプッシュするため、最新の AWS CLI がインストールされています。

実装

手順 1: このブログをサポートする GitHub リポジトリを取得する

github.com/aws-samples/aws-codedeploy-linear-canary-deployments-blog で GitHub リポジトリをプルします。このリポジトリには、この記事用に構築する CloudFormation テンプレートとサンプル Docker コンテナが含まれています。  以下はマスターブランチをマシンにプルします。

git clone git@github.com:aws-samples/aws-codedeploy-linear-canary-deployments-blog.git

手順 1: Amazon ECR リポジトリを作成する

コンテナの 2 つのバージョンを作成して、線形デプロイを使用したバージョン間の更新を説明できるように、少し前もってハウスキーピングを行います。  create-repository コマンドを使用してリポジトリを作成します。

aws ecr create-repository \
--repository-name ecs-sample-app \
--region us-east-2

出力には、リポジトリの URI が次の形式で含まれます。

111111111111.dkr.ecr.us-east-2.amazonaws.com/ecs-sample-app

手順 3: ブルー/グリーンのコンテナイメージを構築して Amazon ECR リポジトリにプッシュする

プルリポジトリを使用して、Docker ディレクトリに移動し、次のコマンドを実行し、必要に応じてアカウント ID を置き換えます。

docker build -t ecs-sample-app .
docker tag ecs-sample-app:latest 111111111111.dkr.ecr.us-east-2.amazonaws.com/ecs-sample-app:v1
aws ecr --region us-east-2 get-login --no-include-email --registry-ids 111111111111| bash
docker push 111111111111.dkr.ecr.us-east-2.amazonaws.com/ecs-sample-app:v1

2 番目のイメージバージョン (v2) でブランチを変更し、上記と同じタスクを実行できるようになりました。  次の git コマンドを使用して、リポジトリの v2 ブランチをチェックアウトします。

git fetch & git checkout v2

上記と同じアクションを実行して、ローカルコンテナを再構築し、コンテナにタグを付け (v1 を v2 に切り替え)、それらをリポジトリにプッシュします。

これで、リポジトリ内のコンテナを確認できます。  イメージ URI にご注意ください。

ECR リポジトリのリスト

画像 1: ECR リポジトリのリスト

手順 4: AWS CloudFormation を使用してインフラストラクチャを作成する

次の CloudFormation (図の下) を起動して、VPC とサポートリソースを含む環境を立ち上げます。  以下は、デプロイされる VPC アーキテクチャの図です。

VPC アーキテクチャ図

画像 2: VPCアーキテクチャ図

CloudFormation マネジメントコンソールを開き、スタックの作成プルダウンメニュー内の新しいリソースを使用 (標準)を選択します。念のため、ここまでの手順で利用している AWS リージョンが選択されていることを確認してください。次の画面ではテンプレートファイルのアップロードラジオボタンを選択し、事前にクローン済みの Git リポジトリ内のcloudformation/linear_ecs.yamlファイルを指定します。

ImageUrl パラメータの値を指定し、他のすべての値はデフォルトのままにします。  この値は、手順 3 の最初のコンテナイメージ (v1) URI に対応します。  デフォルトを承認して次の画面に進み、IAM 承認を行ってスタックを作成します。 スタックがデプロイされたら (CREATE_COMPLETE)、出力セクションに移動し、参照用に出力を収集します。  今後はこれらを使用します。  出力は次のようになります。

CloudFormation 出力リスト

画像 3: CloudFormation 出力リスト

手順 5: ブルー/グリーンデプロイ用の Amazon ECS サービスを作成する

基となるインフラストラクチャを手に入れたので、CodeDeploy からのブルー/グリーンデプロイサポートを使用して Amazon ECS サービスを作成する準備ができました。  CLI を使用して作成します。

プルされた git リポジトリ内で、json_files ディレクトリに移動し、create_service.json を編集して、次の値を CloudFormation 出力の対応する値に置き換えます。

上記の出力が与えられた場合に、置き換えられた例のバージョンは次のとおりです。

{
	"cluster": "ecs-blog-ECSCluster-1BC08Z8YA1A5X",
	"serviceName": "ecs-blog-svc",
	"taskDefinition": "arn:aws:ecs:us-east-2:111111111111:task-definition/ecs-blog-svc:1",
	"loadBalancers": [
		{
			"targetGroupArn": "arn:aws:elasticloadbalancing:us-east-2:111111111111:targetgroup/ecs-b-Targe-NP1KC1KYAEK1/01cf50be3fa1524c",
			"containerName": "ecs-blog-svc",
			"containerPort": 80
		}
	],
	"launchType": "FARGATE",
	"schedulingStrategy": "REPLICA",
	"deploymentController": {
		"type": "CODE_DEPLOY"
	},
	"platformVersion": "LATEST",
	"networkConfiguration": {
		"awsvpcConfiguration": {
			"assignPublicIp": "ENABLED",
			"securityGroups": ["sg-08fdb4f721268b4f0"],
			"subnets": ["subnet-0d348d95b7121ae37", "subnet-0075725bb118146dd"]
		}
	},
	"desiredCount": 2
}

出力値を置き換えたら、リポジトリの json_files ディレクトリ内から次を実行します。

aws ecs create-service \
--cli-input-json file://create_service.json \
--region us-east-2

出力には、次の形式のサービスの ARN が含まれます。

arn:aws:ecs:us-east-2:111111111111:service/ecs-blog-svc

手順 6: CodeDeploy リソースを作成する

次の手順を使用して、CodeDeploy アプリケーションと CodeDeploy デプロイグループを作成します。

CodeDeploy リソースを作成する方法

  1. create-application コマンドを使用して CodeDeploy アプリケーションを作成し、ECS コンピューティングプラットフォームを指定します。
aws deploy create-application \
--application-name ecs-blog-app \
--compute-platform ECS \
--region us-east-2

出力には、次の形式のアプリケーション ID が含まれます。

{
	"applicationId": "09ac62f6-a64d-4ffe-a890-207c8af7494d"
}
  1. create-deployment-group コマンドを使用して、CodeDeploy デプロイグループを作成します。

プルされた git リポジトリ内で、json_file に移動し、code_deployment_group.json を編集して、次の値を CloudFormation 出力の対応する値に置き換えます。

上記の出力が与えられた場合に、置き換えられた例のバージョンは次のとおりです。

{
	"applicationName": "ecs-blog-app",
	"deploymentGroupName": "ecs-blog-app-dg",
	"deploymentConfigName": "CodeDeployDefault.ECSLinear10PercentEvery1Minutes",
	"serviceRoleArn": "arn:aws:iam::111111111111:role/ecs-blog-EcsRoleForCodeDeploy-176BC3DEKYQ0E",
	"deploymentStyle": {
		"deploymentType": "BLUE_GREEN",
		"deploymentOption": "WITH_TRAFFIC_CONTROL"
	},
	"blueGreenDeploymentConfiguration": {
		"terminateBlueInstancesOnDeploymentSuccess": {
			"action": "TERMINATE",
			"terminationWaitTimeInMinutes": 5
		},
		"deploymentReadyOption": {
			"actionOnTimeout": "CONTINUE_DEPLOYMENT"
		}
	},
	"loadBalancerInfo": {
		"targetGroupPairInfoList": [{
			"targetGroups": [{
					"name": "ecs-b-Targe-NP1KC1KYAEK1"
				},
				{
					"name": "ecs-b-Targe-1PFVGY72CEI09"
				}
			],
			"prodTrafficRoute": {
				"listenerArns": [
					"arn:aws:elasticloadbalancing:us-east-2:111111111111:listener/app/ecs-b-Publi-14GAO5UFNWDMZ/24e50a3e4a4b205c/8f817f85ec2fe816"
				]
			},
			"testTrafficRoute": {
				"listenerArns": [
					"arn:aws:elasticloadbalancing:us-east-2:111111111111:listener/app/ecs-b-Publi-14GAO5UFNWDMZ/24e50a3e4a4b205c/b511569563eb2261"
				]
			}
		}]
	},
	"ecsServices": [{
		"serviceName": "ecs-blog-svc",
		"clusterName": "ecs-blog-ECSCluster-1BC08Z8YA1A5X"
	}]
}

CodeDeploy デプロイグループを作成します。

aws deploy create-deployment-group \
--cli-input-json file://code_deployment_group.json \
--region us-east-2

出力には、次の形式のデプロイグループ ID が含まれます。

{
	"deploymentGroupId": "3c7d3ddf-0c8e-463e-8914-526496f0cad5"
}

これで、AWS Fargate で実行されている Amazon ECS サービスの線形デプロイ構成をセットアップできました。  線形デプロイを実行する時間です。  Amazon ECS サービスと CodeDeploy 側で作成したものを見てみましょう。

ECS クラスターコンソールに移動します。  こちらでクラスター、この場合は ecs-blog-ECSCluster-11U2U784RFRG1 をクリックします。  CLI で作成したサービスを確認します。

ECS クラスターコンソール

画像 4: ECS クラスターコンソール

CodeDeploy アプリケーションコンソールに移動します。  こちらから、作成したアプリケーションとデプロイグループを確認できます。  アプリケーション ecs-blog-app をクリックしてから、デプロイグループ ecs-blog-app-dg に進みます。  デプロイグループの構成を確認できます。デプロイ構成にご注意ください。

CodeDeploy デプロイグループコンソール

画像 5: CodeDeploy デプロイグループコンソール

Application Load Balancer の ExternalURL にアクセスして、Amazon ECS で実行されているコンテナを見てみましょう。  これは、手順 4 の出力からコピーできます。  その URL に移動すると、NGINX ホームページにブルーの情報セクションが表示されます。

NGINX ランディングページ

画像 6: NGINX ランディングページ

作成したデプロイ構成を実行してみましょう。  これを行うには、使用するタスク定義のリビジョンを作成し、ECS サービスに新しいタスクセットを使用するよう指示する必要があります。  手順 3 でメモした 2 番目のコンテナバージョン (v2) URI を使用して行います。

手順 7: グリーンのコンテナイメージを使用してタスク定義のリビジョンを更新する

ECS タスク定義コンソールに移動します。  ここでは、タスク定義 ecs-blog-svc の横にあるチェックボックスをオンにして、[新しいリビジョンを作成] ボタンをクリックします。  これにより、新しいリビジョンを作成するための編集画面が表示されます。  画面のコンテナ定義セクションに移動し、コンテナ名をクリックしてコンテナ定義を更新します。

ECS タスク定義 - コンテナ定義の編集

画像 7: ECS タスク定義 – コンテナ定義の編集

これにより、コンテナページを編集できます。画像を手順 3 のセカンダリイメージ (v2) URI に置き換えるだけで充分です。

ECS タスク定義 - コンテナを編集

画像 8: ECS タスク定義 – コンテナを編集

[更新]、[作成] の順にクリックします。  新しいリビジョンを作成しました。

タスク定義コンテナを更新しました

画像 9: タスク定義コンテナを更新しました

手順 8: ECS サービスを更新して新しいタスク定義リビジョンを使用し、CodeDeploy 線形デプロイをトリガーする

ECS クラスターコンソールに移動します。  こちらでクラスター、この場合は ecs-blog-ECSCluster-1BC08Z8YA1A5X をクリックします。  サービスの横にあるチェックボックス ecs-blog-scv をクリックし、[更新] ボタンをクリックします。

ECS クラスターコンソール - サービス

画像 10: ECS クラスターコンソール – サービス

サービスの編集画面で、[タスク定義] 領域の下にある最後のリビジョン (2) を選択します。

サービス更新タスク定義のリビジョン

画像 11: サービス更新タスク定義のリビジョン

最後のウィザード画面までデフォルトを承認し、[サービスを更新] をクリックして、次のすべての手順を実行して [次の手順] をクリックします。

更新されたサービス

画像 12: 更新されたサービス

手順 9: 線形デプロイを観察する

CodeDeploy コンソールに移動します。

最初に、デプロイにより置換タスクセットが作成されます。  元のタスクセットに対して 100% のトラフィックシフトプロセスを右側に表示できます。

シフトが進むにつれて、パーセンテージのシフトを観察できます。

別のウィンドウで Application Load Balancer の外部 URL に移動します。  変更を確認し、更新を有効にすると、NGINX ホームの情報ボックスがブルーからグリーンに変わります。

移行期間が完了すると、デプロイは元のタスクセットを終了します。  この待機期間は設定できます。  この場合は 5 分に設定しました。デフォルト値は 60 分です。

まとめ

この記事では、CodeDeploy を使用したブルー/グリーンの線形デプロイで Fargate ECS サービスを作成する方法を示しました。 この例を使用して、線形/Canary デプロイ構成の他のバリエーションをお試しになって、ニーズに合わせてカスタマイズしてください。

CodePipeline と ECR の継続的デリバリーパイプラインを使用してこのエンドツーエンドを自動化する方法については、このブログ記事をご覧ください。ソースとして Amazon ECR を使用したコンテナイメージの継続的デリバリーパイプラインの構築に関する内容です。

この記事の情報が、お客様のアプリケーションに実装して開始するのに役立つことを願っています。