1. 概要
この記事では、以下の内容を解説します。
variableブロックの基本構文と全引数(type / default / description / sensitive / nullable / validation)- 型制約の書き方(string / number / bool / list / map / object / tuple / any)
- 変数に値を渡す方法(tfvars / -var / 環境変数)の優先順位
- 機密値を扱うための
sensitiveオプション validationブロックによる入力チェック- AWSを使った実践的なコード例
localsとの使い分け
variableブロックは、Terraformコードを環境(dev/stg/prd)やプロジェクトごとに柔軟に使い回すための仕組みです。コードに値をハードコードするのではなく、変数として外部から受け取ることで、再利用性と保守性が大幅に向上します。
2. Terraformにおける位置付け
variableブロックとは
variable(入力変数)はTerraformの外部から値を渡すための仕組みです。
dev.tfvars / -var オプション / 環境変数
↓
variable ブロック(変数の受け口)
↓
resource ブロックで参照(var.xxxで参照)
例えば「環境によってEC2のインスタンスタイプを変えたい」という場合、インスタンスタイプをvariableで定義しておき、dev環境ではt3.micro、prd環境ではt3.mediumを渡すことができます。
localsとの違い
variableと混同されやすいlocalsとの主な違いを以下に示します。
| 比較項目 | variable | locals |
|---|---|---|
| 外部から値を変えられるか | ✅ 変えられる(tfvars等) | ❌ コード内で固定 |
| Terraformの外部から渡すか | ✅ ユーザーや CI が渡す | ❌ コード内で計算 |
| 動的な式を定義できるか | ❌ 式は書けない(値のみ) | ✅ 式・計算結果を定義できる |
| 主な用途 | 環境・設定値の切り替え | 繰り返しの式に名前を付ける |
判断の目安:
- 「
terraform applyのたびに違う値を渡す可能性がある」→variable - 「コード内で同じ式や計算を何度も書いている」→
locals
詳細は「locals vs variableの違い」を参照してください。
3. 基本構文
variable "<変数名>" {
# 引数(すべて省略可能)
type = <型>
default = <デフォルト値>
description = "<説明>"
sensitive = <true/false>
nullable = <true/false>
validation {
condition = <条件式>
error_message = "<エラーメッセージ>"
}
}
変数の値は var.<変数名> で参照します。
variable "instance_type" {
type = string
default = "t3.micro"
}
resource "aws_instance" "web" {
instance_type = var.instance_type # ← var.変数名 で参照
}
4. 詳細解説
全引数一覧
| 引数 | 型 | 必須 | デフォルト | 説明 |
|---|---|---|---|---|
type | 型制約 | 任意 | any | 受け取る値の型を制限する |
default | 任意 | 任意 | なし | デフォルト値。指定なしの場合、apply時に入力を求められる |
description | string | 任意 | "" | 変数の説明(terraform-docs等のドキュメント生成に使われる) |
sensitive | bool | 任意 | false | trueにすると、plan/apply出力でマスクされる |
nullable | bool | 任意 | true | falseにすると、この変数にnullを渡すことを禁止する |
validation | ブロック | 任意 | なし | 入力値のカスタムバリデーション |
type — 型制約
type引数で受け取る値の型を指定します。型が一致しない値が渡された場合はエラーになります。
プリミティブ型
variable "env_name" {
type = string # "dev", "stg", "prd" など
}
variable "instance_count" {
type = number # 1, 2, 3 など(整数・小数を含む)
}
variable "enable_deletion_protection" {
type = bool # true / false
}
コレクション型
# list: 順序があり、同じ型の要素が並ぶ
variable "availability_zones" {
type = list(string)
default = ["ap-northeast-1a", "ap-northeast-1c"]
}
# map: 文字列をキーとして値を持つ
variable "instance_types" {
type = map(string)
default = {
dev = "t3.micro"
stg = "t3.small"
prd = "t3.medium"
}
}
# set: 重複を許さないリスト(for_eachによく使う)
variable "allowed_cidr_blocks" {
type = set(string)
default = ["10.0.0.0/8", "172.16.0.0/12"]
}
構造型
# object: 属性ごとに型を指定できる構造体
variable "database_config" {
type = object({
instance_class = string
allocated_storage = number
multi_az = bool
})
default = {
instance_class = "db.t3.medium"
allocated_storage = 20
multi_az = false
}
}
# tuple: 要素ごとに型が異なるリスト(使用頻度は低い)
variable "network_config" {
type = tuple([string, number])
# 例: ["10.0.0.0/16", 24]
}
optional() — objectの省略可能属性(Terraform 1.3以降)
object型の属性を省略可能にするにはoptional()を使います。
variable "server_config" {
type = object({
instance_type = string # 必須
volume_size = optional(number, 20) # 省略時は 20 が使われる
tags = optional(map(string), {}) # 省略時は空のmapが使われる
})
default = {
instance_type = "t3.micro"
# volume_size と tags は省略可能(defaultが適用される)
}
}
any 型
variable "tags" {
type = any # 型制約なし
default = {}
}
⚠️ 注意:
any型は型チェックが行われないため、意図しない型の値が渡されてもエラーになりません。型が明確な場合はanyを避け、具体的な型を指定することを推奨します。
default — デフォルト値
defaultを設定すると、値が渡されなかった場合にそのデフォルト値が使われます。defaultを設定しない場合は、terraform apply時に値の入力が求められます。
# デフォルトあり: 値が渡されなければ "dev" が使われる
variable "environment" {
type = string
default = "dev"
}
# デフォルトなし: apply時に必ず値を指定する必要がある
variable "aws_account_id" {
type = string
description = "AWSアカウントID"
# defaultなし → apply時に入力を求められる
}
sensitive — 機密値のマスク
sensitive = trueを設定すると、terraform planやterraform applyの出力でその変数の値がマスク((sensitive value)と表示)されます。
variable "db_password" {
type = string
sensitive = true # plan/apply出力でマスクされる
}
⚠️ 重要:
sensitive = trueにしても、terraform.tfstateファイルには平文で記録されます。Stateファイルの取り扱いには注意が必要です。詳細は「state管理とは」を参照してください。
nullable — nullの許可・禁止
nullable = falseを設定すると、この変数にnullを渡すことができなくなります(Terraform 1.1以降)。
variable "environment" {
type = string
nullable = false # null を渡すと即座にエラー
}
nullableのデフォルトはtrueです。変数にデフォルト値が設定されており、かつnullを渡したときにデフォルト値にフォールバックしてほしい場合はnullable = trueのままにします。
validation — 入力値のカスタムバリデーション
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
description = "VPCのCIDRブロック"
validation {
condition = can(cidrhost(var.vpc_cidr, 0))
error_message = "有効なCIDR形式(例: 10.0.0.0/16)を指定してください。"
}
}
variable "instance_type" {
type = string
description = "EC2インスタンスタイプ"
validation {
condition = startswith(var.instance_type, "t3.") || startswith(var.instance_type, "t4g.")
error_message = "instance_type は t3.xxxxx または t4g.xxxxx 系を指定してください。"
}
}
validationブロックは複数設定できます。条件式(condition)にはtrueまたはfalseを返す任意のTerraform式が使えます。
変数に値を渡す方法と優先順位
変数に値を渡す方法は複数あります。複数の方法が重複した場合は、数字が大きいほど優先度が高いです。
| 優先度 | 方法 | 書き方 |
|---|---|---|
| 1(低) | default引数 | variableブロック内に記述 |
| 2 | 環境変数 | export TF_VAR_environment=prd |
| 3 | terraform.tfvars | 変数名 = "値" の形式で記述 |
| 4 | terraform.tfvars.json | JSON形式で記述 |
| 5 | <em>.auto.tfvars / </em>.auto.tfvars.json | 自動読み込み(dev.auto.tfvars等) |
| 6(高) | -var-file / -varオプション(HCP Terraform変数) | terraform apply -var="environment=prd" |
⚠️ 重要: CLIオプション(
-var・-var-file)とHCP Terraform変数が最高優先度です。環境変数(TF_VAR_)はterraform.tfvarsより低い優先度です。*.auto.tfvarsはterraform.tfvarsより高い優先度です。
terraform.tfvars の書き方
# terraform.tfvars
environment = "dev"
instance_type = "t3.micro"
vpc_cidr = "10.0.0.0/16"
複数環境への対応(*.tfvarsを環境ごとに分ける)
# ディレクトリ構成例
project/
├── main.tf
├── variables.tf
├── dev.tfvars # dev環境用
├── stg.tfvars # stg環境用
└── prd.tfvars # prd環境用
# 使い方
terraform apply -var-file="dev.tfvars" # dev環境
terraform apply -var-file="prd.tfvars" # prd環境
⚠️ 注意:
terraform.tfvarsや機密情報を含む*.tfvarsファイルはGitリポジトリに含めないよう.gitignoreに追加してください。
5. 実践例
例1: 環境ごとに設定を変えるパターン
# variables.tf
variable "environment" {
description = "デプロイ環境名"
type = string
validation {
condition = contains(["dev", "stg", "prd"], var.environment)
error_message = "environment は dev / stg / prd のいずれかです。"
}
}
variable "instance_type" {
description = "EC2インスタンスタイプ"
type = string
default = "t3.micro"
}
variable "vpc_cidr" {
description = "VPCのCIDRブロック"
type = string
default = "10.0.0.0/16"
validation {
condition = can(cidrhost(var.vpc_cidr, 0))
error_message = "有効なCIDRブロック形式を指定してください。"
}
}
variable "enable_deletion_protection" {
description = "RDSの削除保護を有効にするか"
type = bool
default = false
}
# dev.tfvars
environment = "dev"
instance_type = "t3.micro"
vpc_cidr = "10.0.0.0/16"
enable_deletion_protection = false
# prd.tfvars
environment = "prd"
instance_type = "t3.medium"
vpc_cidr = "10.1.0.0/16"
enable_deletion_protection = true
# main.tf(variableを参照)
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr # ← tfvarsの値が入る
tags = {
Name = "${var.environment}-vpc"
Environment = var.environment
}
}
resource "aws_instance" "web" {
ami = data.aws_ami.amazon_linux_2023.id
instance_type = var.instance_type # ← 環境によって変わる
tags = {
Name = "${var.environment}-web"
}
}
例2: map型で環境ごとの設定を一元管理
# variables.tf
variable "environment" {
type = string
}
variable "ec2_config" {
description = "EC2の設定(環境ごと)"
type = map(object({
instance_type = string
volume_size = number
}))
default = {
dev = {
instance_type = "t3.micro"
volume_size = 20
}
stg = {
instance_type = "t3.small"
volume_size = 30
}
prd = {
instance_type = "t3.medium"
volume_size = 50
}
}
}
# main.tf
resource "aws_instance" "web" {
ami = data.aws_ami.amazon_linux_2023.id
instance_type = var.ec2_config[var.environment].instance_type # dev → "t3.micro"
root_block_device {
volume_size = var.ec2_config[var.environment].volume_size # dev → 20
volume_type = "gp3"
encrypted = true
}
tags = {
Name = "${var.environment}-web"
}
}
例3: 機密値の管理(DBパスワード、APIキー)
# variables.tf
variable "db_password" {
description = "RDSのマスターパスワード"
type = string
sensitive = true # plan/apply出力でマスクされる
nullable = false # nullは禁止
validation {
condition = length(var.db_password) >= 8
error_message = "パスワードは8文字以上を指定してください。"
}
}
# main.tf
resource "aws_db_instance" "main" {
identifier = "${var.environment}-db"
engine = "mysql"
engine_version = "8.0"
instance_class = "db.t3.medium"
allocated_storage = 20
db_name = "appdb"
username = "admin"
password = var.db_password # ← sensitiveな変数を参照
skip_final_snapshot = true # 検証環境用(本番はfalseを推奨)
tags = {
Name = "${var.environment}-db"
}
}
💡 ヒント: 機密値はtfvarsに書かずに環境変数で渡すのがより安全です。
export TF_VAR_db_password="your-secure-password"
terraform apply
例4: object型で複数の設定をまとめる
# variables.tf
variable "alb_config" {
description = "ALBの設定"
type = object({
internal = bool
idle_timeout = number
access_logs_bucket = string
})
default = {
internal = false
idle_timeout = 60
access_logs_bucket = ""
}
}
# main.tf
resource "aws_lb" "main" {
name = "${var.environment}-alb"
internal = var.alb_config.internal # オブジェクトの属性にアクセス
load_balancer_type = "application"
subnets = aws_subnet.public[*].id
idle_timeout = var.alb_config.idle_timeout
tags = {
Name = "${var.environment}-alb"
}
}
6. よくあるエラー
Error: No value for required variable
│ Error: No value for required variable
│
│ on variables.tf line 1:
│ 1: variable "environment" {
│
│ The root module variable "environment" is not set, and has no default value.
│ Use a -var or -var-file command line argument to provide a value for this variable.
原因: defaultが設定されていない変数に値が渡されていない。
解決方法: terraform.tfvarsに値を記述するか、-varオプションで渡す。
terraform apply -var="environment=dev"
# または terraform.tfvars に environment = "dev" を追記
Error: Invalid value for input variable(validationエラー)
│ Error: Invalid value for input variable
│
│ on terraform.tfvars line 1:
│ 1: environment = "production"
│
│ Invalid value for variable "environment" (from terraform.tfvars line 1):
│ environment は dev / stg / prd のいずれかを指定してください。
原因: validationブロックの条件に合わない値が渡された。
解決方法: error_messageに従い、正しい値を渡す。
Error: Variables may not be used here(backendブロック内)
│ Error: Variables may not be used here
│
│ on providers.tf line 8:
│ 8: bucket = var.state_bucket
│
│ Variables may not be used here.
原因: terraformブロックのbackend設定内では変数が使えない。
解決方法: backendに変数を使いたい場合は、-backend-configオプションで渡す。
terraform init -backend-config="bucket=my-terraform-state-bucket"
型の不一致エラー
│ Error: Invalid value for input variable
│
│ Inappropriate value for attribute "instance_type": string required.
原因: type = stringの変数にnumberやboolを渡した。
解決方法: 変数の型に合った値を渡す。またはtype = anyにして型制約を緩める(非推奨)。
7. ベストプラクティス
推奨パターン
typeは必ず指定する
型を指定することで、誤った値が渡されたときに即座にエラーになります。anyは型チェックが働かないため、デバッグが難しくなります。
descriptionは必ず書く
変数の意味・用途・設定例をdescriptionに記述します。terraform-docsなどのドキュメント生成ツールを使うと、descriptionの内容が自動でドキュメントに反映されます。
variable "instance_type" {
description = "EC2インスタンスタイプ。開発環境: t3.micro / 本番: t3.medium を推奨"
type = string
default = "t3.micro"
}
機密値にはsensitive = trueを付ける
DBパスワード、APIキー、シークレットキーなど機密情報を変数で管理する場合はsensitive = trueを設定します。ただしterraform.tfstateには平文で記録されることを忘れないでください。sensitive値の詳細な挙動・nonsensitive()・ephemeral変数との比較は sensitive変数 — 機密値のマスクとstate記録 を参照してください。
validationで入力値を制限する
想定外の値によるデプロイエラーを防ぐために、可能な限りvalidationブロックを設定します。特にenvironment(dev/stg/prd)やリージョン名はcontains()で制限すると安全です。
変数名はスネークケースで記述する
Terraform公式スタイルガイドに従い、変数名はスネークケース(単語をアンダースコアで繋ぐ形式)で記述します。
# 推奨: スネークケース
variable "instance_type" {}
variable "vpc_cidr_block" {}
variable "enable_deletion_protection" {}
# 非推奨
variable "instanceType" {} # キャメルケース
variable "instance-type" {} # ハイフン区切り
variables.tfファイルに集約する
変数の定義はvariables.tfファイルにまとめます。main.tfにvariableブロックを書くことは技術的には可能ですが、管理が複雑になります。
避けるべきパターン
機密値をdefaultに直接書く
# NG: デフォルト値にパスワードを直書き
variable "db_password" {
default = "mysupersecretpassword" # Gitに漏れる
}
tfvarsに機密情報を書いてGitにコミットする
.gitignoreに以下を追加し、機密情報を含むファイルがGitに含まれないようにします。
terraform.tfvars
*.auto.tfvars
type = anyを多用する
型チェックが機能しないため、誤った型の値が渡されたことに気づきにくくなります。型が決まっている場合は具体的な型を指定してください。
8. 関連記事
- locals(ローカル値)の使い方 — 変数とlocalsの使い分け
- locals vs variableの違い — どちらを使うべきか
- outputの使い方 — 変数に対する「出力側」
- tfvarsファイルの使い方 — 変数ファイルの書き方と優先順位
- 型システム入門 — HCLの型の詳細
- for_eachの使い方 — map型変数とfor_eachの組み合わせ
- state管理とは — sensitiveな値とStateファイルの関係
9. まとめ
variableブロックで入力変数を定義し、var.<変数名>で参照する- 主な引数は
type(型制約)/default(デフォルト値)/description(説明)/sensitive(機密値)/nullable(null禁止)/validation(カスタムチェック) - 型には
string / number / bool / list / set / map / object / tuple / anyが使える - 値を渡す方法は
terraform.tfvars・-var-file・-var・環境変数(TF_VAR_)があり、後者ほど優先度が高い sensitive = trueはplan/apply出力をマスクするが、Stateファイルには平文で記録されるvalidationブロックで入力値を事前チェックし、想定外の値によるエラーを防ぐ- 機密値を
defaultに直書きしたり、tfvarsをGitにコミットしたりしないこと
動作確認バージョン: Terraform >= 1.9 / AWS Provider ~> 5.0 対象リージョン: ap-northeast-1(東京) 公式ドキュメント: https://developer.hashicorp.com/terraform/language/values/variables