mcpField
T
terraform-patterns

terraform-patterns

github.com/alirezarezvaniクラウド・DevOps28.9k623 回インストール2 日前に更新
リポジトリ

terraform-patterns について

インフラチーム向けのTerraformワークフロースキルです。モジュール設計の標準化、ステートの保護、本番向けコードレビューを支援します。レビュー・セキュリティ用コマンドに加え、モジュール品質や設定リスクを調べるコマンドライン分析ツールを備えています。

主な機能

  1. 01Terraformコードレビューコマンド
  2. 02モジュール設計とリファクタリングの指針
  3. 03ステートとバックエンドの安全性チェック
  4. 04モジュール構造のコマンドライン分析ツール
  5. 05.tfファイル向けセキュリティスキャナー
  6. 06CI/CDとドリフト検出のパターン

活用シーン

  1. 01Terraformファイルの構造上の問題をレビュー
  2. 02入出力が明確な再利用可能モジュールの設計
  3. 03インフラコード内の露出したシークレットのスキャン
  4. 04リモートステートとロック設定の確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/alirezarezvani/claude-skills --skill terraform-patterns

インストール後、Claude Code で/terraform-patternsを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
module-patterns.md
state-management.md
scripts/
tf_module_analyzer.py
tf_security_scanner.py

詳細

Terraform のパターン

予測可能なインフラストラクチャ。安全なステート。組み合わせられるモジュール。ドリフトなし。

広大な HCL を、適切に構成された安全な本番環境向けインフラストラクチャコードに変える、独自の方針に基づいた Terraform ワークフローです。モジュール設計、ステート管理、プロバイダーパターン、セキュリティ強化、CI/CD 連携を扱います。

Terraform のチュートリアルではありません。午前 3 時に壊れないインフラストラクチャコードを書くための、具体的な方針をまとめています。


スラッシュコマンド

コマンド内容
/terraform:reviewTerraform コードを分析し、アンチパターン、セキュリティ上の問題、構成上の問題を特定します
/terraform:module適切な入力、出力、構成を備えた Terraform モジュールを設計またはリファクタリングします
/terraform:securityTerraform コードを監査し、セキュリティの脆弱性、シークレットの漏えい、IAM の設定ミスを特定します

このスキルが有効になる場面

ユーザーの次のようなパターンを認識します。

  • 「この Terraform コードをレビューして」
  • 「次のための Terraform モジュールを設計して……」
  • 「Terraform のステートが……」
  • 「リモートステートバックエンドを設定して」
  • 「マルチリージョンの Terraform デプロイ」
  • 「Terraform のセキュリティレビュー」
  • 「モジュール構成のベストプラクティス」
  • 「Terraform の CI/CD パイプライン」
  • .tf ファイル、HCL、Terraform モジュール、ステート管理、プロバイダー設定、Infrastructure as Code に関するあらゆるリクエスト

ユーザーが .tf ファイルを持っている場合、または Terraform でインフラストラクチャをプロビジョニングしようとしている場合、このスキルが適用されます。


ワークフロー

/terraform:review — Terraform コードレビュー
  1. 現在の状態を分析

    • 対象ディレクトリ内のすべての .tf ファイルを読み取ります
    • モジュール構成(フラットかネストか)を特定します
    • リソース、データソース、変数、出力の数を数えます
    • 命名規則を確認します
  2. レビュー用チェックリストを適用

    MODULE STRUCTURE
    ├── Variables have descriptions and type constraints
    ├── Outputs expose only what consumers need
    ├── Resources use consistent naming: {provider}_{type}_{purpose}
    ├── Locals used for computed values and DRY expressions
    └── No hardcoded values — everything parameterized or in locals
    
    STATE & BACKEND
    ├── Remote backend configured (S3, GCS, Azure Blob, Terraform Cloud)
    ├── State locking enabled (DynamoDB for S3, native for others)
    ├── State encryption at rest enabled
    ├── No secrets stored in state (or state access is restricted)
    └── Workspaces or directory isolation for environments
    
    PROVIDERS
    ├── Version constraints use pessimistic operator: ~> 5.0
    ├── Required providers block in terraform {} block
    ├── Provider aliases for multi-region or multi-account
    └── No provider configuration in child modules
    
    SECURITY
    ├── No hardcoded secrets, keys, or passwords
    ├── IAM follows least-privilege principle
    ├── Encryption enabled for storage, databases, secrets
    ├── Security groups are not overly permissive (no 0.0.0.0/0 ingress on sensitive ports)
    └── Sensitive variables marked with sensitive = true
    
  3. レポートを生成

    python3 scripts/tf_module_analyzer.py ./terraform
    
  4. セキュリティスキャンを実行

    python3 scripts/tf_security_scanner.py ./terraform
    
/terraform:module — モジュール設計
  1. モジュールの範囲を特定

    • 単一責任:1 つのモジュールにつき 1 つの論理的なグループ
    • 入力(変数)、出力、リソースの境界を決定します
    • フラットなモジュール(単一ディレクトリ)か、ネストしたモジュール(子モジュールを呼び出す)かを決めます
  2. モジュール設計用チェックリストを適用

    STRUCTURE
    ├── main.tf        — Primary resources
    ├── variables.tf   — All input variables with descriptions and types
    ├── outputs.tf     — All outputs with descriptions
    ├── versions.tf    — terraform {} block with required_providers
    ├── locals.tf      — Computed values and naming conventions
    ├── data.tf        — Data sources (if any)
    └── README.md      — Usage examples and variable documentation
    
    VARIABLES
    ├── Every variable has: description, type, validation (where applicable)
    ├── Sensitive values marked: sensitive = true
    ├── Defaults provided for optional settings
    ├── Use object types for related settings: variable "config" { type = object({...}) }
    └── Validate with: validation { condition = ... }
    
    OUTPUTS
    ├── Output IDs, ARNs, endpoints — things consumers need
    ├── Include description on every output
    ├── Mark sensitive outputs: sensitive = true
    └── Don't output entire resources — only specific attributes
    
    COMPOSITION
    ├── Root module calls child modules
    ├── Child modules never call other child modules
    ├── Pass values explicitly — no hidden data source lookups in child modules
    ├── Provider configuration only in root module
    └── Use module "name" { source = "./modules/name" }
    
  3. モジュールのひな形を生成

    • ボイラープレートを含むファイル構成を出力します
    • 変数の検証ブロックを含めます
    • 適切な場合はライフサイクルルールを追加します
/terraform:security — セキュリティ監査
  1. コードレベルの監査

    確認項目重大度修正方法
    .tf ファイル内のハードコードされたシークレット致命的sensitive = true を指定した変数または Vault を使用します
    * アクションを含む IAM ポリシー致命的特定のアクションとリソースに範囲を絞ります
    ポート 22/3389 で 0.0.0.0/0 を許可するセキュリティグループ致命的既知の CIDR ブロックに制限するか、SSM/bastion を使用します
    暗号化されていない S3 バケット高server_side_encryption_configuration ブロックを追加します
    パブリックアクセスが可能な S3 バケット高aws_s3_bucket_public_access_block を追加します
    暗号化されていない RDS高storage_encrypted = true を設定します
    パブリックアクセスが可能な RDS高publicly_accessible = false を設定します
    CloudTrail が有効になっていない中aws_cloudtrail リソースを追加します
    ステートフルリソースに prevent_destroy がない中lifecycle { prevent_destroy = true } を追加します
    シークレット用の変数に sensitive = true がない中シークレット用変数に sensitive = true を追加します
  2. ステートのセキュリティ監査

    確認項目重大度修正方法
    ローカルのステートファイル致命的暗号化されたリモートバックエンドに移行します
    暗号化されていないリモートステート高バックエンドで暗号化(SSE-S3、KMS)を有効にします
    ステートロックがない高S3 では DynamoDB、TF Cloud ではネイティブのロックを有効にします
    すべてのチームメンバーがステートにアクセス可能中IAM ポリシーまたは TF Cloud のチームを使って制限します
  3. セキュリティレポートを生成

    python3 scripts/tf_security_scanner.py ./terraform
    python3 scripts/tf_security_scanner.py ./terraform --output json
    

ツール

scripts/tf_module_analyzer.py

Terraform のディレクトリ構造とモジュールの品質を分析する CLI ユーティリティです。

機能:

  • リソースとデータソースのカウント
  • 変数と出力の分析(説明、型、検証の不足)
  • 命名規則のチェック
  • モジュール構成の検出
  • ファイル構造の検証
  • JSON およびテキスト形式での出力

使用方法:

# Analyze a Terraform directory
python3 scripts/tf_module_analyzer.py ./terraform

# JSON output
python3 scripts/tf_module_analyzer.py ./terraform --output json

# Analyze a specific module
python3 scripts/tf_module_analyzer.py ./modules/vpc
scripts/tf_security_scanner.py

.tf ファイルをスキャンして、よくあるセキュリティ上の問題を検出する CLI ユーティリティです。

機能:

  • ハードコードされたシークレットの検出(AWS キー、パスワード、トークン)
  • 過度に許容的な IAM ポリシーの検出
  • 外部公開されたセキュリティグループの検出(機密性の高いポートでの 0.0.0.0/0)
  • 暗号化設定の不足をチェック(S3、RDS、EBS)
  • パブリックアクセスの検出(S3、RDS、EC2)
  • 機密変数の監査
  • JSON およびテキスト形式での出力

使用方法:

# Scan a Terraform directory
python3 scripts/tf_security_scanner.py ./terraform

# JSON output
python3 scripts/tf_security_scanner.py ./terraform --output json

# Strict mode (elevate warnings)
python3 scripts/tf_security_scanner.py ./terraform --strict

モジュール設計パターン

パターン 1: フラットモジュール(小規模/中規模プロジェクト)
infrastructure/
├── main.tf          # All resources
├── variables.tf     # All inputs
├── outputs.tf       # All outputs
├── versions.tf      # Provider requirements
├── terraform.tfvars # Environment values (not committed)
└── backend.tf       # Remote state configuration

適している用途: 単一のアプリケーション、リソースが 20 未満、すべてを 1 つのチームが所有する場合。

パターン 2: 入れ子のモジュール(中規模/大規模プロジェクト)
infrastructure/
├── environments/
│   ├── dev/
│   │   ├── main.tf          # Calls modules with dev params
│   │   ├── backend.tf       # Dev state backend
│   │   └── terraform.tfvars
│   ├── staging/
│   │   └── ...
│   └── prod/
│       └── ...
├── modules/
│   ├── networking/
│   │   ├── main.tf
│   │   ├── variables.tf
│   │   └── outputs.tf
│   ├── compute/
│   │   └── ...
│   └── database/
│       └── ...
└── versions.tf

適している用途: 複数の環境、共有インフラストラクチャのパターン、チームでのコラボレーション。

パターン 3: Terragrunt を使用したモノレポ
infrastructure/
├── terragrunt.hcl           # Root config
├── modules/                  # Reusable modules
│   ├── vpc/
│   ├── eks/
│   └── rds/
├── dev/
│   ├── terragrunt.hcl       # Dev overrides
│   ├── vpc/
│   │   └── terragrunt.hcl   # Module invocation
│   └── eks/
│       └── terragrunt.hcl
└── prod/
    ├── terragrunt.hcl
    └── ...

適している用途: 大規模、多数の環境、DRY な設定、チーム単位の分離。


プロバイダー設定パターン

バージョンの固定
terraform {
  required_version = ">= 1.5.0"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"    # Allow 5.x, block 6.0
    }
    random = {
      source  = "hashicorp/random"
      version = "~> 3.5"
    }
  }
}
エイリアスを使用したマルチリージョン
provider "aws" {
  region = "us-east-1"
}

provider "aws" {
  alias  = "west"
  region = "us-west-2"
}

resource "aws_s3_bucket" "primary" {
  bucket = "my-app-primary"
}

resource "aws_s3_bucket" "replica" {
  provider = aws.west
  bucket   = "my-app-replica"
}
Assume Role を使用したマルチアカウント
provider "aws" {
  alias  = "production"
  region = "us-east-1"

  assume_role {
    role_arn = "arn:aws:iam::PROD_ACCOUNT_ID:role/TerraformRole"
  }
}

状態管理の判断ツリー

Single developer, small project?
├── Yes → Local state (but migrate to remote ASAP)
└── No
    ├── Using Terraform Cloud/Enterprise?
    │   └── Yes → TF Cloud native backend (built-in locking, encryption, RBAC)
    └── No
        ├── AWS?
        │   └── S3 + DynamoDB (encryption, locking, versioning)
        ├── GCP?
        │   └── GCS bucket (native locking, encryption)
        ├── Azure?
        │   └── Azure Blob Storage (native locking, encryption)
        └── Other?
            └── Consul or PostgreSQL backend

Environment isolation strategy:
├── Separate state files per environment (recommended)
│   ├── Option A: Separate directories (dev/, staging/, prod/)
│   └── Option B: Terraform workspaces (simpler but less isolation)
└── Single state file for all environments (never do this)

CI/CD 統合パターン

GitHub Actions の Plan/Apply
# .github/workflows/terraform.yml
name: Terraform
on:
  pull_request:
    paths: ['terraform/**']
  push:
    branches: [main]
    paths: ['terraform/**']

jobs:
  plan:
    runs-on: ubuntu-latest
    if: github.event_name == 'pull_request'
    steps:
      - uses: actions/checkout@v4
      - uses: hashicorp/setup-terraform@v3
      - run: terraform init
      - run: terraform validate
      - run: terraform plan -out=tfplan
      - run: terraform show -json tfplan > plan.json
      # Post plan as PR comment

  apply:
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main' && github.event_name == 'push'
    environment: production
    steps:
      - uses: actions/checkout@v4
      - uses: hashicorp/setup-terraform@v3
      - run: terraform init
      - run: terraform apply -auto-approve
ドリフト検出
# Run on schedule to detect drift
name: Drift Detection
on:
  schedule:
    - cron: '0 6 * * 1-5'  # Weekdays at 6 AM

jobs:
  detect:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: hashicorp/setup-terraform@v3
      - run: terraform init
      - run: |
          terraform plan -detailed-exitcode -out=drift.tfplan 2>&1 | tee drift.log
          EXIT_CODE=$?
          if [ $EXIT_CODE -eq 2 ]; then
            echo "DRIFT DETECTED — review drift.log"
            # Send alert (Slack, PagerDuty, etc.)
          fi

先回りして通知する項目

依頼されていなくても、以下の項目を指摘してください。

  • リモートバックエンドが設定されていない → ロックと暗号化を設定し、S3/GCS/Azure Blob に移行してください。
  • プロバイダーにバージョン制約がない → 破壊的なアップグレードを防ぐため、version = "~> X.0" を追加してください。
  • .tf ファイル内にハードコードされたシークレットがある → sensitive = true を設定した変数を使用するか、Vault/SSM と統合してください。
  • IAM ポリシーに "Action": "*" がある → 特定のアクションに範囲を絞ってください。本番環境ではワイルドカードアクションを使用しないでください。
  • SSH/RDP で 0.0.0.0/0 に公開されたセキュリティグループがある → バスティオンの CIDR に制限するか、SSM Session Manager を使用してください。
  • 状態のロックがない → S3 バックエンドでは DynamoDB テーブルを有効にするか、TF Cloud を使用してください。
  • タグのないリソースがある → プロバイダーブロックに default_tags を追加してください。コスト追跡にはタグが必須です。
  • データベース/ストレージに prevent_destroy が設定されていない → 誤削除を防ぐため、lifecycle ブロックを追加してください。

マルチクラウドのプロバイダー設定

単一のルートモジュールで AWS、Azure、GCP にまたがるプロビジョニングが必要な場合に使用します。

プロバイダーのエイリアスパターン
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 3.0"
    }
    google = {
      source  = "hashicorp/google"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = var.aws_region
}

provider "azurerm" {
  features {}
  subscription_id = var.azure_subscription_id
}

provider "google" {
  project = var.gcp_project_id
  region  = var.gcp_region
}
プロバイダー間で共有する変数
variable "environment" {
  description = "Environment name used across all providers"
  type        = string
  validation {
    condition     = contains(["dev", "staging", "prod"], var.environment)
    error_message = "Must be dev, staging, or prod."
  }
}

locals {
  common_tags = {
    environment = var.environment
    managed_by  = "terraform"
    project     = var.project_name
  }
}
マルチクラウドを使用する場合
  • 使用する: 規制要件によりプロバイダー間でのデータレジデンシーが義務付けられている場合、または組織が複数のクラウドですでにワークロードを運用している場合。
  • 使用しない: 「ベンダーロックインの回避」だけでは、十分な正当化理由になりません。マルチクラウドは運用の複雑さを倍増させます。具体的なビジネス要件がない限り、単一のクラウドを優先してください。

OpenTofu との互換性

OpenTofu は Terraform のオープンソースフォークで、MPL 2.0 ライセンスのもと Linux Foundation が管理しています。

Terraform から OpenTofu への移行
# 1. Install OpenTofu
brew install opentofu        # macOS
snap install --classic tofu  # Linux

# 2. Replace the binary — state files are compatible
tofu init                    # Re-initializes with OpenTofu
tofu plan                    # Identical plan output
tofu apply                   # Same apply workflow
ライセンスに関する考慮事項
Terraform (1.6+)OpenTofu
ライセンスBSL 1.1(ソース公開型)MPL 2.0(オープンソース)
商用利用競合製品では制限あり制限なし
コミュニティガバナンスHashiCorpLinux Foundation
機能の同等性

OpenTofu は Terraform 1.6.x の機能に追随しています。OpenTofu 独自の主な追加機能:

  • クライアント側の状態暗号化(tofu init -encryption)
  • 変数/locals の早期評価
  • プロバイダー定義関数
OpenTofu を選ぶ場合
  • サプライチェーンに完全なオープンソースライセンスが必要な場合。
  • Terraform Cloud を使わずに、クライアント側で状態を暗号化したい場合。
  • それ以外の場合は、どちらのツールでも問題ありません。HCL の構文とプロバイダーのエコシステムは同一です。

Infracost との連携

Infracost は、リソースがプロビジョニングされる前に Terraform コードからクラウドコストを見積もります。

PR ワークフロー
# Show cost breakdown for current code
infracost breakdown --path .

# Compare cost difference between current branch and main
infracost diff --path . --compare-to infracost-base.json
GitHub Actions のコストコメント
# .github/workflows/infracost.yml
name: Infracost
on: [pull_request]

jobs:
  cost:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: infracost/actions/setup@v3
        with:
          api-key: ${{ secrets.INFRACOST_API_KEY }}
      - run: infracost breakdown --path ./terraform --format json --out-file /tmp/infracost.json
      - run: infracost comment github --path /tmp/infracost.json --repo $GITHUB_REPOSITORY --pull-request ${{ github.event.pull_request.number }} --github-token ${{ secrets.GITHUB_TOKEN }} --behavior update
予算のしきい値とコストポリシー
# infracost.yml — policy file
version: 2.9.0
policies:
  - path: "*"
    max_monthly_cost: "5000"    # Fail PR if estimated cost exceeds $5,000/month
    max_cost_increase: "500"    # Fail PR if cost increase exceeds $500/month

既存のインフラストラクチャのインポート

手動で作成したリソースを Terraform の管理下に置きます。

terraform import ワークフロー
# 1. Write the resource block first (empty body is fine)
# main.tf:
# resource "aws_s3_bucket" "legacy" {}

# 2. Import the resource into state
terraform import aws_s3_bucket.legacy my-existing-bucket-name

# 3. Run plan to see attribute diff
terraform plan

# 4. Fill in the resource block until plan shows no changes
設定生成を使った一括インポート(Terraform 1.5+)
# Generate HCL for imported resources
terraform plan -generate-config-out=generated.tf

# Review generated.tf, then move resources into proper files
よくある落とし穴
  • インポート後のリソースのドリフト:インポートしたリソースには、Terraform が管理していない属性が含まれている場合があります。すぐに terraform plan を実行し、差分をすべて解消してください。
  • 状態の操作:名前を変更したり、構成を整理したりするには terraform state mv を使用します。リソースを破棄せずに削除するには terraform state rm を使用します。状態を操作する前に必ずバックアップしてください:terraform state pull > backup.tfstate。
  • 機密性の高いデフォルト値:インポートしたリソースによって、状態ファイル内のシークレットが露出する場合があります。状態ファイルへのアクセスを制限し、暗号化を有効にしてください。

Terragrunt のパターン

Terragrunt は Terraform の軽量なラッパーで、複数環境のセットアップ向けに DRY な構成を提供します。

ルートの terragrunt.hcl(共有設定)
# terragrunt.hcl (root)
remote_state {
  backend = "s3"
  generate = {
    path      = "backend.tf"
    if_exists = "overwrite_terragrunt"
  }
  config = {
    bucket         = "my-org-terraform-state"
    key            = "${path_relative_to_include()}/terraform.tfstate"
    region         = "us-east-1"
    encrypt        = true
    dynamodb_table = "terraform-locks"
  }
}
子の terragrunt.hcl(環境ごとのオーバーライド)
# prod/vpc/terragrunt.hcl
include "root" {
  path = find_in_parent_folders()
}

terraform {
  source = "../../modules/vpc"
}

inputs = {
  environment = "prod"
  cidr_block  = "10.0.0.0/16"
}
モジュール間の依存関係
# prod/eks/terragrunt.hcl
dependency "vpc" {
  config_path = "../vpc"
}

inputs = {
  vpc_id     = dependency.vpc.outputs.vpc_id
  subnet_ids = dependency.vpc.outputs.private_subnet_ids
}
Terragrunt が役立つ場面
  • はい:モジュール構造が同一の環境が3つ以上ある場合、バックエンド設定を共有する場合、またはモジュール間の依存関係がある場合。
  • いいえ:単一の環境、小規模なチーム、またはディレクトリベースのシンプルな分離ですでに十分な場合。Terragrunt を導入すると、習得の手間が増え、管理するバイナリも1つ増えます。

インストール

1行でインストール(任意のツール)
git clone https://github.com/alirezarezvani/claude-skills.git
cp -r claude-skills/engineering/terraform-patterns ~/.claude/skills/
複数ツールのインストール
./scripts/convert.sh --skill terraform-patterns --tool codex|gemini|cursor|windsurf|openclaw
OpenClaw
clawhub install terraform-patterns

関連スキル

  • senior-devops — CI/CD、モニタリング、コンテナ化など、より広範な DevOps 領域を扱います。相互補完的です。IaC 固有の作業には terraform-patterns を、パイプラインとインフラストラクチャの運用には senior-devops を使用してください。
  • aws-solution-architect — AWS のアーキテクチャ設計を扱います。相互補完的です。terraform-patterns でインフラストラクチャを実装し、aws-solution-architect で設計します。
  • senior-security — アプリケーションセキュリティを扱います。相互補完的です。terraform-patterns はインフラストラクチャのセキュリティ態勢を、senior-security はアプリケーションレベルの脅威を扱います。
  • ci-cd-pipeline-builder — パイプラインの構築を扱います。相互補完的です。terraform-patterns でインフラストラクチャを定義し、ci-cd-pipeline-builder でデプロイを自動化します。

コメント