---
title: "ECSネイティブBlue/Greenデプロイの設定手順｜ライフサイクルフック・ロールバック・CodeDeploy移行【2026年版】"
url: "https://www.issoh.co.jp/tech/details/7858/"
published: 2025-07-24
updated: 2026-10-02
categories: ["AWS"]
publisher: "株式会社一創"
---

# ECSネイティブBlue/Greenデプロイの設定手順｜ライフサイクルフック・ロールバック・CodeDeploy移行【2026年版】

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の設定値](/tech/details/16189/)で、Blue/Green という手法そのものの考え方や Kubernetes での実装は[ブルーグリーンデプロイメントの仕組みと他方式との違い](/tech/details/4040/)で扱っています。この記事は 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とは？コンテナの仕組み・起動タイプ・料金](/tech/details/3870/)を参照してください。

### 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](https://github.com/hashicorp/terraform-provider-aws/blob/main/CHANGELOG.md)より）。

| 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](https://github.com/hashicorp/terraform-provider-aws/issues/45678)（2025年12月21日起票・2026年10月2日時点で未解決）では、Terraform から更新したときだけ新しいタスクが毎回 alternate 側に登録され、ターゲットグループが交互に入れ替わらないと報告されています。コンソールの「新しいデプロイの強制」では正しく交互になるとのことです。Terraform で運用する場合は、本番に入れる前に2回連続でデプロイし、どちらのターゲットグループに登録されるかを確かめてください。デプロイ操作だけをコード化したい場合は[ecspressoとは｜ECSデプロイをコードで管理する仕組み](/tech/details/13182/)も選択肢になります。

## ライフサイクルフックで検証と承認を挟む方法

### 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 フックのページ](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/lambda-lifecycle-hooks.html)では `callBackDelay`、[ワークフロー解説のページ](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/blue-green-deployment-how-it-works.html)では `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回だけ置き、段階移行中の判定はアラームに任せる構成が運用しやすいです。カナリアリリースの一般的な設計（割合や観察期間の決め方）は[カナリアリリースの仕組みと実装・採用判断](/tech/details/13592/)で解説しています。

## 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ファイルの書き方](/tech/details/7564/)、CodeDeploy 側の機能と料金は[AWS CodeDeployとは？In-Place・Blue/Greenデプロイと料金・採用判断](/tech/details/15597/)にまとめています。

AWS の [DevOps Blog](https://aws.amazon.com/blogs/devops/choosing-between-amazon-ecs-blue-green-native-or-aws-codedeploy-in-aws-cdk/)（2026年2月11日公開・同年3月更新）は、新規プロジェクトや構成を簡素にしたい場合はネイティブ方式を勧めています。一方、CodePipeline と密結合したパイプラインがある場合や、複数サービス・リージョン・アカウントを1回のリリースで協調させる場合は、CodeDeploy を使う場面として挙げています。

### 既存サービスを移行する3つの方法

1. **同じ ELB リソースを使い回す**：本番・テストのリスナールールに alternate のターゲットグループを重み0で追加し、`UpdateService` でコントローラーを `ECS`、戦略を `BLUE_GREEN` に変えます。ダウンタイムはなく手順も最短ですが、並行環境がないためリスクは高いと公式は位置づけています。
2. **既存 ALB に新サービスを並べる**：別ポートのリスナーとターゲットグループで新サービスを作り、検証後にリスナーのポートを入れ替えます。切り戻しはポートを戻すだけで済みます。
3. **新しい 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）デプロイタイプでのみ使用可能」と書き、開発者ガイドの[デプロイ障害の検知](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/deployment-failure-detection.html)のページは、サーキットブレーカーとアラームの両方を「ローリング更新と Blue/Green に対応」としています。どちらの方法でも、ロールバックには COMPLETED 状態の前回デプロイが必要です。挙動が確定するまでは、Blue/Green の自動ロールバックを CloudWatch アラームと Lambda フックで組んでおくのが確実です。

### CodeDeploy方式は廃止されるのですか？

2026年10月時点で、CodeDeploy の ECS 対応を終了する告知はありません。AWS のブログは、既存の `CODE_DEPLOY` 構成は使い続けてよいとしたうえで、新規構築にはネイティブ方式を推奨しています。

## 関連記事

- [ブルーグリーンデプロイメントとは｜仕組み・他方式との違い・AWS/Kubernetes実装をコード例で解説](/tech/details/4040/)
- [AWS CodeDeployとは？In-Place・Blue/Greenデプロイと料金・採用判断を実装者目線で解説](/tech/details/15597/)
- [AWS ECSとは？コンテナの仕組み・起動タイプ・料金・EKSとの違い【2026年版】](/tech/details/3870/)
- [カナリアリリースとは？段階リリースの仕組み・他方式との違い・実装と採用判断を実装視点で解説](/tech/details/13592/)
- [ローリングアップデートとは？仕組みとKubernetes・ECSの設定値・採用判断を解説](/tech/details/16189/)

---

出典: [ECSネイティブBlue/Greenデプロイの設定手順｜ライフサイクルフック・ロールバック・CodeDeploy移行【2026年版】](<https://www.issoh.co.jp/tech/details/7858/>)（株式会社一創）
