Terraform のディレクトリ構成について考える
はじめに
Terraform のディレクトリ構成についてまとめます。
Module
Terraform では、1 つのディレクトリを Module 単位として扱います。Terraform コマンド実行時、Module 内のすべての .tf ファイルが読み込まれ、リソース定義や変数、出力値などがまとめられます。
ルートモジュール
ルートモジュールは、「リソースと対応するModule」です。
ルートモジュールには1つのtfstateファイルが存在しており、ディレクトリ内でのterraform init
コマンドの実行が必要です。
子モジュール
子モジュールは、他の Module(通常はルートモジュール)から呼び出される再利用可能な Module です。子モジュール単体で terraform init を実行する必要はなく、ルートモジュールに統合して利用されます。
ディレクトリ構成
Terraform の構成を「env」「usecases」「modules」の 3 つのディレクトリに分割しています。これにより、環境ごとのルートモジュール、ユースケースごとの構成、そして再利用可能な子モジュールの管理が容易になります。
各ディレクトリの詳細な説明
サンプルツリー(細かい部分は考慮していない)
project-root/
├── env/
│ ├── dev/
│ │ ├── main.tf # dev環境のルートモジュール(usecasesを呼び出す)
│ │ ├── variables.tf
│ │ ├── backend.tf
│ │ └── provider.tf
│ └── prod/
│ ├── main.tf # prod環境のルートモジュール(usecasesを呼び出す)
│ ├── variables.tf
│ ├── backend.tf
│ └── provider.tf
├── usecases/
│ ├── vpc/ # VPCユースケース:プロジェクト固有のネットワーク構成
│ │ ├── main.tf # modules/vpc(またはネットワーク関連のモジュール)を呼び出し、具体的なパラメータを設定
│ │ ├── variables.tf
│ │ ├── outputs.tf
│ │
│ └── ecs/ # ECSユースケース:VPC情報などを参照してECSクラスタを構築
│ ├── main.tf # modules/ecs(または複数の汎用モジュールを組み合わせる)を呼び出す
│ ├── variables.tf
│ ├── outputs.tf
│
└── modules/
├── ecr/ # 汎用モジュール:ECRの作成など、複数のユースケースで再利用可能
│ ├── main.tf
│ ├── variables.tf
│ ├── outputs.tf
│
└── SSM/
├── main.tf
├── variables.tf
├── outputs.tf
env ディレクトリ
目的:
各環境(例: 開発、ステージング、本番)ごとに独立した設定と状態管理を行います。
ここに配置されたディレクトリはルートモジュールとして機能し、各環境ごとに terraform init
、terraform plan
、terraform apply
を実行します。
各ファイルの役割:
-
main.tf:
環境全体のリソースやユースケースを呼び出すエントリーポイント。usecases
内のモジュールを参照して全体構成を組み立てます。 -
variables.tf:
環境固有の変数(例: リージョン、アカウント情報、環境特有のパラメータ)の定義を行います。 -
backend.tf:
リモート状態管理(tfstate)のバックエンド設定(例: S3、Terraform Cloud など)を記述します。 -
provider.tf:
使用するクラウドプロバイダー(AWS、GCP、Azure など)の設定を定義します。
usecases ディレクトリ
目的:
プロジェクト固有のユースケース(例: VPC、ECSなど)のリソース構成を定義します。
このディレクトリ内では、再利用可能なモジュール(modules)を呼び出し、具体的なパラメータを設定することで、プロジェクトの要件に沿ったインフラを実現します。
各ファイルの役割:
-
main.tf:
ユースケースに必要なリソースやモジュールの呼び出しを定義します。たとえば、VPCユースケースではネットワーク関連のモジュールを呼び出し、ECSユースケースではクラスタやサービスの設定を行います。 -
variables.tf:
ユースケース固有の変数を定義し、モジュールに渡すパラメータを管理します。 -
outputs.tf:
ユースケースの実行結果として出力される情報(例: VPC ID、ECSクラスタ名など)を定義します。
modules ディレクトリ
目的:
複数のユースケースで共通して利用できる再利用可能なモジュールを管理します。
ここでは、ECRの作成、SSMなど、汎用的なリソース定義をまとめ、プロジェクト全体での一貫性と保守性を向上させます。
各ファイルの役割:
-
main.tf:
モジュール固有のリソース定義(例: ECRの作成、SSMなど)を記述します。 -
variables.tf:
モジュールで利用するパラメータを定義し、外部からの入力値により挙動をカスタマイズ可能にします。 -
outputs.tf:
モジュール実行後に返す情報(例: ECRの作成、SSM)を定義します。
運用フロー
-
初期化
- 各環境(例:
env/dev
やenv/prod
)のディレクトリに移動し、terraform init
を実行して、必要なプラグインやバックエンドの設定を初期化します。
- 各環境(例:
-
プラン作成
-
terraform plan
を実行し、変更点や新規作成されるリソースを確認します。これにより、意図しない変更が含まれていないかを事前にチェックします。
-
-
適用
- 環境ごとに
terraform apply
を実行し、インフラリソースを作成・更新します。通常は、開発環境での検証後に本番環境へ展開する流れとなります。
- 環境ごとに
-
変更管理
- 各ディレクトリ(env、usecases、modules)で行ったコードの変更は、Git などのバージョン管理システムで管理します。
- プルリクエストやコードレビューを通じて、変更内容の品質や影響範囲を確認し、適切なテストを実施します。
-
CI/CD の活用
- Terraform のコード変更は CI/CD パイプラインに組み込み、
terraform plan
の自動実行や、検証環境への自動デプロイを行います。 - ステージング環境で十分な検証を行った後、本番環境への適用を自動化または手動で実施します。
- Terraform のコード変更は CI/CD パイプラインに組み込み、
-
保守と拡張
- ユースケースやモジュールの更新が必要な場合、変更内容を十分にテストし、複数のユースケースに影響を及ぼさないよう管理します。
- インフラの拡大に合わせて、ディレクトリ構成やモジュールの設計を見直し、保守性と拡張性を向上させます。
まとめ
-
env:
各環境(開発、ステージング、本番)のルートモジュールとして機能し、環境固有の設定や状態管理(tfstate)を行います。各環境ごとにterraform init
、terraform plan
、terraform apply
を実行してインフラを管理します。 -
usecases:
プロジェクト固有のユースケース(例: VPC、ECS)のリソース構成を定義し、必要に応じて複数のモジュールを組み合わせて実装します。これにより、プロジェクトの特定要件に合わせた柔軟な構成が可能となります。 -
modules:
複数のユースケースで再利用可能な汎用モジュール(例: ECR、SSM)を管理し、コードの再利用性と保守性を向上させます。変更が必要な場合は、ここで一括修正することで全ユースケースに反映されます。
Discussion