Amazon ECS のネイティブ Blue/Green デプロイは、CodeDeploy を使わずに ECS のサービス設定だけで新旧バージョンを並走させ、本番トラフィックを切り替える機能です。2025年7月17日に提供が始まり、その後 2025年10月に LINEAR と CANARY、2026年5月に手動承認用の PAUSE フックが加わりました。この記事では、ALB のリスナールールと IAM ロールの準備、create-service と Terraform の設定例、8つのライフサイクルステージ、ロールバックの方法、CodeDeploy からの移行手順を 2026年10月2日時点の AWS 公式ドキュメントに沿って整理します。
まとめ:ECSネイティブBlue/Greenの要点と採用判断
- 設定は
deploymentController.type=ECSとdeploymentConfiguration.strategy=BLUE_GREENの2つが起点です。デプロイは CodeDeploy のCreateDeploymentではなく ECS のUpdateServiceで始まります。 - ALB では、2つのターゲットグループを重み 1 対 0 で束ねたリスナールールを先に作り、そのルールの ARN と ELB 操作用 IAM ロールを
advancedConfigurationに渡します。 - ベイク時間(
bakeTimeInMinutes)は本番切り替え後に Blue を残しておく時間で、0〜1,440分です。CloudFormation で省略すると15分になります。この間は Blue が残っているため、切り戻しが速く済みます。 - 検証は Lambda フック(戻り値で成否を返す)と PAUSE フック(
ContinueServiceDeploymentを呼ぶまで止まる)で差し込みます。 - AWS は 2026年2月公開・同年3月更新のブログで、新規プロジェクトにはネイティブ方式を推奨しています。CodeDeploy 構成はそのまま使い続けられるため、移行は急がなくてかまいません。
- デプロイ中はタスクが最大2倍になります。EC2 起動タイプでキャパシティに余裕がないクラスターや、新旧で互換性のない DB 変更を伴うリリースには向きません。
ECSのデプロイ方式4種とネイティブBlue/Greenの位置づけ
ECS サービスのデプロイ方式は、デプロイコントローラー(ECS/CODE_DEPLOY/EXTERNAL)と、ECS コントローラーの中で選ぶ戦略(strategy)の組み合わせで決まります。ネイティブ Blue/Green は「コントローラーは ECS、戦略は BLUE_GREEN」という組み合わせです。従来の CodeDeploy 方式(コントローラー CODE_DEPLOY)とは別の仕組みです。
| strategy | 新旧の並走 | 本番トラフィックの移し方 | 切り戻し |
|---|---|---|---|
| ROLLING(既定) | 一部のみ | タスクを順次入れ替え | 旧タスクの再起動 |
| BLUE_GREEN | 全量 | 一括で100% | 重みを戻すだけ |
| LINEAR | 全量 | 等間隔で段階移行 | 重みを戻すだけ |
| CANARY | 全量 | 一部を先行し残りを一括 | 重みを戻すだけ |
ローリング更新の設定値はローリングアップデートの仕組みとKubernetes・ECSの設定値で、Blue/Green という手法そのものの考え方や Kubernetes での実装はブルーグリーンデプロイメントの仕組みと他方式との違いで扱っています。この記事は ECS 固有の設定と運用に絞ります。
2025年7月の提供開始から追加された機能
| 発表日 | 追加内容 |
|---|---|
| 2025-07-17 | BLUE_GREEN(ALB・NLB・Service Connect) |
| 2025-10-30 | LINEAR・CANARY(ALB・Service Connect) |
| 2026-02-04 | NLB で LINEAR・CANARY に対応 |
| 2026-05-19 | PAUSE フックと ContinueServiceDeployment API |
提供開始時の AWS News Blog には、機能自体に追加料金はかからず、デプロイ中に使うコンピューティングリソースの料金だけがかかると書かれています。2026年10月時点の公式ドキュメントでは、ロードバランサーも Service Connect も使わないヘッドレスサービスでも Blue/Green 戦略を指定できます。ただしその場合、ECS はタスクを入れ替えるだけで、トラフィックの切り替えは管理しません。
デプロイの流れとライフサイクルステージ
UpdateService でタスク定義を更新すると、ECS は新しいサービスリビジョン(Green)を起動し、次のステージを順に進めます。フックを置けるのは8ステージで、SCALE_UP・BAKE_TIME・CLEAN_UP は状態表示用です。
| ステージ | この時点の状態 | Lambda | PAUSE |
|---|---|---|---|
| RECONCILE_SERVICE | ACTIVE なリビジョンが複数あるときだけ発生 | ○ | ○ |
| PRE_SCALE_UP | Green 未起動・本番は Blue が100% | ○ | ○ |
| SCALE_UP | Green のタスクを起動中 | × | × |
| POST_SCALE_UP | Green 起動済み・トラフィックなし | ○ | ○ |
| TEST_TRAFFIC_SHIFT | テスト用トラフィックを Green へ移行中 | ○ | × |
| POST_TEST_TRAFFIC_SHIFT | テスト用トラフィックは Green が100% | ○ | ○ |
| PRE_PRODUCTION_TRAFFIC_SHIFT | 本番切り替えの直前 | ○ | ○ |
| PRODUCTION_TRAFFIC_SHIFT | 本番トラフィックを Green へ移行中 | ○ | × |
| POST_PRODUCTION_TRAFFIC_SHIFT | 本番の移行完了 | ○ | ○ |
| BAKE_TIME | Blue と Green が並走 | × | × |
| CLEAN_UP | Blue をタスク0まで縮小 | × | × |
時間の上限は4つあります。通常のライフサイクルステージは最大24時間で、超えるとデプロイは失敗してロールバックします。CloudFormation 経由のデプロイには、これとは別に全体で36時間の上限があります。PAUSE フックで止めている間は24時間ではなく PAUSE 用の上限が適用され、最大14日まで待てます。デプロイ全体の上限は30日です。NLB を使う場合、TEST_TRAFFIC_SHIFT と PRODUCTION_TRAFFIC_SHIFT に安全確認のための10分が上乗せされるため、ALB より切り替えに時間がかかります。
ALBで組むときの必要リソースとIAMロール
ターゲットグループ2つと重み1対0のリスナールール
ターゲットグループは Blue 用(primary)と Green 用(alternate)の2つを、ターゲットタイプ ip で作ります。公式手順は Fargate か、awsvpc ネットワークモードの EC2 タスクを前提にしています。CodeDeploy 方式との最大の違いは本番リスナーのルールです。1つのルールに両方のターゲットグループを入れ、重みを primary=1、alternate=0 にしておきます。ECS はデプロイのたびに、このルールの重みを書き換えてトラフィックを移します。
aws elbv2 create-rule \
--listener-arn "$PROD_LISTENER_ARN" \
--priority 10 \
--conditions Field=path-pattern,Values='/*' \
--actions '[{"Type":"forward","ForwardConfig":{"TargetGroups":[
{"TargetGroupArn":"'"$BLUE_TG_ARN"'","Weight":1},
{"TargetGroupArn":"'"$GREEN_TG_ARN"'","Weight":0}]}}]' \
--query 'Rules[0].RuleArn' --output text
テスト用リスナー(例:ポート8080)は任意です。用意しておくと TEST_TRAFFIC_SHIFT の後に、本番へ流す前の Green へ直接リクエストを送れます。ALB では X-Environment: test のようなヘッダー条件のルールでも振り分けられます。NLB はL4なのでヘッダーやパスでは分けられず、別ポートのリスナーが必要です。
ELB操作用のインフラストラクチャロールとLambdaフック用ロール
ECS にリスナールールを書き換えさせるには、ecs.amazonaws.com を信頼するロールに AWS 管理ポリシー AmazonECSInfrastructureRolePolicyForLoadBalancers を付けます。Lambda フックを使う場合は、同じ信頼ポリシーで lambda:InvokeFunction を許可したロールを別に用意します。デプロイを実行する IAM ユーザー側には、両ロールの iam:PassRole が必要です。
cat > ecs-infrastructure-trust-policy.json <<'EOF'
{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"ecs.amazonaws.com"},"Action":"sts:AssumeRole"}]}
EOF
aws iam create-role \
--role-name ecsInfrastructureRoleForLoadBalancers \
--assume-role-policy-document file://ecs-infrastructure-trust-policy.json
aws iam attach-role-policy \
--role-name ecsInfrastructureRoleForLoadBalancers \
--policy-arn arn:aws:iam::aws:policy/AmazonECSInfrastructureRolePolicyForLoadBalancers
進行中のデプロイがある間にこのロールや信頼ポリシーを消すと、デプロイが失敗し、サービスが不整合な状態で残ることがあると公式ドキュメントは警告しています。ロールを整理するのは、デプロイが止まっている時間帯にしてください。
サービス定義の書き方(AWS CLI・Terraform)
create-serviceに渡すJSONの構成例
次の例は、ALB 経由の Fargate サービスに、ベイク時間15分・CloudWatch アラームによる自動ロールバック・Lambda フック・PAUSE フックを設定したものです。この JSON は、botocore の ECS API 定義(CreateService の入力型)と照合して、未知のキーや必須項目の漏れがないことを確認しています。
{
"cluster": "main",
"serviceName": "web",
"taskDefinition": "web:12",
"desiredCount": 2,
"launchType": "FARGATE",
"networkConfiguration": {
"awsvpcConfiguration": {
"subnets": ["subnet-0aaa", "subnet-0bbb"],
"securityGroups": ["sg-0ccc"]
}
},
"deploymentController": { "type": "ECS" },
"loadBalancers": [
{
"targetGroupArn": "arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:targetgroup/web-blue/1111",
"containerName": "web",
"containerPort": 8080,
"advancedConfiguration": {
"alternateTargetGroupArn": "arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:targetgroup/web-green/2222",
"productionListenerRule": "arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:listener-rule/app/web-alb/aaa/bbb/ccc",
"testListenerRule": "arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:listener-rule/app/web-alb/aaa/ddd/eee",
"roleArn": "arn:aws:iam::123456789012:role/ecsInfrastructureRoleForLoadBalancers"
}
}
],
"deploymentConfiguration": {
"strategy": "BLUE_GREEN",
"bakeTimeInMinutes": 15,
"alarms": { "alarmNames": ["web-alb-5xx"], "enable": true, "rollback": true },
"lifecycleHooks": [
{
"hookTargetArn": "arn:aws:lambda:ap-northeast-1:123456789012:function:web-smoke-test",
"roleArn": "arn:aws:iam::123456789012:role/ecsLambdaHookRole",
"lifecycleStages": ["POST_TEST_TRAFFIC_SHIFT"],
"hookDetails": { "TEST_URL": "http://web-alb.example.internal:8080/health" }
},
{
"targetType": "PAUSE",
"lifecycleStages": ["POST_TEST_TRAFFIC_SHIFT"],
"timeoutConfiguration": { "timeoutInMinutes": 120, "action": "ROLLBACK" }
}
]
}
}
作成は aws ecs create-service --cli-input-json file://service.json で行います。以降のリリースは aws ecs update-service --cluster main --service web --task-definition web:13 のようにタスク定義を差し替えるだけで、Blue/Green の手順が自動で進みます。bakeTimeInMinutes は、API リファレンス上 BLUE_GREEN を選んだときの必須項目です。フックはサービス設定の一部なので、変えるときも UpdateService を呼びます。同じステージに Lambda と PAUSE を置くと、両方が完了するまで次に進みません。ECS の構成要素(クラスター・サービス・タスク定義)の関係はAWS ECSとは?コンテナの仕組み・起動タイプ・料金を参照してください。
Terraformでの書き方と対応するプロバイダの版
resource "aws_ecs_service" "web" {
name = "web"
cluster = var.cluster_arn
task_definition = var.task_definition_arn
desired_count = 2
launch_type = "FARGATE"
deployment_controller {
type = "ECS"
}
deployment_configuration {
strategy = "BLUE_GREEN"
bake_time_in_minutes = 15
lifecycle_hook {
hook_target_arn = var.hook_lambda_arn
role_arn = var.hook_role_arn
lifecycle_stages = ["POST_TEST_TRAFFIC_SHIFT"]
hook_details = jsonencode({ TEST_URL = "http://web-alb.example.internal:8080/health" })
}
lifecycle_hook {
target_type = "PAUSE"
lifecycle_stages = ["POST_TEST_TRAFFIC_SHIFT"]
timeout_configuration {
timeout_in_minutes = 120
action = "ROLLBACK"
}
}
}
load_balancer {
target_group_arn = var.blue_tg_arn
container_name = "web"
container_port = 8080
advanced_configuration {
alternate_target_group_arn = var.green_tg_arn
production_listener_rule = var.prod_rule_arn
test_listener_rule = var.test_rule_arn
role_arn = var.infra_role_arn
}
}
network_configuration {
subnets = var.private_subnet_ids
security_groups = [var.sg_id]
}
}
この HCL は、Terraform 1.16.4 と AWS プロバイダ 6.67.0 で terraform validate と terraform plan が通ることを確認しています。使う機能によって、必要なプロバイダの版が変わります(CHANGELOGより)。
| AWSプロバイダ | リリース日 | 追加された引数 |
|---|---|---|
| 6.4.0 | 2025-07-17 | deployment_configuration・advanced_configuration |
| 6.14.0 | 2025-09-18 | lifecycle_hook.hook_details |
| 6.21.0 | 2025-11-13 | linear_configuration・canary_configuration |
| 6.66.0 | 2026-09-21 | lifecycle_hook.target_type・timeout_configuration |
注意点もあります。terraform-provider-aws の Issue #45678(2025年12月21日起票・2026年10月2日時点で未解決)では、Terraform から更新したときだけ新しいタスクが毎回 alternate 側に登録され、ターゲットグループが交互に入れ替わらないと報告されています。コンソールの「新しいデプロイの強制」では正しく交互になるとのことです。Terraform で運用する場合は、本番に入れる前に2回連続でデプロイし、どちらのターゲットグループに登録されるかを確かめてください。デプロイ操作だけをコード化したい場合はecspressoとは|ECSデプロイをコードで管理する仕組みも選択肢になります。
ライフサイクルフックで検証と承認を挟む方法
Lambdaフックの戻り値とIN_PROGRESSでの再試行
Lambda フックは、戻り値の hookStatus で次の動作を決めます。SUCCEEDED なら次のステージへ進み、FAILED ならロールバックします。IN_PROGRESS を返すと、既定では30秒後に同じ関数がもう一度呼ばれます。戻り値が不正な場合や関数がエラーになった場合も、ロールバックとして扱われます。次の関数は、テスト用リスナー経由でヘルスチェック用URLへアクセスし、初回を含め最大5回試行します(再試行は最大4回)。
import urllib.request
def lambda_handler(event, context):
details = event.get("hookDetails") or {}
url = details["TEST_URL"] # 実環境のテスト用URL。内部ALBの場合はLambdaのVPC接続・DNS解決・通信許可が必要
attempts = int(details.get("attempts", 0)) + 1
try:
with urllib.request.urlopen(url, timeout=5) as res:
ok = res.status == 200
except Exception:
ok = False
if ok:
return {"hookStatus": "SUCCEEDED"}
if attempts >= 5:
return {"hookStatus": "FAILED"}
return {
"hookStatus": "IN_PROGRESS",
"callBackDelay": 30,
"hookDetails": {"attempts": attempts},
}
この関数をローカルの HTTP サーバーに向けて Python 3 で実行すると、200 では SUCCEEDED、503 の1回目では IN_PROGRESS、5回目では FAILED が返りました。IN_PROGRESS と一緒に返した hookDetails は、サービス定義側の値(ここでは TEST_URL)とマージされて次の呼び出しに渡されます。引き継がれるのは同じデプロイ内の同じフックの間だけです。1回の呼び出しは Lambda の上限どおり15分以内に終える必要がありますが、IN_PROGRESS を返し続ければ1ステージを最大24時間まで延ばせます。
再呼び出しまでの待ち時間を指定するキー名は、Lambda フックのページでは callBackDelay、ワークフロー解説のページでは callBackDelaySeconds と表記が揺れています。戻り値の例が載っている前者に合わせ、callBackDelay を使ってください。
PAUSEフックで手動承認を待つ手順
PAUSE フックを置いたステージに来ると、デプロイは止まり、EventBridge に detail-type ECS Hook State Change、イベント名 HOOK_AWAITING_ACTION のイベントが出ます。再開するには、describe-service-deployments で hookId を取り出し、continue-service-deployment を呼びます。
DEPLOY_ARN=$(aws ecs list-service-deployments --cluster main --service web \
--status IN_PROGRESS --query 'serviceDeployments[0].serviceDeploymentArn' --output text)
HOOK_ID=$(aws ecs describe-service-deployments --service-deployment-arns "$DEPLOY_ARN" \
--query "serviceDeployments[0].lifecycleHookDetails[?status=='AWAITING_ACTION'].hookId | [0]" \
--output text)
aws ecs continue-service-deployment \
--service-deployment-arn "$DEPLOY_ARN" \
--hook-id "$HOOK_ID" \
--action CONTINUE # 差し戻すときは ROLLBACK
開発者ガイドの PAUSE フックのCLI例には --hook-id と --action しか書かれていません。しかし API 定義では、serviceDeploymentArn と hookId の両方が必須です。待ち時間の既定は1,440分で、1〜20,160分(14日)の範囲で変えられます。期限が切れたときの既定の動作は ROLLBACK です。PAUSE フックは TEST_TRAFFIC_SHIFT と PRODUCTION_TRAFFIC_SHIFT には置けません。この2つのステージはロールバック中にも呼ばれるためです。1つのサービスに設定できるのは、Lambda フックと PAUSE フックそれぞれ10個までです。
ロールバックの経路と失敗の検知
Green から Blue へ戻す経路は4つあります。
- Lambda フックが
FAILEDを返す、PAUSE フックでROLLBACKを選ぶ、または期限切れ時の動作が ROLLBACK に設定されたフックがタイムアウトする deploymentConfiguration.alarmsにrollback: trueで登録した CloudWatch アラームが ALARM になる- 人が
aws ecs stop-service-deployment --service-deployment-arn "$DEPLOY_ARN" --stop-type ROLLBACKを実行する(コンソールのデプロイ画面の「ロールバック」と同じ) - ステージが24時間を超えてタイムアウトする
手動の ROLLBACK は、自動ロールバックを設定していないサービスでも使えます。進行状況はサービスデプロイの状態(IN_PROGRESS→ROLLBACK_REQUESTED→ROLLBACK_IN_PROGRESS→ROLLBACK_SUCCESSFUL など全9値)で追えます。Blue が残っているベイク時間中なら、ECS はリスナールールの重みを戻すだけで切り戻せます。CLEAN_UP で Blue が0タスクになった後は、前のタスク定義で改めてデプロイし直すことになります。ベイク時間は「アラームが鳴るまでに必要な時間」から決めるのが実務的です。5分間隔で評価するアラームを2回連続の条件で使うなら、15分の既定値は最低ラインと考えてください。
アラームについては、デプロイ開始時点で設定対象のいずれかが ALARM 状態だと、そのデプロイではアラーム設定全体が無視され、アラームによる監視が行われません。障害を直すためのデプロイが、障害中のアラームで止まらないようにするための仕様です。ALB の場合、AWS は HTTPCode_ELB_5XX_Count と HTTPCode_ELB_4XX_Count をアラームの指標に推奨しています。ただし、これらはALB自身が生成したエラーの指標です。アプリケーションが返す5xxも検知する場合は、HTTPCode_Target_5XX_Count などを別途監視します。
LINEAR・CANARYへの切り替え判断とパラメータ
BLUE_GREEN は本番トラフィックを一括で100%移すため、テスト用リスナーで確認できない負荷依存の不具合は、切り替えた瞬間に全ユーザーへ影響します。実トラフィックの一部で様子を見たいなら LINEAR か CANARY を選びます。リスナールール・ロール・フックの構成は共通で、strategy と次の設定ブロックを変えるだけです。
| 設定 | 範囲 | 既定値 |
|---|---|---|
| linearConfiguration.stepPercent | 3.0〜100.0%(0.1刻み) | 10.0 |
| linearConfiguration.stepBakeTimeInMinutes | 0〜1,440分 | 6 |
| canaryConfiguration.canaryPercent | 0.1〜100.0%(0.1刻み) | 5.0 |
| canaryConfiguration.canaryBakeTimeInMinutes | 0〜1,440分 | 10 |
LINEAR を既定値(10%刻み・6分待ち)で使うと、本番移行だけで10段階・待ち時間の合計54分かかります(100%到達後の待ちは省略されます)。PRE_PRODUCTION_TRAFFIC_SHIFT と PRODUCTION_TRAFFIC_SHIFT に置いたフックは各段階で呼ばれるため、PRE_PRODUCTION_TRAFFIC_SHIFT に PAUSE フックを置くと10回の承認操作が必要になります。手動承認は POST_TEST_TRAFFIC_SHIFT に1回だけ置き、段階移行中の判定はアラームに任せる構成が運用しやすいです。カナリアリリースの一般的な設計(割合や観察期間の決め方)はカナリアリリースの仕組みと実装・採用判断で解説しています。
CodeDeploy方式との違いと移行手順
CodeDeploy方式とECSネイティブ方式の構成・運用比較
| 項目 | CodeDeploy方式 | ECSネイティブ |
|---|---|---|
| デプロイの起点 | CreateDeployment+AppSpec | UpdateService |
| 新旧の単位 | タスクセット | サービスリビジョン |
| フックの定義場所 | AppSpec(毎回変更可) | サービス設定 |
| フックの完了通知 | API呼び出し・1時間以内 | 戻り値・最大24時間 |
| リスナールール | 単一ターゲットグループ | 2つを重み1対0 |
| CLIの aws ecs deploy | 対応 | 非対応 |
CodeDeploy 方式のフック関数は PutLifecycleEventHookExecutionStatus を呼んで結果を返しますが、ネイティブ方式では関数の戻り値がそのまま結果になります。そのため、フック関数は書き直しが必要です。AppSpec の書き方はappspec.ymlとは?CodeDeployのAppSpecファイルの書き方、CodeDeploy 側の機能と料金はAWS CodeDeployとは?In-Place・Blue/Greenデプロイと料金・採用判断にまとめています。
AWS の DevOps Blog(2026年2月11日公開・同年3月更新)は、新規プロジェクトや構成を簡素にしたい場合はネイティブ方式を勧めています。一方、CodePipeline と密結合したパイプラインがある場合や、複数サービス・リージョン・アカウントを1回のリリースで協調させる場合は、CodeDeploy を使う場面として挙げています。
既存サービスを移行する3つの方法
- 同じ ELB リソースを使い回す:本番・テストのリスナールールに alternate のターゲットグループを重み0で追加し、
UpdateServiceでコントローラーをECS、戦略をBLUE_GREENに変えます。ダウンタイムはなく手順も最短ですが、並行環境がないためリスクは高いと公式は位置づけています。 - 既存 ALB に新サービスを並べる:別ポートのリスナーとターゲットグループで新サービスを作り、検証後にリスナーのポートを入れ替えます。切り戻しはポートを戻すだけで済みます。
- 新しい ALB ごと作る:Route 53 や CloudFront で上位から振り替えます。すでにその層があり、全通信がそこを経由する構成に向きます。
コントローラーを CODE_DEPLOY から ECS へ変えることはできますが、進行中のデプロイがある間は変更できません。逆方向の変更にも制約があります。BLUE_GREEN 戦略やアラームを設定済みのサービスは、ECS から他のコントローラーへ戻せません。戻す可能性があるなら、方法2か3で旧構成を残しておくのが安全です。
ECSネイティブBlue/Greenを避けるべき場面とつまずきやすい点
- EC2 起動タイプでキャパシティに余裕がない:Green は desiredCount 分を全量起動するため、デプロイ中は一時的にタスクが2倍になります。キャパシティプロバイダーの上限が足りないと
SCALE_UPで止まります。この場合はローリング更新のほうが確実です。 - 新旧で互換性のない DB マイグレーションを伴う:本番トラフィックが Green へ移った後でも、切り戻せば Blue は Green が書き込んだ後の DB を読みます。キューの受信処理のようにリスナーを経由しない処理は、ベイク時間中も Blue のタスクで動き続けます。列の削除や型変更を含むリリースでは、切り戻した瞬間に Blue が壊れます。expand-contract で段階化できないなら、この方式を採るべきではありません。
- リリースごとに検証内容が変わる:フックはサービス設定に固定されます。毎回違うテストを差し込む運用では、検証の分岐を Lambda 側に持たせるか、
hookDetailsをUpdateServiceで毎回書き換える必要があります。 - Service Connect でヘッダー振り分けを使いたい:既定のテスト用ヘッダーは
x-amzn-ecs-blue-green-testです。ポートマッピングのappProtocolがhttp・http2・grpcのいずれかでないと、ヘッダーで振り分けられません。 - NLB で短時間の切り替えを期待する:トラフィック移行の2ステージに10分ずつ上乗せされます。L4 なので、テスト用トラフィックは別ポートでしか分けられません。
よくある質問
ECSネイティブBlue/Greenに追加料金はかかりますか?
機能自体の料金はかかりません。費用が増えるのは、Blue と Green が並走している間のタスク(Fargate なら vCPU とメモリ)と、Lambda フックの実行分です。ベイク時間を長くするほど並走時間も延びます。
ベイク時間は何分に設定すればよいですか?
0〜1,440分の範囲で指定でき、CloudFormation で省略すると15分になります。ロールバック用アラームが ALARM に達するまでの時間(評価期間×連続回数)より長く取るのが目安です。ベイク時間が終わると Blue が消え、重みを戻すだけの即時切り戻しはできなくなります。
aws ecs deploy コマンドはネイティブBlue/Greenで使えますか?
使えません。AWS CLI リファレンスには「CodeDeploy を使うサービスのみ対応」と書かれています。ネイティブ方式では、aws ecs update-service でタスク定義を差し替えてデプロイします。
ローリング更新のデプロイサーキットブレーカーはBlue/Greenでも使えますか?
公式資料の記述が揃っていません。API リファレンスと CloudFormation のリファレンスは「ローリング更新(ECS)デプロイタイプでのみ使用可能」と書き、開発者ガイドのデプロイ障害の検知のページは、サーキットブレーカーとアラームの両方を「ローリング更新と Blue/Green に対応」としています。どちらの方法でも、ロールバックには COMPLETED 状態の前回デプロイが必要です。挙動が確定するまでは、Blue/Green の自動ロールバックを CloudWatch アラームと Lambda フックで組んでおくのが確実です。
CodeDeploy方式は廃止されるのですか?
2026年10月時点で、CodeDeploy の ECS 対応を終了する告知はありません。AWS のブログは、既存の CODE_DEPLOY 構成は使い続けてよいとしたうえで、新規構築にはネイティブ方式を推奨しています。