Amazon ECS ブルー/グリーンデプロイメントのロールバックを試してみた

Amazon ECS ブルー/グリーンデプロイメントのロールバックを試してみた

2026.02.23

Amazon ECS ブルー/グリーンデプロイメント(※)のロールバック手順や動作を確認してみました。

※Code Deployを使わないネイティブの方法を指します。本ブログ中では公式ドキュメントの記載に合わせて「Amazon ECS ブルー/グリーンデプロイメント」と記載します

環境構築

検証用の環境をTerraformを使って構築します。

以下はECS部分になります。

コード全体を確認したい場合は、以下のGitHubリポジトリをご確認ください。

https://github.com/msato0731/terraform-sample/tree/main/ecs-bluegreen-native

ecs.tf
resource "aws_ecs_cluster" "main" {
  name = "${local.prefix}-cluster"

  setting {
    name  = "containerInsights"
    value = "enabled"
  }
}

resource "aws_ecs_task_definition" "app" {
  family                   = "${local.prefix}-app"
  network_mode             = "awsvpc"
  requires_compatibilities = ["FARGATE"]
  cpu                      = "256"
  memory                   = "512"
  execution_role_arn       = aws_iam_role.ecs_task_execution.arn

  container_definitions = jsonencode([
    {
      name      = "nginx"
      image     = "nginx:latest"
      essential = true
      command   = ["sh", "-c", "echo '<html><body><h1>Version: v1</h1><p>ECS Blue/Green Native Demo</p></body></html>' > /usr/share/nginx/html/index.html && nginx -g 'daemon off;'"]
      portMappings = [
        {
          containerPort = 80
          protocol      = "tcp"
        }
      ]
      logConfiguration = {
        logDriver = "awslogs"
        options = {
          "awslogs-group"         = aws_cloudwatch_log_group.ecs.name
          "awslogs-region"        = "ap-northeast-1"
          "awslogs-stream-prefix" = "ecs"
        }
      }
    }
  ])
}

resource "aws_ecs_service" "app" {
  name            = "${local.prefix}-service"
  cluster         = aws_ecs_cluster.main.id
  task_definition = aws_ecs_task_definition.app.arn
  desired_count   = 1
  launch_type     = "FARGATE"

  network_configuration {
    subnets          = aws_subnet.private[*].id
    security_groups  = [aws_security_group.ecs_tasks.id]
    assign_public_ip = false
  }

  load_balancer {
    target_group_arn = aws_lb_target_group.blue.arn
    container_name   = "nginx"
    container_port   = 80

    advanced_configuration {
      alternate_target_group_arn = aws_lb_target_group.green.arn
      production_listener_rule   = aws_lb_listener_rule.prod.arn
      test_listener_rule         = aws_lb_listener_rule.test.arn
      role_arn                   = aws_iam_role.ecs_infrastructure_lb.arn
    }
  }

  deployment_configuration {
    strategy             = "BLUE_GREEN"
    bake_time_in_minutes = 5
  }

  alarms {
    alarm_names = [aws_cloudwatch_metric_alarm.ecs_5xx.alarm_name]
    enable      = true
    rollback    = true
  }

  depends_on = [
    aws_iam_role_policy_attachment.ecs_task_execution,
    aws_iam_role_policy_attachment.ecs_infrastructure_lb,
    aws_lb_listener_rule.prod,
    aws_lb_listener_rule.test,
  ]

  lifecycle {
    ignore_changes = [
      load_balancer
    ]
  }
}

ポイントはaws_ecs_serviceignore_changesload_balancerを指定している点です。

Amazon ECS ブルー/グリーンデプロイメントでは、ターゲットグループ(どちらがブルーでどちらがグリーンか)の割当をECSが自動的に切り替えます。

Amazon ECS ブルー/グリーンデプロイメント実行後に`terraform apply すると、Terraform が「ECS が変更したターゲットグループの割り当てを元に戻す」差分を検出し、意図しない変更が発生します。

今回は検証目的でTerraform経由でECSタスク定義を変更するため、task_definitionsignore_changesに指定しませんでした。

Terraform経由以外(GitHub Actionsや手動デプロイ、ロールバック等)でタスク定義を変更する場合は、task_definitionignore_changesに入れることをおすすめします。(理由はターゲットグループの件と同様です。)

以下のコマンドを実行してリソースをデプロイします。

terraform init
terraform apply

ロールバックの概要

本番トラフィックがグリーン環境に切り替わった後、ブルー環境を削除せずに両方を並行稼働させる監視期間をベイク時間と呼びます。

今回の設定では、aws_ecs_service.app.deployment_configuration.bake_time_in_minutes5に設定しています。

今回の構成では以下のように動作します。

  1. グリーン環境に本番トラフィックが切り替わる
  2. 5分間、ブルーとグリーン両環境が稼働し続ける
  3. 5分間問題なければブルー環境が削除されてデプロイ完了

つまり、新バージョンに問題があった場合に即座にロールバックできる「猶予期間」です。

ベイク時間は現時点では、0分~1440分(1日)の間で設定可能です。

ベイク時間内のロールバックはマネジメントコンソール上からは以下のボタンから・AWS CLIなら以下のコマンドで実行できます。

サービスデプロイ___Elastic_Container_Service___ap-northeast-1.png

aws ecs stop-service-deployment \
  --service-deployment-arn "<サービスデプロイメントARN>" \
  --stop-type ROLLBACK \
  --region ap-northeast-1

ロールバックを実行することで、ALBのリスナールールのターゲットグループの重みが自動的に変更されてブルー ←→ グリーン間で環境が切り替わります。

リスナーの詳細___EC2___ap-northeast-1.png

動作確認

ロールバックを試してみます。

タスク定義を更新して、Amazon ECS ブルー/グリーンデプロイメントを行います。

ecs.tf
resource "aws_ecs_cluster" "main" {
  name = "${local.prefix}-cluster"

  setting {
    name  = "containerInsights"
    value = "enabled"
  }
}

resource "aws_ecs_task_definition" "app" {
  family                   = "${local.prefix}-app"
  network_mode             = "awsvpc"
  requires_compatibilities = ["FARGATE"]
  cpu                      = "256"
  memory                   = "512"
  execution_role_arn       = aws_iam_role.ecs_task_execution.arn

  container_definitions = jsonencode([
    {
      name      = "nginx"
      image     = "nginx:latest"
      essential = true
+      command   = ["sh", "-c", "echo '<html><body><h1>Version: v2</h1><p>ECS Blue/Green Native Demo</p></body></html>' > /usr/share/nginx/html/index.html && nginx -g 'daemon off;'"]

-      command   = ["sh", "-c", "echo '<html><body><h1>Version: v1</h1><p>ECS Blue/Green Native Demo</p></body></html>' > /usr/share/nginx/html/index.html && nginx -g 'daemon off;'"]
# 省略
terraform apply

デプロイ完了までしばらく待ちます。

デプロイが完了し、HTTPレスポンスがVersion: v2になっていることを確認できました。

curl <ALB DNS>
出力例
<html><body><h1>Version: v2</h1><p>ECS Blue/Green Native Demo</p></body></html>

マネジメントコンソールからロールバックを行います。

サービスデプロイ___Elastic_Container_Service___ap-northeast-1.png

だいたい20秒程度で、ロールバックが完了しました。

curl <ALB DNS>
出力例
<html><body><h1>Version: v1</h1><p>ECS Blue/Green Native Demo</p></body></html>

ちなみに現時点では Amazon ECS ブルー/グリーンデプロイメントのトラフィックシフト時のリスナールール変更時間の実行間隔をカスタマイズする設定はありません。

https://dev.classmethod.jp/articles/cdk-l2-ecs-native-blue-green-deployment/

補足: ベイク時間を過ぎた場合のロールバック

ベイク時間経過後に前バージョンに戻したい場合は、新しくデプロイを実行する必要があります。

マネジメントコンソール上からも「ロールバック」ボタンは表示されなくなります。

サービスデプロイ___Elastic_Container_Service___ap-northeast-1.png

おわりに

Amazon ECS ブルー/グリーンデプロイメントのロールバック手順と動作について確認しました。

ベイク時間内であれば20秒程度で旧バージョンに切り戻しができるのは安心感があります。

一方、ベイク時間を過ぎるとロールバックではなく再デプロイが必要になる点には注意が必要です。ベイク時間の設定は、アプリケーションの特性や監視体制に応じて検討することをお勧めします。

この記事をシェアする

FacebookHatena blogX

関連記事