Amazon ECS ブルー/グリーンデプロイメントのロールバックを試してみた
Amazon ECS ブルー/グリーンデプロイメント(※)のロールバック手順や動作を確認してみました。
※Code Deployを使わないネイティブの方法を指します。本ブログ中では公式ドキュメントの記載に合わせて「Amazon ECS ブルー/グリーンデプロイメント」と記載します
環境構築
検証用の環境をTerraformを使って構築します。
以下はECS部分になります。
コード全体を確認したい場合は、以下のGitHubリポジトリをご確認ください。
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_serviceのignore_changesにload_balancerを指定している点です。
Amazon ECS ブルー/グリーンデプロイメントでは、ターゲットグループ(どちらがブルーでどちらがグリーンか)の割当をECSが自動的に切り替えます。
Amazon ECS ブルー/グリーンデプロイメント実行後に`terraform apply すると、Terraform が「ECS が変更したターゲットグループの割り当てを元に戻す」差分を検出し、意図しない変更が発生します。
今回は検証目的でTerraform経由でECSタスク定義を変更するため、task_definitionsをignore_changesに指定しませんでした。
Terraform経由以外(GitHub Actionsや手動デプロイ、ロールバック等)でタスク定義を変更する場合は、task_definitionもignore_changesに入れることをおすすめします。(理由はターゲットグループの件と同様です。)
以下のコマンドを実行してリソースをデプロイします。
terraform init
terraform apply
ロールバックの概要
本番トラフィックがグリーン環境に切り替わった後、ブルー環境を削除せずに両方を並行稼働させる監視期間をベイク時間と呼びます。
今回の設定では、aws_ecs_service.app.deployment_configuration.bake_time_in_minutesを5に設定しています。
今回の構成では以下のように動作します。
- グリーン環境に本番トラフィックが切り替わる
- 5分間、ブルーとグリーン両環境が稼働し続ける
- 5分間問題なければブルー環境が削除されてデプロイ完了
つまり、新バージョンに問題があった場合に即座にロールバックできる「猶予期間」です。
ベイク時間は現時点では、0分~1440分(1日)の間で設定可能です。
ベイク時間内のロールバックはマネジメントコンソール上からは以下のボタンから・AWS CLIなら以下のコマンドで実行できます。

aws ecs stop-service-deployment \
--service-deployment-arn "<サービスデプロイメントARN>" \
--stop-type ROLLBACK \
--region ap-northeast-1
ロールバックを実行することで、ALBのリスナールールのターゲットグループの重みが自動的に変更されてブルー ←→ グリーン間で環境が切り替わります。

動作確認
ロールバックを試してみます。
タスク定義を更新して、Amazon ECS ブルー/グリーンデプロイメントを行います。
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>
マネジメントコンソールからロールバックを行います。

だいたい20秒程度で、ロールバックが完了しました。
curl <ALB DNS名>
<html><body><h1>Version: v1</h1><p>ECS Blue/Green Native Demo</p></body></html>
ちなみに現時点では Amazon ECS ブルー/グリーンデプロイメントのトラフィックシフト時のリスナールール変更時間の実行間隔をカスタマイズする設定はありません。
補足: ベイク時間を過ぎた場合のロールバック
ベイク時間経過後に前バージョンに戻したい場合は、新しくデプロイを実行する必要があります。
マネジメントコンソール上からも「ロールバック」ボタンは表示されなくなります。

おわりに
Amazon ECS ブルー/グリーンデプロイメントのロールバック手順と動作について確認しました。
ベイク時間内であれば20秒程度で旧バージョンに切り戻しができるのは安心感があります。
一方、ベイク時間を過ぎるとロールバックではなく再デプロイが必要になる点には注意が必要です。ベイク時間の設定は、アプリケーションの特性や監視体制に応じて検討することをお勧めします。







