TerraformとKubernetesの「甘美な罠」:ハイブリッドIaCの深淵とGitOpsへの昇華
君たちがTerraformの`helm_release`リソースに手を出したとき、それは「インフラ管理の楽園」への切符を手に入れたつもりで、実は「地獄の泥沼」への片道切符を買っている可能性が高い。
今日は、TerraformとKubernetesという二つの巨人が衝突する境界線で、エンジニアが直面する「状態管理の不整合」と、その先にある「真の自動化」について、現場の血と汗の結晶を共有しよう。
—
1. `helm_release` という名のパンドラの箱
Terraformの`helm_release`は、HelmのバイナリをラップしてTerraformのステートと同期させる。一見エレガントだが、ここには重大な落とし穴がある。
限界:ステートの乖離と「見えない変更」
Kubernetesは「常に現在の状態(Actual State)を望ましい状態(Desired State)に合わせようとする」自律的なシステムだ。一方、Terraformは「最後に実行された時点の記録(State File)」を絶対視する。
もし、誰かがKubernetes上で直接`kubectl edit`を叩けば、Terraformのステートは即座に陳腐化する。`terraform plan`はそれを検知できないことが多い。なぜなら、`helm_release`はHelmのチャート展開結果の「一部」しかトラッキングしていないからだ。
対策:
`helm_release`を使うなら、「Immutableなインフラ」という思想をK8s内にも強制せよ。 運用中に手動変更を許す余地は1ミリも残さない。もし手動変更が避けられないなら、それはインフラの設計ミスだ。
—
2. CRD管理の悪夢:Terraformで挑むべきではない領域
TerraformでKubernetesのCustom Resource Definition (CRD) や、そのカスタムリソースを管理しようとするのは、茨の道だ。
なぜCRD管理で失敗するのか
1. APIサーバーの応答速度: CRDはインストール直後にはAPIが準備できていないことがある。Terraformのプロバイダーは、リソース生成時にAPIの存在確認を行うが、この「タイミングのラグ」で死ぬ。
2. 依存関係の地獄: CRDが作成されるまで、そのリソースはデプロイできない。`depends_on`を駆使しても、APIのレジストリが更新されるまでのミリ秒単位の揺らぎが、CI/CDパイプラインを真っ赤に染める。
極限の知見:
CRDとカスタムリソースはTerraformの責務から切り離せ。 Terraformの役割は「K8sクラスターの基盤(Control Plane、Node Pool、Namespaceの枠組み)」までだ。その中で動くワークロードは、Kubernetesの思想に適したGitOpsツールへ委譲すべきだ。
—
3. 究極の役割分担:Terraform × ArgoCD
「すべてをTerraformで管理したい」という欲求は、技術的なエゴに過ぎない。真のプロは、ツールを適材適所で使い分ける。
- Terraformの責務:
- VPC, RDS, EKSクラスター, IAM等の「クラウド基盤」。
- ArgoCDのインストール(Bootstrap)。
- ArgoCDの責務:
- アプリケーションのデプロイメント。
- CRDを含む全Kubernetesリソースの同期。
現場で役立つ「Terraform + ArgoCD」のアーキテクチャ
TerraformでArgoCDをデプロイする際、`helm_release`を使ってArgoCDの `Application` を `ApplicationSet` として定義して投げる。これにより、「TerraformがArgoCDの箱を作り、その箱の中身(アプリケーション)はArgoCDがGitから自動で同期する」という完全自動のパイプラインが完成する。
—
4. パフォーマンスを極めるための内部ハック
Terraformのプロバイダーがメモリを食いつぶし、実行速度が低下するのは、Stateファイルが肥大化している証拠だ。
内部アーキテクチャの最適化テクニック
1. Stateの分割:
`terraform.tfstate`を一つにまとめるな。環境毎、レイヤー毎に`terragrunt`やワークスペースを使って細分化せよ。これにより、APIサーバーへのクエリ回数を劇的に減らせる。
2. プロバイダーのタイムアウト設定:
巨大なCRDを扱う際は、プロバイダーのタイムアウトを意図的に調整する。
provider “kubernetes” {
# APIのレスポンスを待つ時間を明示的に伸ばす
experiments {
manifest_resource = true
}
}
3. APIサーバーへの負荷削減:
`kube-client`のキャッシュをローカルに持たせるよう設定を変更する。これで、`terraform plan`時のネットワークI/Oが激減する。
—
最後に:エンジニアとしての矜持
Terraformで何でも解決しようとするな。それはツールへの依存であり、アーキテクチャの敗北だ。
「Terraformで環境を構築し、GitOpsでアプリケーションを運用する」。この境界線を明確に引くことこそが、大規模なシステムにおいて「冪等性」を維持し、夜中にアラートで叩き起こされないための唯一の正解だ。
君たちのインフラが、コードであり、美しく、そして何よりも「壊れない」ものであることを願っている。さあ、次はどのボトルネックを破壊しに行こうか。