ハブ記事: Terraform モジュール 完全ガイド →
設計・配布・運用まで Terraform モジュールの全体像を一望できるハブ記事
モジュールの入力設計は、使いやすさ・安全性・将来の拡張性を左右します。曖昧な型や雑なデフォルトは、計画外の差分や本番事故につながりやすいポイントです。
ここではTerraform公式ドキュメントの振る舞いに基づき、Associate受験でも問われやすい安定概念(型制約、validation、sensitive、tfvarsの優先順位など)を、実務に落とし込める形でまとめます。
入力変数は、モジュールの外部と内部の契約面です。名前・型・説明・既定値を適切に定義することで、意図せぬ値の流入を防ぎ、使い手が迷わないAPIを提供します。
Associateレベルでは、変数ブロックの基本プロパティ(type、default、description、sensitive、nullable)と、var.参照、tfvars/CLI/環境変数からの値供給、およびplan/apply時の型検証の理解が求められます。
最小限の読みやすいvariables.tf例
variable "name" {
type = string
description = "このモジュールで作るリソース群の論理名(接頭辞)"
}
variable "environment" {
type = string
description = "環境識別子(例: dev, stg, prd)"
}
variable "tags" {
type = map(string)
description = "共通タグ。空マップで上書き可"
default = {}
}
# 呼び出し側例
module "app" {
source = "./modules/app"
name = "web"
environment = var.environment
tags = merge(var.tags, { component = "frontend" })
}型を厳格にし、validationで業務制約を明示します。nullableを使ってnull許容かどうかをはっきりさせ、defaultがあるのに不正値が混ざる状況を避けます。
sensitiveは表示抑制であり暗号化ではありません。値はstateに保存されるため、バックエンドの暗号化とアクセス制御も前提に設計します。
実用的なvalidationとnullable/sensitiveの例
variable "environment" {
type = string
description = "dev/stg/prd のいずれか"
validation {
condition = contains(["dev", "stg", "prd"], var.environment)
error_message = "environment は dev, stg, prd のいずれかにしてください。"
}
}
variable "instance_count" {
type = number
description = "起動するインスタンス数(1〜10)"
default = 2
nullable = false
validation {
condition = var.instance_count >= 1 && var.instance_count <= 10
error_message = "instance_count は 1〜10 の範囲で指定してください。"
}
}
variable "cidr_block" {
type = string
description = "CIDR表記 (例: 10.0.0.0/16)"
validation {
condition = can(cidrhost(var.cidr_block, 0))
error_message = "cidr_block は有効なCIDR表記である必要があります。"
}
}
variable "db_password" {
type = string
description = "DBパスワード"
sensitive = true
nullable = false
}相関の強い値(例: ネットワーク周り、スケーリング設定)は、個別変数を乱立させるより、object型で1つにまとめると誤組み合わせを防げます。
Terraform 1.3以降はobject内のoptional属性を型として表現できます。これにより、呼び出し側の指定項目を最小限にしつつ、デフォルト戦略を型レベルで明文化できます。
optional属性つきobjectの例(Terraform 1.3+)
variable "network" {
description = "VPCとサブネット構成"
type = object({
cidr_block = string
private_subnets = list(string)
public_subnets = optional(list(string), [])
dns_hostnames = optional(bool, true)
})
}
# 利用側(モジュール内部)
locals {
all_subnets = concat(var.network.private_subnets, var.network.public_subnets)
}
# サブネット数の整合をvalidationで防ぐ例(必要に応じて)
variable "az_count" {
type = number
description = "利用するAZの数"
default = 2
validation {
condition = length(var.network.private_subnets) >= var.az_count
error_message = "private_subnets は az_count 以上必要です。"
}
}同じ変数に複数の供給源があるときは、Terraformの優先順位で最終値が決まります。試験ではこの順序の理解が問われやすいです。実務では、環境ごとtfvarsを標準化し、必要時のみCLIで一時上書きにするのが堅実です。
自動読み込みファイル(terraform.tfvars, *.auto.tfvars)はチーム標準の入口として便利です。長期的に残すべき値はtfvars側、短命な一時値はCLIや環境変数を使い分けます。
| 供給方法 | 優先度(1=最高) | 適用範囲 | 実務の使い所 |
|---|---|---|---|
| -var | 1 | コマンド都度 | 一時的な上書き・緊急回避。恒久運用は避ける |
| -var-file=PATH | 1 | コマンド都度 | 環境固有ファイルを明示指定。CIでの切替に有効 |
| terraform.tfvars / *.auto.tfvars | 2 | カレントディレクトリ | 標準の環境設定。チームで共有しやすい |
| 環境変数 TF_VAR_name | 3 | シェル/CIのプロセス環境 | 機密やCIの注入。ログ残しを抑制 |
| 変数ブロックのdefault | 4 | モジュール定義 | 安全な既定のみ(曖昧なデフォルトは入れない) |
入力供給と解決の流れ(高優先→低優先)
CLI引数 (-var / -var-file)
|
v (最優先で上書き)
自動読み込み tfvars (terraform.tfvars / *.auto.tfvars)
|
v
環境変数 TF_VAR_*
|
v
変数ブロック default
|
v
root module の var へ束ねられる
|
v
module 呼び出しの引数として渡る
|
v
各 resource の属性に反映され plan/apply現場での使い分け例
# 自動読み込みファイル(チーム標準)
# terraform.tfvars
environment = "stg"
name = "web"
# 本番のみ明示指定(CI)
terraform apply -var-file=envs/prd.tfvars
# 機密は環境変数から注入(CIやローカル)
TF_VAR_db_password="s3cr3t" terraform plan
# 一時上書き(デバッグ用途)
terraform apply -var instance_count=3createやenableのboolフラグは便利ですが、増えすぎると挙動の組み合わせ爆発が起きます。将来の拡張性とテスト容易性を考えると、具体的な集合(map/list/object)で明示する設計の方がメンテナンス性が高いです。
どうしてもフラグにするなら、count/for_eachでリソース生成を完全に切る、依存関係が循環しないことを確認する、といった消し方を徹底します。
フラグ方式と集合方式の対比
# フラグ方式(最小限にとどめる)
variable "create_iam_role" {
type = bool
default = true
}
resource "aws_iam_role" "this" {
count = var.create_iam_role ? 1 : 0
name = "example"
assume_role_policy = data.aws_iam_policy_document.assume.json
}
# 集合方式(推奨)
variable "iam_roles" {
description = "作成するIAMロールの定義マップ"
type = map(object({
name = string
assume_role_policy = string
tags = optional(map(string), {})
}))
default = {}
}
resource "aws_iam_role" "this_map" {
for_each = var.iam_roles
name = each.value.name
assume_role_policy = each.value.assume_role_policy
tags = coalesce(each.value.tags, {})
}sensitiveは表示マスキングであり、状態ファイルの暗号化ではありません。リモートバックエンドの暗号化と権限制御を前提に、出力にもsensitiveを伝播させます。
変数スキーマ変更は破壊的になりがちです。既存入力を保ったまま新フィールドをoptionalで追加し、旧入力は段階的に非推奨化してから削除します。変更点はCHANGELOGと変数のdescriptionに明記しましょう。
機密の伝播と非推奨の明示例
# 機密入力と出力
variable "db_password" {
type = string
description = "DBパスワード"
sensitive = true
}
output "db_password" {
value = var.db_password
sensitive = true
}
# 非推奨の入力を段階的に廃止
variable "instance_type_legacy" {
type = string
default = null
description = "DEPRECATED: 代わりに compute.instance.type を使用。将来のメジャー版で削除予定"
}
variable "compute" {
description = "計算リソース設定(新スキーマ)"
type = object({
instance = object({
type = string
size = optional(number, 1)
})
})
}
Associate
問題 1
同じ変数に対し複数の供給源がある場合、Terraformが最終的に採用する値の優先順位(高→低)として正しいものはどれか?
正解: A
Terraformは、CLI引数(-var / -var-file)が最も優先され、次にtfvars(terraform.tfvars / *.auto.tfvars)、その次が環境変数 TF_VAR_*、最後が変数ブロックのdefaultです。公式ドキュメントに準拠した安定仕様です。
object型のoptional属性はどのTerraformバージョンから使えますか?
Terraform 1.3以降で、object内のoptional属性と既定値の表現がサポートされました。バージョンをまたぐモジュールでは、required_versionで下限を明示するか、従来どおりlocalsで補完する実装にしてください。
variableでsensitive=trueにすれば、値は完全に秘匿されますか?
いいえ。sensitiveは計画出力やUI上の表示をマスクする機能です。stateには値が保存されるため、バックエンドの暗号化(例:Terraform Cloud/Enterprise、S3+KMSなど)と厳格なアクセス制御が必須です。外部サービスに渡れば、その先のログにも注意が必要です。
defaultとnullの使い分けは? nullableはどう設定すべき?
「指定がなければ安全な既定で動かしたい」ならdefaultに安全値をセット。「値が必須で未指定を許容しない」ならnullable=falseにして明示的な入力を求めます。nullは意図的な未設定を表しますが、nullable=trueのままだと意図せぬnull流入に気づきにくくなるため、重要パラメータはnullable=falseを推奨します。
NicheeLab編集部
データエンジニアリング・クラウド資格の専門家。Databricks・Snowflake等の認定資格を保有し、実務経験に基づいた問題作成・解説を行っています。NicheeLab運営。
Terraform HCL 構文の基礎:Block / Attribute / Expression を正しく使い分ける
Terraform Associate で頻出の HCL 構文を、ブロック・属性・式の3視点で整理。実務で迷いがちな書き...
Terraform Authoring & Ops Pro: 上位資格の範囲と対策
上位レベルを想定したTerraformの設計・運用ドメインを整理し、実務で通用する対策を提示。モジュール設計、ステート運...
Terraform Providers の基本: プラグイン型アーキテクチャを正しく使いこなす
Associate レベルで押さえるべき Provider の基礎、インストール、バージョニング、認証、エイリアス運用を...
Terraform Resourceブロック徹底ガイド: 最小単位のリソース定義
Associateレベルで押さえるべきResourceブロックの構造、依存関係、メタ引数、ライフサイクル制御を実務目線で...
Terraform Data Source徹底理解:既存リソースの参照で壊さず足す
Terraform Associate向けに、Data Sourceを用いた既存リソース参照の基本、選択基準、評価順序、...