何の話
TerraformのModuleの分け方はマイクロサービス的な単位で分けると良いという話です。TerraformだけではなくてIaC全般に言える話だと思います。
アタッチされたサービス
Twelve-Factor AppのIV. バックエンドサービスでは、バックエンドサービス(DBやキャッシュなど)はアタッチされたサービスとして扱う、としております。
設定は環境変数で接続先を具体的に記入し、アプリケーションコード(ビルド)の差し替えなしにバックエンドサービスを切り替えれるようにすべきとしております。
これにより様々なメリットが生まれますが、ここでは特に責任分界点がこの接続先によって明確になるということがあります。
マイクロサービスの設計では独立性が重要になりますので、責任分界点が明確になっているということは独立性が高いものを組み合わせて安全に利用できている状態と言えると思います。
TerraformによるModule化の境界
Terraformに限らずIaCではインフラの単位をコードとして再利用しようとすると失敗しやすく、例えば「フロントエンド用のnginx」と「画像変換サーバー用nginx」を「同じnginxだから」と言って「同じmodule化」すると確実に失敗します。
今の例は見ただけで失敗だとわかると思いますが、ようは複雑性の意味が全然違うものを共通にしようとすると、その複雑性を隠蔽するためにより複雑な汎用化をしないといけなくて本末転倒になるという話です。
TerraformにおけるModule化は、「共通のものを1つにまとめる」という用途より、「名前空間の分離」を目的として設計するほうが上手くいくと考えております。
例えばTerraformでAWSリソースをModule化する場合、以下のようにするのが良いです。
上記の「アタッチされたサービス」の図とほぼ同じなのがわかるかと思います。責任分界点が事前に明確になっているので、その単位でModule化することによって、Module内でお互いのことを意識することがほとんどなくなります。Module間で必要な情報(エンドポイントなど)はvariablesとoutputで明確に書く必要がありますので、どの情報が外で使われるかも明確になります。
IAM(Role)やSG(セキュリティグループ)もModule毎に個別で作ることで、変に再利用されることがなく、最小の権限を個別に与えることができます。別環境の同リソース(staging/productionなど)や似たような権限のModuleでも必ず個別に作りましょう。
Moduleは汎用的に使えないの?
もちろんそんなことはありません。責任分界点がしっかりしているModuleは汎用的になります。一般的なWebサービスの構成はそんなにどれも違いがないのでModule単位で別プロジェクトに持ち出しなども簡単にできるようになると思います。以前紹介した terraform-aws-modules などの設計も参考にしてください。