🏗️

実践的なTerraform構成設計:モジュール化とベストプラクティス

に公開

はじめに

Terraformを使い始めたものの、「どのようにファイルを整理すればいいのか」「どこまでモジュール化すべきか」といった疑問を持つ方は多いでしょう。本記事では、実際のプロジェクトで使用されている構成を例に、実践的なTerraform設計パターンを解説します。

対象読者

  • Terraformの基本的な書き方は理解している
  • より良い構成設計を学びたい
  • チーム開発でのTerraform運用を考えている

全体構成の設計思想

ディレクトリ構造

terraform/
├── modules/              # 再利用可能なコンポーネント
│   ├── vpc/
│   ├── subnet/
│   ├── ec2_instance/
│   └── security_group/
└── services/             # 環境別の設定
    └── dev/
        ├── main.tf
        ├── var_vpc.tf
        ├── var_ec2.tf
        └── var_secg.tf

この構成の3つの核心原則

  1. 関心の分離: モジュール(what)と環境設定(how)を分離
  2. 再利用性: 同じモジュールを複数環境で利用
  3. 保守性: 変更影響範囲を限定

モジュール設計のベストプラクティス

1. 適切な粒度でのモジュール化

# modules/vpc/main.tf
resource "aws_vpc" "this" {
  cidr_block           = var.cidr_block
  enable_dns_hostnames = true
  enable_dns_support   = true
  
  tags = {
    Name         = var.name
    Environment  = var.tags.Environment
    Owner        = var.tags.Owner
  }
}

ポイント

  • 1つのモジュール = 1つの責任
  • AWSリソース単位でモジュール化
  • 設定値は全て変数化

2. 統一されたファイル構成

各モジュールは以下の3ファイルで構成:

module/
├── main.tf      # リソース定義
├── variable.tf  # 入力パラメータ
└── output.tf    # 出力値

3. 柔軟な設定管理

# services/dev/var_vpc.tf
locals {
  vpc_definitions = {
    dev-vpc = {
      cidr_block = "172.16.0.0/22"
      subnets = {
        dev-subnet-public-alb-1a = {
          cidr_block        = "172.16.0.0/25"
          availability_zone = "ap-northeast-1a"
        }
        # ...
      }
    }
  }
}

メリット

  • 設定の一元管理
  • 環境間での差分が明確
  • 新しい環境追加が容易

実践的な構成パターン

1. for_eachを活用した動的リソース作成

# services/dev/main.tf
module "module_vpcs" {
  source   = "../../modules/vpc"
  for_each = local.vpc_definitions

  name       = each.key
  cidr_block = each.value.cidr_block
  tags       = local.tags
}

2. モジュール間の依存関係管理

module "module_subnets" {
  source   = "../../modules/subnet"
  for_each = local.vpc_definitions

  vpc_id  = module.module_vpcs[each.key].output_vpcs.id
  subnets = each.value.subnets
  tags    = local.tags
}

3. 共通設定の外部化

# services/dev/var_common.tf
locals {
  tags = {
    Environment  = "dev"
    Owner        = "admin"
  }
}

セキュリティ設計のパターン

階層化されたセキュリティグループ

locals {
  secg_definitions = {
    dev-vpc = {
      dev-secg-alb-external = {
        description = "external ALB"
        rules = [
          {
            type        = "ingress"
            protocol    = "tcp"
            from_port   = 443
            to_port     = 443
            cidr_blocks = ["0.0.0.0/0"]
          }
        ]
      }
      dev-secg-ec2-web = {
        description = "Web Instance"
        rules = [
          {
            type                      = "ingress"
            source_security_group_key = "dev-secg-alb-external"
            protocol                  = "tcp"
            from_port                 = 80
            to_port                   = 80
          }
        ]
      }
    }
  }
}

設計原則

  • 最小権限の原則
  • セキュリティグループ間参照の活用
  • 役割別の明確な分離

運用面での考慮事項

1. 状態管理

terraform {
  required_version = ">= 1.12.0"
  
  backend "local" {
    path = "./terraform.tfstate"
  }
}

本番環境では

  • S3 + DynamoDBでリモート状態管理
  • 状態ファイルの暗号化
  • 状態ロックの実装

2. プロバイダー設定

provider "aws" {
  region  = "ap-northeast-1"
  profile = "dev-profile"
}

3. タグ戦略

locals {
  tags_ec2_control = {
    Environment   = "dev"
    Owner         = "admin"
    AutoStartStop = true  # 自動起動停止用
  }
}

この構成の利点

1. スケーラビリティ

  • 新環境(staging, prod)の追加が容易
  • 設定ファイルをコピーして値を変更するだけ

2. 保守性

  • 変更影響範囲が限定的
  • モジュールの修正が全環境に反映

3. 可読性

  • 設定が構造化されている
  • 役割ごとにファイルが分離

4. 再利用性

  • モジュールが環境に依存しない
  • 他プロジェクトでも利用可能

まとめ

良いTerraform構成の要素:

  1. 適切な抽象化: モジュールと環境設定の分離
  2. 一貫性: 命名規則とファイル構成の統一
  3. 柔軟性: 設定の外部化と構造化
  4. セキュリティ: 最小権限とベストプラクティスの適用

この構成パターンを参考に、プロジェクトの規模や要件に応じてカスタマイズしてください。重要なのは、チーム全体で一貫した設計原則を共有することです。

次のステップ

  • CI/CDパイプラインとの統合
  • terraform planの自動化
  • セキュリティスキャンの導入
  • コスト監視の実装

Discussion