Terraform × Kubernetes:ハイブリッドIaCの深淵と、その先にある「境界の設計」
Terraformの `helm_release` リソースを使って、インフラからアプリケーションまで一撃で構築する。一見、理想的な「IaCの完成形」に見える。だが、現場でこの構成を突き詰めれば突き詰めるほど、ある壁にぶつかるはずだ。
「Terraformがクラスタの状態と乖離し、デプロイが膠着する」
今日は、TerraformとKubernetesを共存させる際の「実戦的な限界」と、それを突破するためのアーキテクチャ設計について語ろう。
—
1. `helm_release` の甘い罠と「状態管理の不整合」
多くのエンジニアが陥る罠は、Terraformを「K8sのデプロイメントツール」として過信することだ。
- リソース競合の発生: `helm_release` は Helmのリリースを Terraform のステートファイルでラップする。しかし、Helmチャート内で定義されたリソースが、別の Terraform モジュールや手動運用(`kubectl`)で変更された場合、Terraform はその不整合を検知できず、あるいは過剰な修正を試みてクラスタを破壊する。
- CRDの管理: CRD(Custom Resource Definition)は Terraform との相性が最悪だ。CRDの適用順序、待機時間、そして Terraform 実行中の CRD 更新に伴う API サーバーの反応。これらを `helm_release` だけで制御しようとするのは、泥沼への入り口だ。
突破口:役割分担の黄金比
結論から言う。「インフラ(Namespaces, RBAC, StorageClass)は Terraform」、「アプリケーション(Deployments, Services, CRDs)は ArgoCD」と割り切るのが現代の正解だ。
Terraform は「GitOpsが動くための土壌」を作り、ArgoCD は「Git上の宣言的状態をクラスタに同期させるエンジン」として専念させる。これが最も再現性が高く、トラブルシューティングも容易な構成だ。
—
2. 開発スピードを劇的に高める「プロの武器」
ここからは、現場で「こいつ、できるな」と思われるためのツールセットと設定術だ。
必須の神プラグイン & 設定
- VS Code: `Terraform` (HashiCorp公式) + `Kubernetes` (Microsoft):
- この2つは必須。特に `Kubernetes` 拡張機能の「Resource Graph」を使って、Terraformで作成したリソースがクラスタ内でどう動いているか、即座に可視化する癖をつけろ。
- `tflint` と `terrascan` のCI統合:
- GitHub Actionsでプルリク時に `tflint` を回すのは当たり前。さらに `checkov` を入れ、K8sのセキュリティコンテキスト(特権コンテナの禁止など)を静的解析で叩き落とすルールを強制せよ。
隠れたキーボードショートカット
- Terraform: `Shift + Alt + F` (フォーマット)。保存時に自動実行する設定(`”editor.formatOnSave”: true`)は、チーム全員の強制事項だ。
- K8s: `k` (kubectlのエイリアス) を使い、更に `fzf` を組み合わせる。「`k get pods | fzf`」でPodを選択し、ログを見る速度を物理的に上げろ。
—
3. 実践:ベストプラクティス構成例
チーム開発で「誰が書いても同じ品質」にするためのディレクトリ構成例だ。
├── terraform/
│ ├── modules/
│ │ └── k8s-bootstrap/ # クラスタ作成後の基盤(ArgoCD本体など)
│ └── environments/
│ └── production/
│ ├── main.tf
│ ├── provider.tf
│ └── terraform.tfvars
└── k8s-manifests/ # ここを ArgoCD が監視する
└── apps/
└── backend/
├── deployment.yaml
└── kustomization.yaml # TerraformではなくKustomizeで差分管理
TerraformでArgoCDをブートストラップする設定例
TerraformでArgoCDをインストールする際の最小構成
resource “helm_release” “argocd” {
name = “argocd”
repository = “https://argoproj.github.io/argo-helm”
chart = “argo-cd”
namespace = “argocd”
create_namespace = true
# 重要なのは「ここでアプリを管理しない」こと。
# インストールした後の「アプリの同期」はArgoCDに委譲する。
values = [
“${file(“values/argocd.yaml”)}”
]
}
—
4. 最後に:テックリードからの提言
IaCにおいて最も危険なのは「全能感」だ。Terraformで何でもできるからといって、すべてを Terraform に詰め込んではいけない。
- 境界を設計せよ: Terraform は「環境を準備するツール」、GitOpsツールは「環境を運用するツール」だ。この境界を明確に引くことで、ステートファイルの肥大化を防ぎ、デプロイの失敗が環境全体に波及することを防げる。
- 「冪等性」のその先へ: 冪等性はスタートラインだ。本当に目指すべきは、誰が触っても壊れない「宣言的な自律運用システム」である。
君たちが今日書くコードが、明日の夜中の障害コールを減らす。そう信じて、設計の美しさにこだわってほしい。それがエンジニアとしての矜持だ。