TerraformのLocal Paths Module移行がつらかったのでTerraform版kustomizeのようなものを作ってみた
これはなに
Terraform で複数環境に DRY に展開しようと思ったら、オレオレ Module みたいな Local Paths Module [1] しか選択肢がないのつらくね? Kustomize みたいなのでいいんやけど…? と思って PoC 的に Terraform 版 Kustomize のようなものを作ってみました。
モチベーション
Terraform Modules は、Terraform でリソース設定ファイルを再利用するほぼ唯一の方法です。
terragrunt なんかもツールとしてはありますが、Terraform Module を拡張し包括するようなものと捉えており、 Module 化からは逃れられないはずです。
オープンソースの Module として普及している場合や、社内のプライベートな環境で公式に提供されている場合などは効果的に思えます。しかし、自プロダクトでしか使わないモジュールを作成するのはやや過剰に思えます。
ここで、Kubernetes のマニフェスト管理ツールを考えると、Helm
と Kustomize
の二択がぱっと思いつきます。
おおよその場合、外部のパッケージ化されたものを使いたい場合は Helm Chart を利用し、プロダクトのマニフェストファイルの再利用は Kustomize を使うケースが多いのではないでしょうか。
Module をあるコンポーネントを構築するためのテンプレートを提供する、と考えると Kubernetes の世界における Helm Chart と同列に位置するものと捉えられ、Module 化は Chart を作るようなものと捉えられるのではないでしょうか。
このとき、Terraform において、Kustomize に対応するソリューションがあってもいいように感じました。
また、個人的な経験としても、コピペ管理から Local Paths Module への移行はかなりつらかったので、PoC として Terraform 版の Kustomize のようなものを作ってみよう!となりました。
一方で、最低限動いて出せるかも、というところまで作ったところで Override Files のことを知りました。
そのため、「それ override.tf
やんけ」と言われると耳が痛いのですが、こちらは再利用目的ではないし多用を推奨するものでもないし…、ということで棲み分けはできると考えています。(処理としてはかなり近しいことをやっていそうなので、もっと早く知ってればがっつり参考にできそうでした)
使い方
tfustomize build
は tfustomization.hcl
ファイルを読み込み、マージの結果としてディレクトリとファイルを生成します。ユーザーは出力されたファイルを使用して terraform plan
と terraform apply
を実行できます。
kustomize だと標準出力を渡して kubectl apply -f -
みたいなことができますが、Terraform は実行ディレクトリ以下の tf ファイルをすべて見るため、ファイル生成してディレクトリ移動して…といった操作が必要になっています。
Usage:
tfustomize build [dir] [flags]
Flags:
-h, --help help for build
-o, --out string Output directory (default "generated")
-f, --outfile string Output filename (default "main.tf")
-p, --print Print the result to the console instead of writing to a file
Global Flags:
-d, --debug Enable debug mode
tfustomization.hcl
のフォーマットは以下の通りです。
tfustomize {
syntax_version = "v1"
}
resources {
paths = [
"../base",
]
}
patches {
paths = [
"./main.tf",
]
}
-
tfustomize
ブロック- 現在はプレースホルダーとしてのみ使用されます。
-
resources
ブロック- "base" となる設定ファイルを指定します。
- ディレクトリ名またはファイル名を指定できます。
-
patches
ブロック- "overlay" となる設定ファイルを指定します。
- ディレクトリ名またはファイル名を指定できます。
マージの挙動と制限
- トップレベルのブロックのマージルール
- base と overlay で同じブロックタイプとラベルのブロックがある場合、マージされます。
- ただし、
moved
、import
、removed
ブロックはマージではなく追記されます。
- ただし、
- base と overlay で同じブロックタイプとラベルのブロックがある場合、マージされます。
-
locals
ブロック- 1つのブロックにマージされます。
- トップレベルのブロック内の attribute
- overlay ブロック内の attribute は、ベースブロック内の同名の attribute を上書きします。
- トップレベルのブロック内の任意のブロック
- 追記されます。上書きはできません。(issue #8)
- ブロック内の出力順序について
- ランダムに出力されます (issue #6)
サンプル
Docker Provider を利用してコピペで動かしてみるサンプルを用意しています。
おわりに
Terraform 版 Kustomize のようなツール tfustomize
を紹介しました。
本番に入れたりCIに組み込んでこそカバーしたい機能や、そもそも使い物になるかならないか、などが分かると思うのですが、プライベートだとそもそも terraform を書かないか、書いたとして共通化したいケースがないので実戦投入する機会があれば投入してみたいところです。
これを読んでくださった方で、ご興味あればぜひ動かしてみてフィードバックをください🙏
-
自プロダクトでしか利用しない独自 Module を勝手に呼称 ↩︎
Discussion