Terraform の設定ファイルは HCL で書かれ、最小単位は「ブロック」「属性(引数)」「式」。この3つの違いと関係をつかむと、どのリソースでも迷わず読めて書けます。
本稿は公式ドキュメントの用語と挙動に沿い、Associate 試験の出題傾向を踏まえて、具体例とチェックポイント中心に解説します。
Terraform の .tf ファイルはブロックの集合体です。各ブロックは種類(type)、ラベル(任意、0個以上)、本体({ ... })からなり、本体の中に属性(key = value)や入れ子のブロックが並びます。value の部分に書けるのが式(expression)です。
コメントは # または //、複数行は /* */ が利用できます。識別子は英数字とアンダースコアを用い、先頭は数字不可。ファイルの先頭・末尾に特別な記号は不要で、複数ファイルはディレクトリ単位で結合されます(同一ディレクトリ内の .tf は論理的にマージ)。
HCL 構文の関係(ファイル → ブロック → 属性/入れ子ブロック → 式)
最小構成の例:ブロック内に属性と入れ子ブロック
resource "random_pet" "name" {
length = 2 # 属性(value は number リテラル)
prefix = var.project # 属性(value は式:変数参照)
separator = "-" # 属性(value は string リテラル)
}
output "pet_name" {
value = random_pet.name.id # 式:リソース属性参照
}
ブロックは HCL の構文単位です。書式は block_type "label1" "label2" { ... }。label は 0 個以上で、resource のように type と name の 2 ラベルをとるものが典型です。入れ子のブロック(例:resource 内の lifecycle、provisioner、dynamic など)もあります。
Terraform の公式用語では、ブロック本体の key = value を argument(引数)と呼びますが、一般に attribute とも表現されます。試験やドキュメントでは argument の語が出ても同義と理解しておくと混乱しません。
| 概念 | 役割 | 代表例・書式 | 記述パターン |
|---|---|---|---|
| Block(ブロック) | 構造を規定(型・ラベル・本体) | resource "aws_s3_bucket" "this" { ... } | 入れ子ブロックや属性を内包 |
| Attribute(引数) | ブロックの性質・値を指定 | bucket = "example" | key = value(value は式) |
| Expression(式) | 値を計算・合成 | var.name, aws_vpc.main.id, join(",", list) | リテラル/参照/関数/for/条件 |
ブロックの型とラベル例
# ラベルなし
terraform {
required_version = ">= 1.5.0"
}
# 1 ラベル
variable "project" {
type = string
description = "Project name"
}
# 2 ラベル(type と name)
resource "random_pet" "this" {
length = 2
}
# 入れ子ブロック(lifecycle)
resource "null_resource" "hook" {
triggers = { t = timestamp() }
lifecycle {
prevent_destroy = true
}
}
属性は key = value の形でブロック本体に記述します。value は常に式で、リテラル(string/number/bool)、コレクション(list/set/map)、構造体(object/tuple)、参照、関数呼び出し、for/条件式などが使えます。
文字列は二重引用符。複数行はヒアドキュメント(<<EOT ... EOT)を利用可能。true/false はブール値としてクォートしないのが基本です。型は暗黙変換が効く場面もありますが、variable では type を明示し、必要に応じて tonumber などで整えます。
属性の型と表現例
variable "env" { type = string }
locals {
enabled = true # bool
retries = 3 # number
owners = ["ops", "dev"] # list(string)
tags = { env = var.env } # map(string)
config = { retries = 3, debug = false } # object
message = <<-EOT
Hello ${var.env}
EOT
}
output "tags" {
value = merge(local.tags, { app = "web" }) # 関数呼び出しも式
}
式は値を作るための構文です。参照(var.x、local.y、resource.attr)、関数(merge, join, coalesce など)、条件演算子(cond ? x : y)、for 式(リスト/マップ内包表記)、スプラット演算子([*])などが代表です。
0.12+ では多くの場所で ${} を不要に記述できます。文字列中で式を埋め込むときは "name-${var.env}" のように補間を使います。計画時に未確定の値(unknown value)は「known after apply」となり、関数や比較に制約が出る点に注意します。
式の具体例(参照・関数・条件・for)
variable "names" { type = list(string) }
locals {
upper_names = [for n in var.names : upper(n)]
name_map = { for idx, n in var.names : idx => n }
pick = length(var.names) > 0 ? var.names[0] : "default"
tags = merge({ env = "dev" }, { app = "api" })
}
output "first_or_default" {
value = local.pick
}
同型リソースの複数作成は for_each または count。キーで管理したい場合や後続参照を安定させたい場合は for_each が有利です。index ベースで十分なら count を選べます。
明示的な依存は depends_on を使用。ただし大半は属性参照で自動的に依存が解決されます。入力値の優先順位は -var / -var-file > *.auto.tfvars > terraform.tfvars > 環境変数 TF_VAR_* > 変数の default(上位が優先)。
for_each と count、depends_on の例
variable "subnets" { type = map(string) } # name => cidr
resource "null_resource" "by_each" {
for_each = var.subnets
triggers = { name = each.key, cidr = each.value }
}
resource "null_resource" "by_count" {
count = 2
triggers = { idx = count.index }
}
resource "null_resource" "needs_each" {
depends_on = [null_resource.by_each]
triggers = { ready = true }
}
true/false を文字列で書かない、数値をクォートしないなど、型の素直な表現が基本。式の中でのみ補間(${})を使い、不要な場所では用いないのが 0.12+ の流儀です。
resource と data の参照接頭辞、出力(output)や locals の評価タイミング、unknown value の扱い(plan 時未確定)を取り違えないように。ブロックと属性の区別(例:lifecycle はブロック、tags は属性の map)も頻出ポイントです。
ありがちな誤りと正しい書き方
# 誤:文字列化された bool
# enabled = "true"
# 正:
enabled = true
# 誤:リソース全体参照
# value = aws_subnet.app
# 正:
value = aws_subnet.app.id
# 誤:不要な補間(0.12+)
# name = "${var.project}"
# 正:
name = var.project
Associate
問題 1
次の設定行は HCL のどの要素を最も正しく表していますか? availability_zones = length(data.aws_availability_zones.current.names)
正解: A
key = value の形で属性(引数)を定義し、value 側は式です。この式は data ソース(data.aws_availability_zones.current.names)を参照し、その長さを length 関数で計算しています。
Terraform 公式が言う argument と attribute は同じ意味ですか?
実質同義です。Terraform の仕様・ドキュメントではブロック本体の key = value を argument(引数)と呼びますが、一般的な解説では attribute と表記されることもあります。試験では argument の語が出ても混乱しないようにしましょう。
${} は今も必要ですか?
0.12 以降、式は素で書けるため多くの場面で不要です。文字列中で変数や参照を埋め込みたいときは "name-${var.env}" のように補間を使います。属性の右辺を丸ごと式にする場合は ${} なしで var.env や local.tags のように書きます。
null と空文字("")の違いは?
null は「値なし」を表し、プロバイダやリソースによりデフォルト適用や未設定扱いになります。空文字は長さ 0 の文字列であり、明示的な値です。条件式や merge の結果で意図せず空文字が入らないよう、coalesce や try でガードすると安全です。
NicheeLab編集部
データエンジニアリング・クラウド資格の専門家。Databricks・Snowflake等の認定資格を保有し、実務経験に基づいた問題作成・解説を行っています。NicheeLab運営。
Terraform Authoring & Ops Pro: 上位資格の範囲と対策
上位レベルを想定したTerraformの設計・運用ドメインを整理し、実務で通用する対策を提示。モジュール設計、ステート運...
Terraform Providers の基本: プラグイン型アーキテクチャを正しく使いこなす
Associate レベルで押さえるべき Provider の基礎、インストール、バージョニング、認証、エイリアス運用を...
Terraform Resourceブロック徹底ガイド: 最小単位のリソース定義
Associateレベルで押さえるべきResourceブロックの構造、依存関係、メタ引数、ライフサイクル制御を実務目線で...
Terraform Data Source徹底理解:既存リソースの参照で壊さず足す
Terraform Associate向けに、Data Sourceを用いた既存リソース参照の基本、選択基準、評価順序、...
terraform init 実務と試験に効く: backend・provider の初期化を正しく設計する
Terraform Associate 向けに、terraform init の役割と backend・provider...