Amazon ECSでサービスデプロイメントの一時停止と再開の制御機能がサポートされました
ECS Native Blue/Green Deploymentで本番トラフィックの再ルーティングのタイミングを自分で指定したい
皆さんはECS Native Blue/Green Deploymentでトラフィックの再ルーティングのタイミングを自分で指定したいなと思ったことはありますか? 私はあります。
本記事でECS Native Blue/Green DeploymentとはCodeDeployを使用しない、ECSの組み込みのBlue/Green Deploymentを指します。
以下記事で紹介しているようにECS Native Blue/Green Deploymentではトラフィックの再ルーティングまでの猶予時間を指定することはできませんでした。
実装しようとすると、開発者側でデプロイライフサイクルフックLambda関数を用意する必要がありました。中々に手間です。加えて、Lambda関数を何回もポーリングさせる挙動になるため、なんだかな... という気持ちにもなります。
さらに、マネジメントコンソールで直接再ルーティングのタイミングを指示することもできなかっため不便でありました。
今回、アップデートによりAmazon ECSでサービスデプロイメントの一時停止と再開の制御機能がサポートされました。
指定したライフサイクルステージに到達したタイミングでデプロイを一時停止してくれます。この時発行されたフックIDと次のアクションを付与することで、デプロイの再開 / ロールバックを行うことが可能です。
さらにEventBridgeにイベントも発行されます。
こちらの機能を用いることによって、先ほどの辛みが一気に解消されることになります。
早速使ってみました。
いきなりまとめ
- Amazon ECSでサービスデプロイメントの一時停止と再開の制御機能がサポートされた
- ECS Native Blue/Green Deploymentでデプロイライフサイクルフック用のLambda関数を用意することなく、指定したライフサイクルステージでデプロイを一時停止できるようになった
- 以下のいずれかの方法で
ContinueServiceDeploymentAPIを呼び出すことで、デプロイの継続 / ロールバックを指示する- マネジメントコンソールから直接
続行/ロールバックを選択 aws ecs continue-service-deploymentコマンドの実行
- マネジメントコンソールから直接
- 一時停止フックを設定できるライフサイクルステージは以下の6つ
RECONCILE_SERVICEPRE_SCALE_UPPOST_SCALE_UPPOST_TEST_TRAFFIC_SHIFTPRE_PRODUCTION_TRAFFIC_SHIFTPOST_PRODUCTION_TRAFFIC_SHIFT
- タイムアウトは1分単位で最大20,160分(14日)まで指定可能
- Lambdaフックの最大1日から大幅に拡張
- タイムアウト時のアクションとして
CONTINUE/ROLLBACKを選択可能
- 2026/5/20現在、Q Developer in chat applicationsは
ecs continue-service-deploymentをサポートしていないため、Slackのカスタムアクションボタンからは実行できない - ECSのデプロイ中に人による承認を挟みたい場合は、今後は一時停止フックを使用するのが第一選択肢になりそう
一時停止フックの仕組み
一時停止フックの仕組みは以下AWS公式ドキュメントにまとまっています。
先述のとおり、デプロイ時に指定したライフサイクルステージに到達したタイミングで、デプロイを停止してくれます。
ContinueServiceDeploymentを用いてフックIDと次のアクションを指定してコントロールする動きになります。
フックIDはEventBridgeに発行されるイベントやDescribeServiceDeploymentsから確認することができます。
{
"version": "0",
"id": "a1b2c3d4-5678-90ab-cdef-EXAMPLE11111",
"detail-type": "ECS Hook State Change",
"source": "aws.ecs",
"account": "123456789012",
"time": "2024-01-15T10:00:00Z",
"region": "us-west-2",
"detail": {
"eventType": "INFO",
"eventName": "HOOK_AWAITING_ACTION",
"hookId": "ecs-pause-e7tK9G_WRJqNF_EOMjztDXfKenlJuEUVjsNStf4WLKw",
"hookType": "PAUSE",
"expiresAt": "2024-01-15T12:00:00Z",
"lifecycleStage": "POST_TEST_TRAFFIC_SHIFT",
"clusterArn": "arn:aws:ecs:us-west-2:123456789012:cluster/my-cluster",
"serviceArn": "arn:aws:ecs:us-west-2:123456789012:service/my-cluster/my-service",
"serviceDeploymentArn": "arn:aws:ecs:us-west-2:123456789012:service-deployment/my-cluster/my-service/EZe5RNVLH6PPzHXINuP28",
"updatedAt": "2024-01-15T10:00:00Z"
}
}
{
"serviceDeployments": [
{
"lifecycleHookDetails": [
{
"hookId": "ecs-pause-e7tK9G_WRJqNF_EOMjztDXfKenlJuEUVjsNStf4WLKw",
"targetType": "PAUSE",
"status": "AWAITING_ACTION",
"expiresAt": "2024-01-15T12:00:00Z",
"timeoutAction": "ROLLBACK"
}
]
}
]
}
通知という観点でいうと基本的にはEventBridge Ruleを使うことになるかなと思います。
EventBridgeに発行されるイベントのイベント名(eventName)は以下の通りです。
| イベント名 | 説明 |
|---|---|
HOOK_IN_PROGRESS |
一時停止フック処理開始 |
HOOK_AWAITING_ACTION |
一時停止フックは ContinueServiceDeploymentの実行待ち |
HOOK_SUCCEEDED |
一時停止フックは正常に完了 ( CONTINUEで ContinueServiceDeploymentを実行)。 |
HOOK_FAILED |
一時停止フックは正常に完了 ( ROLLBACKで ContinueServiceDeploymentを実行)。 |
HOOK_TIMED_OUT |
ContinueServiceDeploymentが呼び出される前にタイムアウトが発生 |
一時停止フックの設定は簡単です。以下のようにデプロイライフサイクルフックにフックを一時停止という項目が生えて来ているので、そこに以下を指定する形です。
- ライフサイクルステージ
- タイムアウト
- タイムアウトアクション

指定できるライフサイクルステージは以下です。
Lambdaフックと一時停止フックでそれぞれ使用できるイベントの一覧は以下の通りです。
| Lifecycle stage | Lambda hooks | Pause hooks |
|---|---|---|
RECONCILE_SERVICE |
Yes | Yes |
PRE_SCALE_UP |
Yes | Yes |
POST_SCALE_UP |
Yes | Yes |
TEST_TRAFFIC_SHIFT |
Yes | No |
POST_TEST_TRAFFIC_SHIFT |
Yes | Yes |
PRE_PRODUCTION_TRAFFIC_SHIFT |
Yes | Yes |
PRODUCTION_TRAFFIC_SHIFT |
Yes | No |
POST_PRODUCTION_TRAFFIC_SHIFT |
Yes | Yes |
抜粋 : Lifecycle hooks for Amazon ECS service deployments - Amazon Elastic Container Service
以前はPRE_PRODUCTION_TRAFFIC_SHIFTというライフサイクルステージは存在していなかったので、今回のアップデートに合わせて追加されたようです。
PRE_PRODUCTION_TRAFFIC_SHIFTは線形やカナリアデプロイの場合は都度呼び出されるようです。
For linear and canary deployments, Lambda hooks configured at PRODUCTION_TRAFFIC_SHIFT or PRE_PRODUCTION_TRAFFIC_SHIFT are invoked at each traffic shift step.
Lambda hooks for Amazon ECS service deployments - Amazon Elastic Container Service
For linear and canary deployments, pause hooks configured at PRE_PRODUCTION_TRAFFIC_SHIFT are invoked at each traffic shift step. Each invocation generates a unique hookId, and you must call ContinueServiceDeployment for each one.
For example, a linear deployment with 5 traffic shift steps and a pause hook at PRE_PRODUCTION_TRAFFIC_SHIFT pauses 5 times - once before each step. Each pause requires a separate call to ContinueServiceDeployment with the corresponding hookId.
Pause hooks for Amazon ECS service deployments - Amazon Elastic Container Service
都度中断を挟みたいのであればPRE_PRODUCTION_TRAFFIC_SHIFTを使うことになりそうですが、本番トラフィックのルーティング前に一度承認を挟みたいという用途であればPOST_TEST_TRAFFIC_SHIFTを採用することになりそうです。
また、一時停止フックのタイムアウトは1分単位で最大20,160分(14日)まで指定可能です。Lambdaフックの場合は最大1日までだったのでありがたいですね。
指定したタイムアウトを超過した場合は、指定したタイムアクションにしたがってロールバック / 継続を行います。
やってみた
検証環境
実際に試してみます。
検証環境は以下のとおりです。

以下記事のものをベースにしています。
ログはAWS FireLens (AWS for Fluent Bit)を使用して、エラーログはCloudWatch Logs、全てのログをData Firehose経由でS3バケットに出力させています。

通知やカスタムアクションボタン周りの仕組みを図示すると以下のようになります。
通知のフローは以下のとおりです。

Step Functionsでは以下のような処理をしています。
本来であれば初回デプロイ時は承認を挟まずにデプロイをしたいところです。しかし、Step Functionでは2026/5/20現在はContinueServiceDeploymentをサポートしていませんでした。そのため、Step Functionsの処理の中でサービスデプロイの状態を見て、初回デプロイ時はContinueServiceDeploymentでデプロイを継続するといったことはできませんでした。
リソースは全てAWS CDKでデプロイしています。使用しているコードは以下のとおりです。
初回デプロイ
cdk deployで初回デプロイを行います。
デプロイを開始してしばらくすると以下の通知が指定したSlackチャンネルに通知が飛んできました。

URLをクリックすると、サービスデプロイの詳細を確認することができます。サービスのデプロイは一時停止フック ecs-pause-xrkqfL99Sem2S5poPtD78IuIDa-rXkj9vSMCk2xWx6w によって一時停止されています。アクションが実行されない場合、デプロイは 2026/5/21 17:32:45 に自動的にロールバックされますとデプロイアクションを待機していることが分かりますね。

このecs-pause-xrkqfL99Sem2S5poPtD78IuIDa-rXkj9vSMCk2xWx6wがフックIDです。
Take actionをクリックすると、続行かロールバックを選択できるようです。過去はマネジメントコンソールでコントロールできなかったので最高にアツいです。

今回はSlack通知内のカスタムボタンから操作してみます。再ルーティングボタンを押下すると以下のように実行するコマンドの確認ウィンドウが開きます。

Runをクリックします。

はい、I can’t answer that question. For an enhanced natural language experience using Amazon Q, visit Enabling Amazon Q Developer in Slack in the Amazon Q Developer in Slack User Guide.と本来コマンドが受け付けられたレスポンスを期待していたところですが、質問に回答できないというレスポンスが返ってきてしまいました。
カスタムボタンではなく、Amazon Q Developer in chat applications(以降、Q Dev chat)のアプリケーションをメンションする形で指示してみます。

結果は変わりません。ということでQ Dev chatではContinueServiceDeploymentをサポートしてくていなさそうです。残念です。
手元の端末で同様のコマンドを叩いてみます。
> aws ecs continue-service-deployment \
--service-deployment-arn arn:aws:ecs:us-east-1:<AWSアカウントID>:service-deployment/EcsNativeBlueGreenStack-EcsConstructCluster14AE103B-YYGmVwRgPNVq/EcsNativeBlueGreenStack-EcsConstructServiceC04CE253-1kSuWyKVrhqc/F__6AFivDyvRHXj-mEde2 \
--hook-id ecs-pause-xrkqfL99Sem2S5poPtD78IuIDa-rXkj9vSMCk2xWx6w \
--action CONTINUE \
--region us-east-1
{
"serviceDeploymentArn": "arn:aws:ecs:us-east-1:<AWSアカウントID>:service-deployment/EcsNativeBlueGreenStack-EcsConstructCluster14AE103B-YYGmVwRgPNVq/EcsNativeBlueGreenStack-EcsConstructServiceC04CE253-1kSuWyKVrhqc/F__6AFivDyvRHXj-mEde2"
}
こちらは正常に受け付けられました。
マネジメントコンソールを確認すると、デプロイが進行中となりました。

しばらくするとデプロイが成功しました。

2回目のデプロイ
index.htmlを変更して再度デプロイしてみます。
cdk deployをしてしばらくをすると以下の通知がきました。

このタイミングで本番リスナーとテストリスナーにアクセスをします。
> curl EcsNat-AlbCo-heEpSVXyHHDZ-670410644.us-east-1.elb.amazonaws.com/
index.txt v1.0
> curl EcsNat-AlbCo-heEpSVXyHHDZ-670410644.us-east-1.elb.amazonaws.com:10080/
index.txt v1.1
テストリスナーのみレスポンスが変わりましたね。
今回はマネジメントコンソールからロールバックをしてみます。

確認をクリックすると、正常に受け付けられたようです。

そのまま待つとロールバックが開始されました。

さらに待つとロールバックが完了しました。

再度アクセスすると、本番リスナーとテストリスナーのレスポンスが同じものになりました。
> curl EcsNat-AlbCo-heEpSVXyHHDZ-670410644.us-east-1.elb.amazonaws.com/
index.txt v1.0
> curl EcsNat-AlbCo-heEpSVXyHHDZ-670410644.us-east-1.elb.amazonaws.com:10080/
index.txt v1.0
ECSのデプロイ中に人が介在する場合は一時停止フックを使用しよう
Amazon ECSでサービスデプロイメントの一時停止と再開の制御機能がサポートされたアップデートを紹介しました。
今後、ECSのデプロイ中に人が介在する場合は一時停止フックを使用することになるかなと思います。積極的に使っていきましょう。
この記事が誰かの助けになれば幸いです。
以上、クラウド事業本部 コンサルティング部の のんピ(@non____97)でした!







