この記事について
ECS FargateのCI/CDパイプラインをCodeシリーズ(CodePipeline/CodeDeploy/CodeBuild)で実装しています。またこれら一連のAWSリソースはTerraformにより構成管理しています。
あるときterraform applyを実行しようとした際に、ECSサービスのLoadBalancerに変更を検出して、ECSサービスを更新しようとしていることがわかりました。
なにも変更を加えているつもりはなかったのに、変更が検出されるため、何が原因か調べました。その結果、変更が検出された理由に加えて、自分自身がECSのBlue/Greenデプロイの挙動を正しく理解できていないことがわかりました。
どのように挙動を勘違いしていたのか、そして正しい挙動はどうなっているのか、またterraformで変更が検出された原因について、解説していきます。
構成
- ECS
- データプレーンはFargate
- 以下のコンテナがタスク内にて稼働
- PHP-FPM(Laravelが実行)
- NGINX
- CI/CDパイプライン
- ソース : CodeCommit
- ビルド : CodeBuild
- デプロイ : CodeDeploy
- IaC
- Terraform
よくある構成だと思います。
何が起きたかのおさらい。
terraform applyを実行した際に以下の差分が検出されました。
# aws_ecs_service.hogehoge will be updated in-place ~ resource "aws_ecs_service" "hogehoge" { id = "arn:aws:ecs:ap-northeast-1:111122223333:service/hogehoge/fugafuga" name = "hogehoge" tags = {} # (16 unchanged attributes hidden) - load_balancer { - container_name = "nginx" -> null - container_port = 80 -> null - target_group_arn = "arn:aws:elasticloadbalancing:ap-northeast-1:111122223333:targetgroup/targetgroup-2/6621b4dd8e08cd79" -> null } + load_balancer { + container_name = "nginx" + container_port = 80 - target_group_arn = "arn:aws:elasticloadbalancing:ap-northeast-1:111122223333:targetgroup/targetgroup-1/6621b4dd8e08cd79" -> null }
ECSサービスに紐づいているターゲットグループに差分が生じているというようです。
では、この差分はなぜ生じているのでしょうか?
Blue/Greenデプロイの挙動を勘違いしていた
私は元々Blue/Greenデプロイの挙動を以下のように認識していました。
勘違いしていた挙動
デプロイ前
移行期間中
デプロイ後
移行期間が完了して、デプロイが完了したらターゲットグループ1が再度新しいECSサービスに紐づき直すと思いました。ただこれが誤りでした。
デプロイ前->移行期間中->デプロイ後の流れをみると、違和感を感じる方もいるかと思います。
正しい挙動は以下の通りでした。
正しい挙動
(デプロイ前と移行期間中は同じです)
デプロイ前
移行期間中
デプロイ後
デプロイが終わったあと、新しいECSサービスに紐づくターゲットグループは1ではなく2です。つまりBlue/Greenデプロイでは、デプロイが行われるたびに、ECSサービスに紐づくターゲットグループが入れ替わります。
Terraformで差分を検出していた原因
aws_ecs_serviceリソースのload_balancerは一意にならない(デプロイごとに変わる)ため、ignore_changesしてあげる必要がありました。
resource "aws_ecs_service" "hogehoge" { ..省略.. lifecycle { ignore_changes = [task_definition, load_balancer] } }
(タスク定義もCI/CDパイプラインにより更新されるため、ignoreします)
これをしていなかったため、Terraformで差分を検出してしまっていました。