Terraform

Terraformモジュール設計パターン実戦ガイド: コンポジット・レイヤー・単機能

2026-04-19
NicheeLab編集部

ハブ記事: Terraform モジュール 完全ガイド

設計・配布・運用まで Terraform モジュールの全体像を一望できるハブ記事

Terraformは同じ結果でも設計の切り方で運用コストと失敗時の影響が大きく変わります。本稿では単機能モジュール、コンポジットモジュール、レイヤーモデルを使い分けるための具体指針を示します。

HashiCorp公式の一般的な挙動に基づき、安定的な概念に絞って説明します。機能は各クラウドやバージョンで差異が出やすいため、パターン選定は保守性と適用順序の明確化を優先します。

モジュール設計パターンの全体像

単機能モジュールは、1つの明確な責務(例: VPC、サブネット、セキュリティグループなど)に集中し、入力と出力を最小限に絞ります。コンポジットモジュールは、複数の単機能モジュールを束ね、ガードレールや標準設定を内包して再利用性を高めます。レイヤーは、ルートモジュール(スタック)を境界として、適用順序や責任分離を保つための構造です(例: Bootstrap、Network、Platform、Application)。

実務では、単機能で細かく分割し過ぎると利用側の負荷が上がり、逆に巨大なコンポジットや単一レイヤーに寄せすぎると失敗時の影響範囲が広がります。組織の変更頻度と運用体制に合わせたバランスが重要です。

  • 単機能: 小さく作り、I/Oを安定化。差分が明確でテストしやすい
  • コンポジット: 組織標準のガードレール(タグ、暗号化、命名規則)を内包
  • レイヤー: 適用順序と責務境界を強制し、環境(dev/stg/prod)単位で並列運用しやすくする
観点単機能モジュールコンポジットモジュールレイヤー(ルートモジュール)
目的責務を最小化し再利用性を高める単機能を組み合わせて標準を内包適用順序と境界の明確化
責務範囲リソース種別または小さなまとまりワークロード単位やドメイン単位インフラの階層(Network/Platform/App等)
入出力の粒度少数・厳格な型・安定した出力入力はまとめたオブジェクト、出力は代表値他レイヤーに渡す最小のアウトプット
依存関係の扱い明示的に親へ委ねる子モジュール間の順序は内部で調整他レイヤーとは出力を介して疎結合
適用シーン単体の部品化、テスト容易性重視標準構成の迅速展開環境分離、責任分担、並列デプロイ
失敗時の影響小さい(ロールバック容易)中程度(束ねた範囲)大きいが境界外には波及しづらい

単機能モジュール: 小さく明確なインターフェイス

単機能モジュールは、入力の型を厳格にし、デフォルトとバリデーションを活用して利用者の誤入力を防ぎます。出力は後段で必要な最小限に絞り、破壊的変更が発生しにくい設計にします。

変数はスカラーや小さなオブジェクトに留め、曖昧なマップで何でも受ける設計は避けます。出力に機微情報が含まれる場合は sensitive を付与し、上位の plan 表示に不用意に露出しないようにします。

  • 変数は型指定を必須化し、validation で範囲・パターンを制約
  • 出力は後続で本当に必要なキーのみに限定
  • 命名規則やタグ付けは入力ではなく、可能ならデフォルト(locals)で一元化
  • 破壊的変更はメジャーバージョンにまとめ、互換エイリアス出力で移行手順を用意

コンポジットモジュール: 子モジュールの編成とガードレール内包

コンポジットモジュールは、単機能モジュールの配線図を固定化し、タグや暗号化、ログ取得などの組織標準を内包します。利用者は少数の入力を与えるだけで、標準準拠のスタックを得られます。

子モジュールにエイリアス付きプロバイダを渡す場合、providers マップで明示的に伝播する必要があります。for_each を使って複数の子を生成する場合は、安定したキー(例: 論理名)で差分を抑えます。

  • 標準タグや暗号化既定値は locals で集中管理し、子へ明示的に渡す
  • for_each のキーは不変な論理名を使い、差分ノイズを抑制
  • 子モジュールのバージョンを固定し、段階的に上げる
  • プロバイダの alias を使う場合は providers で伝播を明示

コンポジットモジュールの骨子例(network_stack)

variable "name" { type = string }
variable "region" { type = string }
variable "network" {
  type = object({
    cidr_block = string,
    subnets = map(object({ az = string, cidr_block = string }))
  })
}
variable "security_rules" { type = list(object({
  description = string,
  protocol    = string,
  from_port   = number,
  to_port     = number,
  cidr_blocks = list(string)
})) }

locals {
  default_tags = { "managed-by" = "terraform", "stack" = var.name }
}

provider "aws" { region = var.region }

module "vpc" {
  source     = "../modules/vpc"
  name       = var.name
  cidr_block = var.network.cidr_block
  tags       = local.default_tags
}

module "subnet" {
  for_each   = var.network.subnets
  source     = "../modules/subnet"
  vpc_id     = module.vpc.id
  az         = each.value.az
  cidr_block = each.value.cidr_block
  tags       = local.default_tags
}

module "sg" {
  source   = "../modules/security_group"
  vpc_id   = module.vpc.id
  name     = "${var.name}-base"
  rules    = var.security_rules
  tags     = local.default_tags
}

output "vpc_id" { value = module.vpc.id }
output "subnet_ids" { value = [for s in module.subnet : s.id] }
output "security_group_id" { value = module.sg.id }

レイヤー: 適用順序と環境境界の分離

レイヤーはルートモジュールの単位で分割し、適用順序を明確にします。典型例は Bootstrap(バックエンド・IAM最小権限)、Network(VPC等)、Platform(EKS/ECS/Compute基盤)、Application(サービス)の4層です。各レイヤーは独立した状態を持ち、他レイヤーとの連携は出力を通じて行います。

レイヤー間の依存は出力を介した疎結合に留めます。どうしても別レイヤーの値が必要な場合は、data.terraform_remote_state を使って読み出しますが、循環依存や過剰な参照に注意します。環境(dev/stg/prod)はディレクトリ分割とバックエンド分離で並列運用し、CIでレイヤー順に plan/apply します。

  • 各レイヤーは独立したバックエンド(状態)とロックを持つ
  • レイヤー間の通信は最小限の出力に限定し、循環参照を避ける
  • 環境はディレクトリ/バックエンドで分離し、必要に応じてワークスペースを補助的に使用
  • パイプラインで Network → Platform → Application の順序を強制
Layer 0: Bootstrap(Backend, IAM minima)Layer 1: Network(VPC, Subnet, SG, NAT)Layer 2: Platform(EKS/ECS/ASG, Observability)Layer 3: Application(services, ALB, DNS)レイヤー構成の例(環境は並列に展開)各レイヤーは独立State。dev/stg/prodは同構成を横に並べて運用。

バージョニングと互換性: 壊さないための約束事

モジュールはセマンティックバージョニングを採用し、破壊的変更(入力名の変更、出力削除、リソース置換を強制する論理変更)はメジャーアップ時にまとめます。change log と移行手順を必ず添えます。

利用側では required_version と required_providers で Terraform本体とプロバイダを固定し、レジストリ配布のモジュールは version で制約します。子モジュールが特定のプロバイダ設定を要求する場合(alias 等)は、providers マップで明示的に渡せるようにドキュメント化します。

  • 破壊的変更はメジャー、後方互換の追加はマイナー、バグ修正はパッチ
  • 入力の追加はデフォルトを付け、既存利用者に影響を出さない
  • 出力の改名は当面は両方残し、非推奨期間を設ける
  • required_providers と providerバージョン範囲の整合をCIで確認

試験で狙われやすいポイントとアンチパターン

プロ試験では、責務分離、依存の取り扱い、プロバイダ伝播、for_each と count の選択、センシティブ情報の扱いが頻出です。モジュール境界での状態分離と、出力の最小化が正解に寄りやすい傾向があります。

アンチパターンとして、なんでも受けるマップ変数、巨大モジュールの一括適用、レイヤー跨ぎの過剰な remote_state 参照、可変なキーでの for_each、プロバイダ alias の未伝播などがあります。

  • for_each は安定キー(論理名)で。count は順序変化に弱いケースがある
  • module に depends_on は使えるが、乱用せず出力を介した依存を優先
  • sensitive 出力は必要最小にし、上位の plan 露出を避ける
  • プロバイダ alias を子に渡す場合は module ブロックの providers で明示
  • 環境分離はワークスペース単独に依存せず、状態と権限境界を分ける

問題で確認

Pro

問題 1

複数環境(dev/stg/prod)で、組織標準のタグ・暗号化・ネットワーク設計を強制しつつ、アプリごとの違いは最小限の入力で吸収したい。失敗時の影響範囲は小さく保ち、適用順序も明確にしたい。最も適切な設計はどれか。

  1. 単機能モジュールを組み合わせたコンポジットを各レイヤー(Bootstrap/Network/Platform/Application)に用意し、環境ごとにレイヤー単位で状態を分離する
  2. 単一の巨大ルートモジュールに全環境・全レイヤーを集約し、一度の apply で全てを作成する
  3. 全リソースを単機能モジュール化して直接ルートから個別呼び出しし、都度タグや暗号化を入力で渡す
  4. モジュールは使わず、既存リソースは data ソースで参照して都度リソースを追加する

正解: A

標準設定を内包したコンポジットで入力負荷と逸脱を抑え、レイヤー化で適用順序と状態境界を明確化するのが要件に合致します。巨大モノリスは影響範囲が広く、単機能の直列配線は入力負荷と逸脱リスクが高い。data のみでは作成と標準強制ができません。

よくある質問

環境分離はディレクトリとワークスペースのどちらを使うべきですか?

本番運用ではディレクトリ分割とバックエンド(状態)分離を基本にし、必要に応じてワークスペースを補助的に使います。これにより権限境界、ロック、ライフサイクルを環境ごとに独立させやすくなります。

レイヤー間の値受け渡しは変数で渡すか、terraform_remote_state を使うべきですか?

同一レイヤー内のモジュール間は変数・出力で直接渡し、レイヤーを跨ぐ場合のみ terraform_remote_state で最小限の出力を参照します。循環依存や過剰な参照は避け、境界は疎結合に保ちます.

プロバイダのバージョンと alias をモジュールでどう扱えばよいですか?

ルートで required_providers にバージョン範囲を明示し、必要なら別リージョン等に alias を定義します。子モジュールへは module ブロックの providers 引数で alias を明示的に渡します。モジュール側の README には期待するプロバイダ設定を記載し、互換性を保てるようにします。

この記事で学んだ内容を問題で確認しましょう

16,000問以上の問題で実力チェック

無料で問題を解いてみる
この記事の著者

NicheeLab編集部

データエンジニアリング・クラウド資格の専門家。Databricks・Snowflake等の認定資格を保有し、実務経験に基づいた問題作成・解説を行っています。NicheeLab運営。


関連記事
Terraform

Terraform HCL 構文の基礎:Block / Attribute / Expression を正しく使い分ける

Terraform Associate で頻出の HCL 構文を、ブロック・属性・式の3視点で整理。実務で迷いがちな書き...

Terraform

Terraform Authoring & Ops Pro: 上位資格の範囲と対策

上位レベルを想定したTerraformの設計・運用ドメインを整理し、実務で通用する対策を提示。モジュール設計、ステート運...

Terraform

Terraform Providers の基本: プラグイン型アーキテクチャを正しく使いこなす

Associate レベルで押さえるべき Provider の基礎、インストール、バージョニング、認証、エイリアス運用を...

Terraform

Terraform Resourceブロック徹底ガイド: 最小単位のリソース定義

Associateレベルで押さえるべきResourceブロックの構造、依存関係、メタ引数、ライフサイクル制御を実務目線で...

Terraform

Terraform Data Source徹底理解:既存リソースの参照で壊さず足す

Terraform Associate向けに、Data Sourceを用いた既存リソース参照の基本、選択基準、評価順序、...

Terraformの記事一覧 (102件)
© 2026 NicheeLab All rights reserved.