outputブロック — 出力値の定義とモジュール間の橋渡し

1. 概要

この記事では、以下の内容を解説します。

  • outputブロックの基本構文と全引数(value / description / sensitive / depends_on / precondition
  • ルートモジュールでのoutputの使い方(terraform outputコマンド)
  • モジュールのoutputを親モジュールで参照する方法
  • sensitive出力のマスク仕様
  • よくある間違いと対処法

outputブロックは、Terraformが作成したリソースの情報(IPアドレス・ARN・ID等)を外部に公開するための仕組みです。モジュール間の値の橋渡しとして特に重要です。


2. outputブロックとは

outputブロックで定義した値は以下の2つの用途に使われます。

用途1: terraform applyの完了後に値を表示する(ルートモジュール)
  → EC2のIPアドレス、RDSのエンドポイント等をコンソールに出力

用途2: モジュールの値を親モジュールで参照できるようにする
  → module.<NAME>.<OUTPUT_NAME> の形式で参照
output "instance_public_ip" {
  description = "EC2インスタンスのパブリックIPアドレス"
  value       = aws_instance.web.public_ip
}

3. 基本構文と全引数

output "<出力名>" {
  value       = <式>          # 必須: 出力する値
  description = "<説明>"      # 任意: 説明文
  sensitive   = <true/false>  # 任意: マスク表示
  depends_on  = [<リソース>]  # 任意: 明示的な依存
}

全引数一覧

引数必須説明
value出力する値。任意のTerraform式が使える
description任意出力の説明文。ドキュメント生成に使われる
sensitive任意trueにするとterraform output時にマスク表示
depends_on任意暗黙的な依存関係が作れない場合に明示する

4. ルートモジュールでのoutput

terraform outputコマンドで確認する

terraform apply実行後、定義したoutputの値が自動表示されます。後から確認するにはterraform outputコマンドを使います。

# main.tf
terraform {
  required_version = ">= 1.9"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

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

data "aws_ami" "amazon_linux_2023" {
  most_recent = true
  owners      = ["amazon"]
  filter {
    name   = "name"
    values = ["al2023-ami-*-x86_64"]
  }
}

resource "aws_instance" "web" {
  ami           = data.aws_ami.amazon_linux_2023.id
  instance_type = "t3.micro"

  tags = {
    Name        = "web"
    Environment = "dev"
    ManagedBy   = "terraform"
  }
}

# outputの定義
output "instance_id" {
  description = "EC2インスタンスのID"
  value       = aws_instance.web.id
}

output "instance_private_ip" {
  description = "EC2インスタンスのプライベートIPアドレス"
  value       = aws_instance.web.private_ip
}
# apply後に出力を確認
terraform output

# 特定の出力だけ確認
terraform output instance_private_ip

# JSON形式で出力(スクリプトとの連携に便利)
terraform output -json

sensitive — 出力のマスク

sensitive = trueを設定すると、terraform outputの標準実行では値がマスクされます。

output "db_password" {
  description = "RDSのマスターパスワード(機密値)"
  value       = random_password.db.result
  sensitive   = true  # コンソール出力でマスクされる
}
# sensitive = trueの出力
terraform output db_password
# → (sensitive value)   ← マスク表示

# 実際の値を確認するには -json または -raw
terraform output -raw db_password
# → your-actual-password

⚠️ 注意: sensitive = trueにしても、terraform.tfstateファイルには平文で記録されます。Stateファイルのアクセス権限管理が必要です。

depends_on — 出力前の明示的な依存

outputブロックにもdepends_onを設定できます。リソース間に暗黙的な依存関係が作れない場合に使います。

output "endpoint" {
  description = "アプリケーションのエンドポイント"
  value       = aws_lb.main.dns_name

  # IAMポリシーのアタッチが完了してからoutputを確定させる
  depends_on = [
    aws_iam_role_policy_attachment.app
  ]
}

5. モジュールでのoutput

サブモジュールの値を親モジュールで参照する

モジュール内でoutputを定義すると、呼び出し元からmodule.<NAME>.<OUTPUT_NAME>の形式で参照できます。

# modules/vpc/outputs.tf(サブモジュール内)
output "vpc_id" {
  description = "作成したVPCのID"
  value       = aws_vpc.main.id
}

output "private_subnet_ids" {
  description = "プライベートサブネットIDのリスト"
  value       = aws_subnet.private[*].id
}

output "public_subnet_ids" {
  description = "パブリックサブネットIDのリスト"
  value       = aws_subnet.public[*].id
}
# main.tf(ルートモジュール)
module "vpc" {
  source = "./modules/vpc"

  cidr_block  = "10.0.0.0/16"
  environment = var.environment
}

# モジュールのoutputを参照: module.<モジュール名>.<output名>
resource "aws_instance" "web" {
  ami           = data.aws_ami.amazon_linux_2023.id
  instance_type = "t3.micro"
  subnet_id     = module.vpc.private_subnet_ids[0]  # ← モジュールのoutputを参照

  tags = {
    Name        = "web"
    Environment = var.environment
    ManagedBy   = "terraform"
  }
}

# ルートのoutputでモジュールの値を再公開
output "vpc_id" {
  description = "VPCのID"
  value       = module.vpc.vpc_id  # モジュールの値をそのまま公開
}

map型のoutputでまとめて出力する

関連する値をまとめてmapで返すパターンは可読性が高くなります。

# モジュールのoutputs.tf
output "endpoints" {
  description = "各サービスのエンドポイント情報"
  value = {
    alb_dns   = aws_lb.main.dns_name
    rds_host  = aws_db_instance.main.address
    redis_host = aws_elasticache_cluster.main.cache_nodes[0].address
  }
}
# 呼び出し元での参照
resource "aws_ssm_parameter" "app_config" {
  name  = "/app/config/alb_endpoint"
  type  = "String"
  value = module.app.endpoints.alb_dns  # mapの属性にアクセス
}

6. よくある間違い

outputの名前でリソースを参照しようとした

# ❌ outputブロックでresourceを参照するとき属性名を間違えやすい
output "instance_ip" {
  value = aws_instance.web.public_ip  # public_ipはattr名
}
# → aws_instance.webがElastic IPなしの場合、空文字列が返る
# → Elastic IPを使う場合は aws_eip.main.public_ip を参照すべき

循環参照エラー

│ Error: Cycle: aws_instance.web, output.instance_ip

原因: outputがリソースを参照し、そのリソースが別の方法でoutputに依存している循環が発生している。

解決方法: depends_onを使わずに参照式だけで依存関係を表現するように整理する。

モジュールのoutputを参照するのにsensitiveが伝播する

モジュール内でsensitive = trueのoutputを定義すると、それを参照するルートモジュールの値も自動的にsensitive扱いになります。

# モジュール内
output "db_connection_string" {
  value     = "mysql://admin:${var.db_password}@${aws_db_instance.main.address}/app"
  sensitive = true
}

# ルートモジュール
output "app_db_url" {
  # module.db.db_connection_stringがsensitiveなため、この値も自動的にsensitiveになる
  value = module.db.db_connection_string
  # sensitive = true を書かなくても自動でマスクされる
}

7. 関連記事


8. まとめ

  • outputブロックで定義した値はterraform apply後にコンソールに表示され、terraform outputコマンドで確認できる
  • モジュール内のoutputはmodule.<NAME>.<OUTPUT_NAME>で親から参照できる
  • 必須引数はvalueのみ。残りは任意(description / sensitive / depends_on
  • sensitive = trueでコンソール出力をマスクできるが、Stateファイルには平文記録される
  • map型のoutputで複数の値をまとめて返すとモジュール設計がすっきりする
  • depends_onはoutputにも設定できるが、必要なケースは少ない

動作確認バージョン: Terraform >= 1.9 / AWS Provider ~> 5.0 対象リージョン: ap-northeast-1(東京) 公式ドキュメント: https://developer.hashicorp.com/terraform/language/values/outputs