ECS×Terraformで実現する「ゼロダウンタイム」の極致:ブルーグリーンデプロイメントの静かなる支配
TerraformでECSを管理している諸君、`terraform apply` を打つたびに「デプロイ時の瞬断」に怯えてはいないか? もしくは、コンソールをポチポチしてターゲットグループを切り替えるような前時代的な運用をしていないか?
インフラエンジニアにとって、デプロイは「イベント」ではなく「日常の呼吸」であるべきだ。今回は、Terraformの力を極限まで引き出し、ECSとALBを完璧に連携させて、「誰がいつデプロイしても絶対に失敗しない」ブルーグリーンデプロイメント(BGD)を構築する。
—
1. なぜ「Terraform単体」でのBGDが難しいのか?
Terraformは「宣言的」だ。しかし、ECSのデプロイは「命令的」なフロー(タスク定義更新 → 新タスク起動 → ヘルスチェック → 切り替え)を要求する。
Terraformのリソース依存関係だけでこれを制御しようとすると、`terraform apply` 一発で旧環境が消滅し、新環境が立ち上がる前にダウンタイムが発生する。我々が求めるのは、「ターゲットグループの重み付けを、Terraformのステートと分離して制御する」というアプローチだ。
実践的コードパターン:ALBリスナールールとターゲットグループの分離
まず、Terraformで管理すべきは「ECSサービス本体」と「リスナールール」を疎結合にすることである。
BlueとGreenのターゲットグループを定義
resource “aws_lb_target_group” “blue” {
name = “app-blue”
port = 80
protocol = “HTTP”
vpc_id = var.vpc_id
target_type = “ip”
lifecycle { create_before_destroy = true } # 必須:新旧入れ替え時のデッドロック回避
}
ECSサービス側では、ターゲットグループを「固定」しないのがコツ
resource “aws_ecs_service” “main” {
name = “my-app”
cluster = var.cluster_id
task_definition = aws_ecs_task_definition.app.arn
# ここでlifecycleを使い、デプロイ時にターゲットグループ構成の更新を無視させる
lifecycle {
ignore_changes = [load_balancer]
}
}
2. 現場で震える「神」設定と開発環境の最適化
インフラコードを書く速度は、エディタの設定一つで劇的に変わる。テックリードとしてチームに強制(推奨)している設定を共有する。
Terraformエンジニアの「三種の神器」
1. VS Code 拡張機能: `HashiCorp Terraform`
- 言わずもがな。`terraform validate` や `fmt` を保存時に自動実行させるのは、もはや呼吸だ。
2. `tflint` による静的解析
- 「リソース名が命名規則に沿っていない」「非推奨の引数を使っている」といったミスをCI前に叩き潰す。`.tflint.hcl` をルートに置くことは義務と心得よ。
3. `direnv` + `asdf`
- プロジェクトごとにTerraformのバージョンを固定せよ。`v0.12` と `v1.x` が混在するカオスは、チームの寿命を削る。
チーム開発を加速させる「神ショートカット」
- `Ctrl + P` (ファイルジャンプ): リソース数が増えたらディレクトリ構成が深くなる。名前で即座に飛べ。
- `Alt + Shift + F` (フォーマット): 汚いコードは悪。Gitコミット前に必ず叩く癖をつけろ。
—
3. 実用的な設定ファイル(YAML/JSON)のベストプラクティス
IaCを運用していると、Terraformの変数管理に疲弊する。`tfvars` を巨大化させるな。設定は YAML で切り出し、`yamldecode` で読み込むのがスマートだ。
config.yaml (階層化して管理)
ecs_settings:
cpu: 512
memory: 1024
desired_count: 2
deployment_controller: “CODE_DEPLOY” # BGDにはCodeDeployの利用を強く推奨する
main.tf (読み込み)
locals {
config = yamldecode(file(“${path.module}/config.yaml”))
}
resource “aws_ecs_service” “main” {
# …
cpu = local.config.ecs_settings.cpu
}
このように、「ビジネスロジック(Terraform)」と「設定値(YAML)」を分離することで、CI/CDパイプラインから設定値のみを上書きする運用が可能になる。
—
4. 伝説のSREが教える「最後の砦」
最後に、TerraformでBGDを運用する際の真の鉄則を授ける。
1. `lifecycle { ignore_changes = […] }` を愛せ
- ECSの `load_balancer` 設定や、オートスケーリングの `desired_count` は、Terraformに管理させつつも、デプロイ時の動的な変更は「無視」させる。これができないと、デプロイのたびにTerraformが「元の状態に戻そう」として、せっかく切り替えたターゲットグループを破壊しに来る。
2. Stateのロックを過信するな
- S3 + DynamoDBのバックエンドは必須だが、チーム開発では必ず `terraform plan` の結果をプルリクにコメントするボットを導入せよ。人間が見るべきは「何が起きるか」の差分だけだ。
3. 「切り戻し」の練習を怠るな
- BGDの真価は「素早いデプロイ」ではなく「瞬時の切り戻し」にある。ALBのリスナールールをワンコマンドで反転させるスクリプトを用意しておけ。
—
エンジニア諸君。
コードは単なるテキストではない。それはインフラの「意思」だ。今日紹介したテクニックを使い、手動作業という名の悪魔を駆逐し、デプロイをただの「退屈な成功」へと変えてくれ。
質問があればいつでも歓迎する。だが、まずは `terraform fmt` を実行してからにしろ。それがプロの礼儀だ。