👻

Terraformで、どんなディレクトリ構成のパターンがあるか調べる

2025/02/14に公開

公式の推奨するモジュールのディレクトリ構成

ディレクトリ構成全体の記事ではないですが、モジュールのディレクトリ構成に限っては、公式ドキュメントに以下のような構成が推奨されています。

$ tree complete-module/
.
├── README.md
├── main.tf
├── variables.tf
├── outputs.tf
├── ...
├── modules/
│   ├── nestedA/
│   │   ├── README.md
│   │   ├── variables.tf
│   │   ├── main.tf
│   │   ├── outputs.tf
│   ├── nestedB/
│   ├── .../
├── examples/
│   ├── exampleA/
│   │   ├── main.tf
│   ├── exampleB/
│   ├── .../

わりと特徴的だなと思うのは、exampleディレクトリです。モジュールの使い方を示すサンプルコードを配置するディレクトリです。これは、モジュールの利用者がモジュールの使い方を理解しやすくなるため非常に良いアプローチだと思います。また、特定のインフラ構成をモジュール化する際に、そのユースケースに特化した設計を避ける助けにもなります。さらに、多くのリリースに依存しすぎていないかチェックする際の参考にもなります。

Workspaceを用いて環境を分ける

Terraformでは、ワークスペースを使って環境を分けることができます。ワークスペースを使って環境を分けたディレクトリ構成の例です。

terraform-project/
├── main.tf
├── variables.tf
├── outputs.tf
└── modules/
    ├── app/
    ├── database/
    └── network/

ワークスペースを利用すると、開発・ステージング・本番といった環境を、同じコードベースで管理できます。ワークスペースの切り替えは以下のように行います。

# 新しいワークスペースの作成
terraform workspace new <workspace_name>

# ワークスペースの切り替え
terraform workspace select <workspace_name>

# 現在のワークスペースを確認
terraform workspace show

メリット

  • ディレクトリがシンプル
    環境別のフォルダが増えず、コードは1つの場所に集約される。
  • コード共有が容易
    環境によって共通化できるロジックをそのまま使いまわせる。

デメリット

  • ステートが同じバックエンドに保存される
    S3への権限が、すべての環境で同一になる。
  • 環境の切り替え忘れリスク
    実行時のワークスペースを選択し間違えると、想定外の環境に対して変更を加えてしまう恐れがある。CI/CDとか使えば間違えなさそう。
  • 全環境のことを考える必要がある
    ファイルが共通しているためdev環境だけ何かやりたい場合、"dev"をキーにして他の環境には影響がないようにするのかな?

環境ごとにディレクトリを分ける

環境ごとにディレクトリを分ける方法もあります。以下は、環境ごとにディレクトリを分けたディレクトリ構成の例です。

terraform-project/
├── environments/
│   ├── production/
│   │      ├─ main.tf
│   │      ├─ variables.tf
│   │      └─ outputs.tf
│   ├── staging/
│   │      ├─ main.tf
│   │      ├─ variables.tf
│   │      └─ outputs.tf
│   └── development/
│          ├─ main.tf
│          ├─ variables.tf
│          └─ outputs.tf
└── modules/
    ├── app/
    ├── database/
    └── network/

明示的で良いと思います。ただし、環境ごとにディレクトリを分けることでコードの重複が発生しやすくなる点には注意が必要です。重複が多くなる代わりに、コードと実際の環境が明確になるので良いなーという感じです。
environmentsliveだったりするものも見かけます。共通で使うリソースが出てきたときに environmentsだとどこに置くか迷ったりします。

ステートをより細かく分ける

ステートをより細かくするものもあります。

terraform-project/
├── environments/
│   ├── production/
│   │   ├── app/
│   │   ├── database/
│   │   └── network/
│   ├── staging/
│   │   ├── app/
│   │   ├── database/
│   │   └── network/
│   └── development/
│       ├── app/
│       ├── database/
│       └── network/
└── modules/
    ├── app/
    ├── database/
    └── network/

この場合、環境・モジュール単位でステートファイルが独立するため、万が一のトラブルで特定モジュールのデプロイに失敗しても、他のモジュールには影響が及びにくいというメリットがあります。しかし、リソース間の依存関係をTerraformだけで完結させることが難しくなるため、Terragruntなどを併用して、依存関係を整理しながら運用することが多いです。

まとめ

Terraformのディレクトリ構成にはさまざまなアプローチがあり、チームの規模や運用ポリシー、権限管理の考え方によって最適解が変わります。

  • examples/ディレクトリ
    モジュールをわかりやすく提供し、利用者にもメリットが大きい。
  • ワークスペースを用いる構成
    シンプルに同一コードベースで複数環境を扱いたい場合に有効。
  • 環境ごとにディレクトリを分ける構成
    コードが環境ごとに明確になる一方、重複や共通リソースの扱いに注意が必要。
  • さらに細かい単位でステートを分割する構成
    障害切り分けや独立性を高められるが、Terraformでの依存管理が難しくなる可能性がある。

参考

Discussion