この記事について
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で差分を検出してしまっていました。