背景
複数環境あるインフラでのterraformのディレクトリ構造として以下の構成を取っているケースを比較的見かけます。
├── environments
│ ├── dev
│ │ ├── backend.tf
│ │ └── main.tf
│ ├── prod
│ │ ├── backend.tf
│ │ └── main.tf
│ └── stg
│ ├── backend.tf
│ └── main.tf
└── modules
├── database
│ ├── main.tf
│ ├── outputs.tf
│ └── variables.tf
├── eks
│ ├── main.tf
│ ├── outputs.tf
│ └── variables.tf
└── vpc
├── main.tf
├── outputs.tf
└── variables.tf
Terraform を使用するためのベスト プラクティス | Google Cloudにもこれと同じ構成の例が載っています。
ただ、この構造はあんまり良くない点があります。
なぜ微妙か
多くの人が意識していませんが、普段 terraform plan
や terraform apply
を実行するディレクトリもまたrootモジュールと呼ばれるモジュールです1。
冒頭のディレクトリ構造を見ると、フォルダ(ファイル)をenvironmentsとmodulesという2種類に分類しているように見えます。しかし、実際にはenvironmentsフォルダ中にあるdevやprodもまたモジュールです。なので、rootモジュールの知識を持っている人が見ると奇妙に見えます。
├── environments
│ ├── dev ← これもモジュール
│ ├── prod ← これもモジュール
│ └── stg ← これもモジュール
└── modules
├── database
├── eks
└── vpc
例えるなら以下のような構造に見えます。
├── 人物
│ ├── 太郎 ← これも哺乳類
│ ├── 花子 ← これも哺乳類
│ └── フェルスタッペン ← これも哺乳類
└── 哺乳類
├── 犬
├── 猫
└── 熊
どうすればいいか
以下のどちらかをおすすめします。
案1. modulesをchild-modulesへリネームする
environments下のディレクトリはモジュールではありますが、rootモジュールでありchildモジュールではありません。
なので、modulesディレクトリをchild-modulesなどへリネームすれば矛盾は解消できます。
├── environments
│ ├── dev
│ ├── prod
│ └── stg
└── child-modules (修正)
├── database
├── eks
└── vpc
案2. modulesをchild-modulesへ、environmentsをroot-modulesへリネームする
案1に加えてenvironmentsディレクトリもリネームする案です。
個人的にはこちらのほうがおすすめです。というのは、そもそもenvironmentsとmodulesというディレクトリの切り方が概念として直行していないことが根本的なわかりにくさの原因だからです。root-modules or child-modulesという切り方は同じ切り口でフォルダを分類しており、その問題を解消しています。
├── root-modules (修正)
│ ├── dev
│ ├── prod
│ └── stg
└── child-modules (修正)
├── database
├── eks
└── vpc
蛇足
childモジュールの名前の変更は moved ブロックを使用すれば結構手軽にできます。
terraform state mv
の利用なしに通常の terraform plan / apply
と同じフローで移動できるからです。
なので、微妙だと思っているモジュール名やモジュール配置は気軽に改善していきましょう。