Terraform

Terraform Output Values: モジュール出力の設計ガイド(Associate向け)

2026-04-19
NicheeLab編集部

モジュールの出力は、親モジュールや他スタックに提供する“公開API”です。どの属性を、どの形で、どこまで公開するかで、チームの拡張性と安全性が大きく変わります。

本稿では、Terraform Associateレベルで押さえるべき安定仕様に基づき、出力の基本から設計パターン、機密値、依存関係、アンチパターンまでをまとめます。

Outputの基本と宣言

output ブロックは、モジュール外へ値を公開する仕組みです。子モジュールの出力は親から module.<name>.<output> で参照でき、ルートモジュールの出力は terraform output コマンドで取得できます。

出力は式から型が推論されます。必要なら tolist、tomap、toset、tostring などで明示的に形を整えます。description、sensitive、depends_on を指定できます。

  • ルート出力は CLI と -json オプションで参照可能(機密扱いは後述)。
  • 同一モジュール内で output を参照することはできない。内部での再利用は locals を使う。
  • 子の出力は親で module.child.output_name として参照(暗黙に依存関係が張られる)。

基本的な出力の宣言(子→親)

# modules/storage/outputs.tf
output "bucket_id" {
  description = "S3 bucket ID"
  value       = aws_s3_bucket.this.id
}

# root/main.tf
module "storage" {
  source = "./modules/storage"
}

output "app_bucket_id" {
  value       = module.storage.bucket_id
  description = "App uses this bucket"
}

モジュール出力のインターフェース設計

出力は“安定インターフェース”として最小限かつ将来互換を意識して設計します。下位リソースの全属性を丸ごと出すのではなく、利用側が本当に必要とするキー属性(ID、エンドポイント、ARN、ポートなど)に絞るのが基本です。

複数の関連値はオブジェクトでまとめて返すと拡張が容易です。個別スカラーを乱立させるより、service.endpoint など論理名でグルーピングすると命名衝突を避けられます。

  • 公開対象は安定しやすい属性に限定(例: エンドポイント、ID、ポート、ロールARN)。
  • 関連値は1つのオブジェクト出力にまとめ、将来キーを追加しても後方互換が保てる形にする。
  • 可視性と責務を明確化し、密結合(内部実装の漏洩)を避ける。機密値は原則非公開。
構造/手段主な用途公開範囲主な注意点
locals(非出力)モジュール内部の計算・再利用非公開(内部限定)外部利用を想定しない。テストしやすく保つ。
出力(スカラー)単一のキー属性(ID, ARN)共有親モジュール属性増に弱い。命名が増えがち。
出力(オブジェクト)関連属性のまとまった公開親モジュールキー名の契約がAPI。後方互換を壊さない。
data.terraform_remote_state別ステートからの値取得(スタック間連携)他ワークスペース/状態ステート依存で結合が強くなる。組織標準とガバナンス必須。

モジュール間の出力フロー(安定インターフェース)

module.networkoutputs: vpc_id, subnets[]module.runtimeinputs: vpc_id, subnetsoutputs: service = { id, name, endpoint }rootuses: module.runtime.service.endpointmodule.network → module.runtime → root

オブジェクト出力でのインターフェース安定化

# modules/runtime/outputs.tf
output "service" {
  description = "Service interface for consumers"
  value = {
    id       = aws_ecs_service.this.id
    name     = aws_ecs_service.this.name
    endpoint = aws_lb.this.dns_name
    port     = 443
  }
}

# root/main.tf(利用側)
module "runtime" {
  source = "./modules/runtime"
  # ...inputs
}

locals {
  service_endpoint = module.runtime.service.endpoint
}

出力の型・構造と形の固定化

出力は式から型推論されます。契約(API)として形を安定させたい場合、toset/tomap/tolist などで明示的に整形し、キー付きオブジェクト(マップ)を構築します。can/try を併用して将来の拡張に備えると安全です。

数値・文字列の曖昧さを避けるため tostring、tonumber を使って表現を統一し、利用側の破壊的変更を防ぎます。

  • リスト順序の意味が薄ければ toset で集合化し、差分ノイズを抑制。
  • マップのキーは安定・ドキュメント化。不要なネストは避ける。
  • try とデフォルトを使い、将来キー追加時の下位互換を確保。

形の明示と後方互換のための整形例

# オブジェクトの形を明示的に構築
locals {
  service_if = {
    id       = aws_ecs_service.this.id
    name     = aws_ecs_service.this.name
    endpoint = aws_lb.this.dns_name
    # まだ無いが将来に備えて try で既定値
    zone_id  = try(aws_lb.this.zone_id, null)
    ports    = toset([443])
  }
}

output "service" {
  value       = local.service_if
  description = "Stable service interface"
}

# 数値/文字列の揺れを抑える
output "replicas" {
  value = tonumber(var.desired_count)
}

機密値の扱いと安全設計

output に sensitive = true を指定、または sensitive() で包むと、計画表示や terraform output で値が伏せられます。ただし状態ファイルには値が格納されます。リモートバックエンドのアクセス制御やワークスペース分離と併せて保護してください。

下流へは機密性が伝播します。必要に応じて nonsensitive() を使って明示的に解除しますが、漏洩リスクを十分に評価してください。

  • 機密値は原則として出力しない。どうしても必要な場合は最小権限で、期間限定の資格情報などを検討。
  • terraform output -json は機密値を伏せたメタ情報のみを返すため、自動化連携での取り扱いを設計段階で決める。
  • State に値は残るため、バックエンド・RBAC・監査を前提とする。

機密値の出力と伝播制御

# パスワードを機密として出力
output "db_password" {
  description = "Generated DB password (avoid exposing if possible)"
  value       = sensitive(random_password.db.result)
  sensitive   = true
}

# 非機密として扱いたいメタ情報のみを公開
output "db" {
  value = {
    endpoint = aws_db_instance.this.address
    port     = aws_db_instance.this.port
    engine   = aws_db_instance.this.engine
  }
}

# 機密の解除は慎重に
output "password_for_debug" {
  value     = nonsensitive(random_password.db.result)
  sensitive = false
  depends_on = [null_resource.allow_debug_window]
}

依存関係と評価タイミング

出力は apply 時点の実値に基づいて評価されます。unknown(計画時未確定)な値は plan 段階では具体化されません。値の算出順序が重要な場合、出力にも depends_on を指定して依存関係を明示できます(Terraform 0.13以降)。

同一モジュール内のリソース間の依存は、通常は参照で自動解決されます。出力はあくまで“外向きの契約”であり、内部の計算や依存解決には locals や明示参照を使います。

  • module.child.output は親で参照すれば自動で依存が張られる。
  • スタック間連携が必要なら data.terraform_remote_state の利用を検討。ただし結合が強くなるため、責務境界とバージョニングを設計する。
  • 出力は同一モジュールの他リソース引数には使えない。内部再利用は locals。

出力での depends_on とスタック間参照の例

# 出力の評価順を明示(post init 処理の完了を待つ)
resource "null_resource" "post" {
  triggers = {
    service_id = aws_ecs_service.this.id
  }
  provisioner "local-exec" {
    command = "echo post-init"
  }
}

output "service_endpoint" {
  value      = aws_lb.this.dns_name
  depends_on = [null_resource.post]
}

# 別ステートからの参照(root 側の例)
data "terraform_remote_state" "network" {
  backend = "s3"
  config = {
    bucket = "tf-states"
    key    = "net/terraform.tfstate"
    region = "ap-northeast-1"
  }
}

module "runtime" {
  source = "./modules/runtime"
  vpc_id  = data.terraform_remote_state.network.outputs.vpc_id
  subnets = data.terraform_remote_state.network.outputs.subnets
}

バージョニングとアンチパターン

出力はモジュールの公開APIです。キー名や意味を変えるのは破壊的変更なので、モジュールのメジャーバージョンアップに合わせます。移行期間は旧出力を残しつつ新出力を追加し、利用側を段階的に移行します。

アンチパターンは、リソース全体をそのまま公開すること、機密値を安易に公開すること、文字列連結で不安定な値を組み立てることです。安定キーに限定し、構造化し、内部実装の漏洩を避けましょう。

  • 破壊的変更はメジャー更新。非破壊はマイナーでキー追加に留める。
  • 旧出力は非推奨化(descriptionにDeprecated)してから一定期間後に削除。
  • “全部出す”のは最後の手段。利用用途を確認して必要最小限を返す。

非破壊移行の例(旧キーを残して新構造へ移行)

# 新API(推奨)
output "service" {
  description = "Preferred aggregated interface"
  value = {
    id       = aws_ecs_service.this.id
    endpoint = aws_lb.this.dns_name
    port     = 443
  }
}

# 旧API(非推奨: 互換用)
output "service_endpoint" {
  description = "Deprecated: use output 'service.endpoint' instead"
  value       = aws_lb.this.dns_name
}

# 利用側は段階的に module.runtime.service.endpoint へ移行

問題で確認

Associate

問題 1

複数チームが利用する共通モジュールで、ECSサービスのID・エンドポイント・ポートを公開したい。将来フィールドが増える可能性があり、後方互換性を維持したい。最も適切な設計はどれか?

  1. ID・エンドポイント・ポートをそれぞれ個別のスカラー出力として3つ公開する
  2. サービスリソース全体(aws_ecs_service.this)をそのまま出力として公開する
  3. ID・エンドポイント・ポートを1つのオブジェクト出力にまとめ、必要に応じてキーを追加できる形にする
  4. terraform_remote_state で他スタックから直接リソース属性を読ませる

正解: C

後方互換性と拡張性を両立するには、関連属性を1つのオブジェクト出力にまとめ、将来はキー追加で非破壊に拡張できる形にするのが最適。スカラー分割はキー増で破壊的になりやすく、リソース全体の露出や remote_state の直接参照は密結合を招く。

よくある質問

output で type を指定できますか?

出力ブロックに type 引数はありません。型は式から推論されます。形を安定させたい場合は tolist/tomap/toset などで明示的に整形し、固定キーのオブジェクトを構築して契約を文書化します.

sensitive = true にしても state に値は保存されますか?

はい。計画表示や terraform output で値は伏せられますが、状態ファイルには保存されます。リモートバックエンドと厳格なアクセス制御、監査で保護してください。

出力に depends_on を書く必要はありますか?

通常は不要です。参照しているリソースやモジュールへの暗黙依存で十分です。評価順を明示したい特殊なケースのみ、出力に depends_on を付けます(Terraform 0.13以降でサポート)。

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

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の記事一覧 (101件)
© 2026 NicheeLab All rights reserved.