★ 初級

03. 値(variable / local / output)

Terraform の「値」には 3 つの場所 があります。variable は外から受け取る値、local は中で計算する値、output は外に返す値。役割をちゃんと分けると、コードがぐっと読みやすくなります。

3 種類の使い分け

役割参照する書き方使う場面
variable外から受け取る入力var.NAME環境ごとに変えたい値(リージョン、サイズ)
local内部で計算する中間値local.NAME長い式の名前付け、共通タグ
output外に出す結果(モジュールから親へ)VPC ID を別モジュールに渡す等

variable(入力)

variable "region" {
  type        = string
  description = "AWS リージョン"
  default     = "ap-northeast-1"
}

variable "instance_type" {
  type    = string
  default = "t3.micro"
}

variable "subnet_cidrs" {
  type    = list(string)
  default = ["10.0.1.0/24", "10.0.2.0/24"]
}

variable "tags" {
  type = map(string)
  default = {
    Project = "hcl-guide"
    Env     = "dev"
  }
}

variable の主要属性

属性意味
type受け付ける型(次章)。型を書くとミス値で弾かれる
default省略時の値。書かないと「必須入力」
description説明。terraform plan やドキュメント生成で使われる
sensitivetrue で plan/apply 出力にマスク表示
nullablefalsenull 不可(デフォルト true)
validation値の妥当性チェック(後述)

variable に値を渡す方法と優先順位

同じ変数に複数の経路から値が来ると、下に行くほど強い(後から上書き)

  1. variable の default(最弱)
  2. 環境変数 TF_VAR_NAME
  3. terraform.tfvars
  4. terraform.tfvars.json
  5. *.auto.tfvars / *.auto.tfvars.json(辞書順に)
  6. CLI の -var-file / -var(最強)

tfvars ファイルの書き方

# terraform.tfvars
region        = "us-east-1"
instance_type = "t3.small"
subnet_cidrs  = ["10.10.1.0/24", "10.10.2.0/24"]
# 環境ごとの tfvars を CLI で指定
terraform apply -var-file=envs/prd/terraform.tfvars

# ピンポイントで上書き
terraform apply -var="instance_type=t3.large"

# 環境変数で渡す(自動化で便利)
export TF_VAR_region=ap-northeast-1
terraform apply

validation で値を検証する

受け取った値が「想定外」で apply が走ってしまう前に、validation で止められます。

variable "environment" {
  type        = string
  description = "環境名"

  validation {
    condition     = contains(["dev", "stg", "prd"], var.environment)
    error_message = "environment は dev / stg / prd のいずれかにしてください。"
  }
}

variable "vpc_cidr" {
  type = string

  validation {
    condition     = can(cidrnetmask(var.vpc_cidr))
    error_message = "vpc_cidr は有効な CIDR でなければなりません(例: 10.0.0.0/16)。"
  }
}

locals(内部計算)

locals は「式の結果に名前を付ける」場所。同じ式を 3 か所で使うなら local にまとめると変更が 1 か所で済みます。

locals {
  name_prefix = "${var.project}-${var.environment}"
  is_prod     = var.environment == "prd"

  common_tags = {
    Project   = var.project
    Env       = var.environment
    ManagedBy = "Terraform"
  }
}

resource "aws_s3_bucket" "logs" {
  bucket = "${local.name_prefix}-logs"
  tags   = local.common_tags
}

resource "aws_s3_bucket" "data" {
  bucket = "${local.name_prefix}-data"
  tags   = local.common_tags
}
注意 ブロック名は locals(複数形)ですが、参照は local.NAME(単数形)です。間違えやすいポイント。

output(出力)

「root モジュール」(プロジェクト直下)の output は terraform apply の最後に CLI に表示されます。「子モジュール」の output は親から module.NAME.OUTPUT で参照できます。

output "vpc_id" {
  description = "作成した VPC の ID"
  value       = aws_vpc.main.id
}

output "public_subnet_ids" {
  value = [for s in aws_subnet.public : s.id]
}

# 機密値は sensitive = true でマスク
output "db_password" {
  value     = random_password.db.result
  sensitive = true
}

子モジュールの出力を親で使う

# 親 (root)
module "network" {
  source = "./modules/network"
  cidr   = "10.0.0.0/16"
}

resource "aws_instance" "web" {
  subnet_id = module.network.public_subnet_ids[0]   # ← 子の output を参照
  # ...
}