🍡

ECSのBlue/GreenデプロイでGreen環境のタスク情報を取得したい

に公開

これは何?

タイトルのままですが、ECSのBlue/GreenデプロイにおいてGreen環境のタスク情報を取得する方法について記載します。同じ要領でBlue環境にも適用可能かと思います。

今回はECSのデプロイ通知のためにGreen環境のタスク情報が必要でした。他にもやり方はあると思いますが、誰かの参考になれば幸いです。

要件

  • Blue/GreenデプロイにおけるGreen環境がリリースされたタイミングでSlack通知すること
    • ECSにどのバージョンがデプロイされたのか分かること
      • バージョン:GitHubでつけたリリースタグのバージョン
    • デプロイ状況が分かること
      • 成功 or 失敗 or キャンセル
    • デプロイ対象が記載されていること
      • ECSクラスター、ECSサービス

構成概要

今回の設計ではざっくりと以下のような構成になっています。

詳細

GitHub Actions ~ CodeDeployの起動までは一般的な構成なので記載しません。
詳細は以下について記載します。

  • CodeDeployのDeployGroupのトリガーを利用してGreen環境のデプロイ時にイベント発火
  • LambdaにてECSサービスのタスクセットの情報を利用してGreen環境のタスク情報の取得

CodeDeployのDeployGroupのトリガーを利用してGreen環境のデプロイ時にイベント発火

CodeDeployアプリケーションではAmazon SNSの通知ルールを簡単に作成することができます。
https://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/monitoring-sns-event-notifications.html

しかし、これではデプロイ成功時の通知がCodeDeployのステップが全て完了したタイミングで来ることになってしまします。例えば、Blue環境を〇〇分維持するという設計になっている場合、実際のGreen環境のデプロイ(リリース)のタイミングとズレが生じてしまいます。もし、このズレが許容できるのであれば、素直に備え付けの通知ルールを作成するという方法で良いと思います。

今回の要件ではこのズレが許容できないため、Green環境がリリースされたタイミングで通知が来るように工夫しました。

その方法は題目の通りで、CodeDeployのデプロイグループのトリガー設定を使うことにしました。
https://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/deployment-groups-configure-advanced-options.html

先ほどと同様にデプロイグループでもAmazon SNSの通知トリガーを設定できます。先ほどと違う点は、CodeDeployのステップ毎に細かくトリガーの設定をすることができることです。

具体では以下のような選択肢があります。

  • DeploymentStart
  • DeploymentSuccess
  • DeploymentFailure
  • DeploymentStop
  • DeploymentRollback
  • DeploymentReady (Blue/Green デプロイで置き換え先インスタンスにのみ適用します)
  • InstanceStart
  • InstanceSuccess
  • InstanceFailure
  • InstanceReady (Blue/Green デプロイで置き換え先インスタンスにのみ適用します)

https://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/monitoring-sns-event-notifications-create-trigger.html

今回は、Green環境のリリースのタイミングを狙いたいのでInstanceSuccessを選択します。
あと、通知要件に合わせてデプロイの失敗や停止も補足する必要があるのでDeploymentFailureDeploymentStopも選択しておきます。
あとはSNSトピックを選択してトリガー作成をしたら、SNSの通知トリガーの設定は完了です。

LambdaにてECSサービスのタスクセットの情報を利用してGreen環境のタスク情報の取得

今回はBlue/Greenデプロイを利用しているので、ECSサービス上にBlue環境、Green環境が同時に存在します。これらをECSタスクという観点で見る(例えばListTasksなど)と差分がないため、どちらがBlue、Greenか判別ができません。

そのため今回はECSサービスのタスクセットという概念を使って判別をするようにしました。
CodeDeployのBlue/Greenデプロイにおいての詳細は以下に分かりやすくまとまっています。
https://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/deployment-steps-ecs.html#deployment-steps-what-happens

上記のリンクにも記載してある通り、Blue環境、Green環境それぞれ用のタスクセットが用意されます。以下のような差分があるため、この情報を持ってくれば判別することができます。
環境名がそのまま書いてあるのでtaskSetLabelを使うことにしました。

Task setのプロパティ Blue環境 Green環境
DeploymentTarget.ECSTarget.ECSTaskSet.status PRIMARY ACTIVE
DeploymentTarget.ECSTarget.ECSTaskSet.taskSetLabel BLUE GREEN

https://docs.aws.amazon.com/codedeploy/latest/APIReference/API_GetDeploymentTarget.html#API_GetDeploymentTarget_ResponseSyntax
https://docs.aws.amazon.com/codedeploy/latest/APIReference/API_ECSTaskSet.html

Lambda関数の流れは以下です。

  1. SNSトピックのイベント情報からCodeDeployの情報を取得
  2. CodeDeployのGetDeploymentTarget APIを使って、ECSサービスのタスクセット情報を取得
  3. ECSのDescribeTaskSets APIを使って、Green環境のタスクセットの詳細情報を取得
  4. ECSのDescribeTaskDefinition APIを使って、タスク定義詳細を取得
  5. 必要な情報をまとめて、Slack APIを叩く

また、LambdaではPythonランタイムを利用しているため、boto3の以下のAPIを利用しました。
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/codedeploy/client/get_deployment_target.html
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ecs/client/describe_task_sets.html
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ecs/client/describe_task_definition.html

ECSのBlue/Green環境の判別については以上です。

まとめ

  • CodeDeployアプリケーションに備え付けの通知トリガーでは、リリース完了時のみイベント発火が可能
    • 細かいイベント発火を調整する場合はCodeDeployデプロイグループのトリガーを利用すると良い
      • 他にも方法はありそう
  • ECSのBlue/GreenデプロイではBlue環境、Green環境を区別するためにECSサービスのタスクセットの情報が使える

補足

CodeDeployフックについて

今回Green環境のリリース時の通知処理に、CodeDeployフック(AfterAllowTraffic)は利用しませんでした。

理由は、(これはあくまで個人の意見ですが、)フックを使うとCodeDeployからのSlack通知の導線が追いづらくなると思ったからです。一方、デプロイグループのトリガーはAWSコンソールからでもCodeDeployからSNSトピックをトリガーしていることが把握しやすかと思います。

フックの場合はSNSトピックを介さずにLambda関数を呼べるのでシンプルな構成になるかもしれません。

AWSのサービスは便利なので色々組み合わせれば、他の方法でも実現ができそうですが、シンプルに保守しやすい状態にしておくという思想の下、今回の意思決定をしました。

Lambda(実行ロール)に付与するIAMポリシー

デフォルトで作成されるIAMロールにはCloudWatch Logs関連の許可ポリシーのみ付与されるので、処理の中で叩くAPIの実行権限を付与してあげる必要があります。

具体では以下のアクションを許可する必要があります。

  • ecs:DescribeTaskDefinition
  • ecs:DescribeTaskSets
  • codedeploy:GetDeploymentTarget

最小権限の原則に基づいて対象Resourceを指定していたのですが、ecs:DescribeTaskDefinitionのアクションだけ公式ドキュメントを見ても指定するリソースタイプなどの情報がなくどのように記述するか迷いました。

色々試してもうんともすんともなので、最終的に以下のように"*"指定にして動くようにしました。(合ってる?!と不安になりつつ)
https://docs.aws.amazon.com/ja_jp/service-authorization/latest/reference/list_amazonelasticcontainerservice.html#amazonelasticcontainerservice-actions-as-permissions

...
{
    "Effect": "Allow",
    "Action": [
        "ecs:DescribeTaskDefinition"
    ],
    "Resource": [
        "*"
    ]
},
...

動くとはいえ、これでいいのかと少しモヤモヤしていましが、別のタイミングでたまたまGUI(?)でIAMポリシーの設定を試していたら、「選択されたアクションは、ワイルドカードのみをサポートします」と表示され"*"指定で問題ないことが判明しました。

最小権限の原則。。。
あと、できればJSONエディタの方でもその辺り警告を出してほしい。

ECSがネイティブでBlue/Greenデプロイをサポートしました

先日からCodeDeployなしでECSだけでBlue/Greenデプロイができるようになったようです。
Service Connectを利用していてもBlue/Greenデプロイができるのは嬉しいですね。
https://aws.amazon.com/jp/about-aws/whats-new/2025/07/amazon-ecs-built-in-blue-green-deployments/

以下の記事がとても参考になりました。
https://zenn.dev/cadp/articles/ecs-builtin-blue-green

今後はCodeDeployからの移行も検討してみようと思います。

CodeDeployとECSのBlue/Greenデプロイメントの差分は以下にまとまっています。
https://docs.aws.amazon.com/AmazonECS/latest/developerguide/migrate-codedeploy-to-ecs-bluegreen.html#implementation-differences

CodeDeployではタスクセットを使う、ECSではサービスリビジョンを使う、と書いてるので、今回記事に記載した方法は使えなくなりそうです。

CodeDeploy uses a task set, whereas Amazon ECS uses a service revision. Amazon ECS task sets are an older construct which have been superseded by Amazon ECS service revisions and deployments. The latter offer greater visibility into the deployment process, as well as the service deployment and service revision history.

Omiai Tech Blog

Discussion