💁‍♂️

Terraform のディレクトリ構成について考える

2025/02/11に公開

はじめに

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 initterraform planterraform 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)を定義します。


運用フロー

  1. 初期化

    • 各環境(例: env/devenv/prod)のディレクトリに移動し、terraform init を実行して、必要なプラグインやバックエンドの設定を初期化します。
  2. プラン作成

    • terraform plan を実行し、変更点や新規作成されるリソースを確認します。これにより、意図しない変更が含まれていないかを事前にチェックします。
  3. 適用

    • 環境ごとに terraform apply を実行し、インフラリソースを作成・更新します。通常は、開発環境での検証後に本番環境へ展開する流れとなります。
  4. 変更管理

    • 各ディレクトリ(env、usecases、modules)で行ったコードの変更は、Git などのバージョン管理システムで管理します。
    • プルリクエストやコードレビューを通じて、変更内容の品質や影響範囲を確認し、適切なテストを実施します。
  5. CI/CD の活用

    • Terraform のコード変更は CI/CD パイプラインに組み込み、terraform plan の自動実行や、検証環境への自動デプロイを行います。
    • ステージング環境で十分な検証を行った後、本番環境への適用を自動化または手動で実施します。
  6. 保守と拡張

    • ユースケースやモジュールの更新が必要な場合、変更内容を十分にテストし、複数のユースケースに影響を及ぼさないよう管理します。
    • インフラの拡大に合わせて、ディレクトリ構成やモジュールの設計を見直し、保守性と拡張性を向上させます。

まとめ

  • env:
    各環境(開発、ステージング、本番)のルートモジュールとして機能し、環境固有の設定や状態管理(tfstate)を行います。各環境ごとに terraform initterraform planterraform apply を実行してインフラを管理します。

  • usecases:
    プロジェクト固有のユースケース(例: VPC、ECS)のリソース構成を定義し、必要に応じて複数のモジュールを組み合わせて実装します。これにより、プロジェクトの特定要件に合わせた柔軟な構成が可能となります。

  • modules:
    複数のユースケースで再利用可能な汎用モジュール(例: ECR、SSM)を管理し、コードの再利用性と保守性を向上させます。変更が必要な場合は、ここで一括修正することで全ユースケースに反映されます。

BIDIRE

Discussion