TerraformのHCL変数設計|variable・locals・output・data sourceで構成を整理する方法

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOMELinux技術 リナックスマスター.JP(Linuxマスター.JP)Terraform > TerraformのHCL変数設計|variable・locals・output・data sourceで構成を整理する方法
「TerraformでインフラをHCLに落としたはいいが、同じリージョン名や環境名があちこちにハードコードされていて管理できない」
「開発・本番の切り替えでファイルを書き換えたら、うっかり本番用の値で開発環境を壊してしまった」
「モジュールを分割し始めたら、どの値をvariableにして、どの値をoutputで公開するべきか整理できなくなった」

Terraformを触り始めたころ、こういった失敗は誰もが経験します。その根本原因は、Terraformの変数機能を正しく使っていないことにあります。

TerraformのHCLには「variable」「locals」「output」「data source」という4種類の変数・参照機能があります。これらを使い分けることで、コードの重複を排除し、環境ごとの値切り替えをファイルコピーなしに実現できます。さらに、Terraform 1.2以降で使えるprecondition・postconditionを組み合わせれば、設定ミスをapplyの前後に多段で検知できます。

この記事では、HCL変数設計の4要素を実際のコードと実行例で解説します。variables.tfの型定義・バリデーション・tfvarsによる環境分離・locals/outputの使い所・data sourceによる既存リソース参照、そしてlifecycleブロックのprecondition/postconditionによる多段防御まで、設計軸で整理して体得できます。

実行環境:Terraform 1.8.x(RHEL 9.4 / Ubuntu 24.04 LTS で動作確認済み)

この記事のポイント

・variable{}で入力値を外部化し、terraform.tfvarsで環境ごとに安全に切り替えられる
・locals{}は繰り返し使う式や計算結果を1箇所にまとめてDRYにするための要素
・output{}はモジュールから外部へ値を公開し、モジュール間の疎結合を保つ
・data{}ソースは「Terraformで作っていない既存リソース」をコードから参照するための機能
・precondition・postconditionはvariable validationで届かない実行時コンテキスト条件を多段で検証する


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

なぜ変数設計がTerraformコードの品質を決めるのか

変数設計を怠るとどうなるか、まず具体例で確認します。

# 変数を使わないHCLの例 -- ハードコードの問題 resource "aws_instance" "web" { ami = "ami-0abcdef1234567890" instance_type = "t3.micro" subnet_id = "subnet-0abcdef1234" tags = { Name = "dev-web" Env = "dev" } } resource "aws_instance" "app" { ami = "ami-0abcdef1234567890" # 同じ値が重複 instance_type = "t3.micro" # 同じ値が重複 subnet_id = "subnet-0abcdef1234" # 同じ値が重複 tags = { Name = "dev-app" Env = "dev" } }

このコードの問題点は3つあります。AMI IDとサブネットIDが複数箇所に書かれており、変更時に修正漏れが起きやすいこと。「dev」という環境名がハードコードされており、本番用ファイルをコピーして別管理するはめになること。開発は小さいインスタンスタイプ、本番は大きいインスタンスタイプと切り替えたい場合でも全行書き換えが必要になること。

Terraformが提供するvariable・locals・output・data sourceの4要素を使いこなすことで、これらを解消できます。4つの役割を一言でまとめると「variableで外から受け取り、localsで内部で整理し、outputで外に渡し、dataで外の既存リソースを参照する」です。1つずつ見ていきましょう。

variable{}で入力変数を定義する

variable{}は、HCLコードの外から値を渡すための入力変数を定義します。.tfvarsファイル・コマンドラインオプション・環境変数から値を注入できます。

1. 基本的な書き方

variables.tfというファイルにまとめて定義するのが一般的です。

# variables.tf variable "aws_region" { description = "AWSリージョン" type = string default = "ap-northeast-1" } variable "env" { description = "環境名(dev/stg/prd)" type = string # defaultなし -- 必ず外部から指定する必要がある } variable "instance_type" { description = "EC2インスタンスタイプ" type = string default = "t3.micro" }

定義したvariableはvar.変数名という形式で参照します。

# main.tf resource "aws_instance" "web" { ami = var.ami_id instance_type = var.instance_type tags = { Name = "${var.env}-web" Env = var.env } }

2. 必須入力値とデフォルトあり入力値を明確に分ける

variableの設計で最初に決めるべき判断は「defaultを設けるかどうか」です。モジュール化した構成では、この分け方が呼び出し元の使いやすさを左右します。

必須入力値(default なし):呼び出し元が必ず指定しなければならない値。サブネットIDやVPC IDなどリソース固有の値が該当します。defaultを省略するとplanの段階でエラーになり、指定漏れを防止できます。
デフォルトあり入力値(default あり):標準的な値を提供しつつ、必要に応じて上書きできる値。インスタンスタイプや名前プレフィックスなど「大半のケースで共通する値」に使います。

設計の鉄則として「迷ったらdefaultなし(必須)にする」のが安全側です。defaultを設けると呼び出し元がその値に気づかないまま使い続けるリスクがあります。逆に、defaultがなければplanで必ずエラーが出るため、設計の意図が自然に伝わります。

3. type指定で型を明示する

Terraformのvariableが対応する主な型は以下のとおりです。型を明示することで、誤った値の注入をplan実行時に検出できます。
用途
string "ap-northeast-1" リージョン・環境名・AMI ID
number 3 インスタンス数・ポート番号
bool true 機能ON/OFFのフラグ
list(string) ["10.0.1.0/24", "10.0.2.0/24"] CIDRブロック・AZのリスト
map(string) {dev="t3.micro", prd="t3.large"} 環境別の設定マッピング
object({}) {name=string, port=number} 複数属性をまとめた複合型

4. validationブロックでバリデーションを追加する

Terraform 0.13から追加されたvalidationブロックを使うと、変数値の検証ルールをHCL内に書けます。

variable "env" { type = string description = "環境名(dev/stg/prd のいずれか)" validation { condition = contains(["dev", "stg", "prd"], var.env) error_message = "env は dev・stg・prd のいずれかを指定してください。" } }

terraform planを実行した時点でバリデーションされ、誤った値が入力されると以下のようにエラーが出ます。

$ terraform plan -var='env=production' Error: Invalid value for variable on variables.tf line 1: 1: variable "env" { env は dev・stg・prd のいずれかを指定してください。

本番環境への誤った設定値流入を防ぐうえで、特に環境名やインスタンスタイプのvalidationは有効です。

ただし、variable validationはplanの冒頭で評価されるため、参照できる値は入力変数の値のみです。「このAMI IDがそのリージョンに実際に存在するか」「IAMロールが指定のS3バケットにアクセスできるか」といった実行時のコンテキストに依存した条件は検証できません。このような実行時検証には、後述のpreconditionを使います。

terraform.tfvarsと*.auto.tfvarsで環境を切り替える

variableにdefaultを設定しなかった場合、値の指定が必須になります。このとき使うのが「.tfvars」ファイルです。

1. terraform.tfvarsの基本

Terraformはterraform plan/applyの実行ディレクトリに「terraform.tfvars」または「terraform.tfvars.json」があると自動で読み込みます。

# terraform.tfvars(デフォルト・開発環境用) env = "dev" instance_type = "t3.micro" ami_id = "ami-0abcdef1234567890"

2. 環境別のtfvarsファイルで本番・ステージングを切り替える

terraform.tfvarsは自動で読み込まれますが、環境別ファイルは-var-fileオプションで明示指定します。このパターンが環境分離の基本です。

# dev.tfvars env = "dev" instance_type = "t3.micro" db_instance = "db.t3.micro" # prd.tfvars env = "prd" instance_type = "t3.large" db_instance = "db.m6g.large"

# 開発環境でplanする $ terraform plan -var-file=dev.tfvars # 本番環境でplanする $ terraform plan -var-file=prd.tfvars

ファイルを切り替えるだけで、インスタンスタイプやDB容量が環境に合った値になります。本番用ファイルを誤ってコピー・変更するリスクが排除できます。

3. *.auto.tfvarsの自動読み込みルール

「.auto.tfvars」で終わるファイルは、実行ディレクトリ内に置くだけで自動的に読み込まれます。複数ファイルを分割して自動読み込みさせたいときに使います。複数の「.auto.tfvars」が存在する場合はファイル名のアルファベット順で読み込まれ、後から読み込まれたファイルの値が優先されます。意図せず値が上書きされないよう、ファイル名と変数の割り当てを整理しておくことが大切です。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、TerraformのHCL変数設計から環境分離・module設計まで、ハンズオン形式で体系的に学べるセミナーを開催しています。
>> Terraform実践セミナーの詳細はこちら

locals{}で中間値を整理しコードの重複を排除する

locals{}は、variableの値を加工した中間値や、複数箇所で繰り返し使う式をまとめるための機能です。variableと似ていますが、次の2点が異なります。外部から値を渡すことができない(.tfvarsや-varで上書きできない)点と、呼び出し元のモジュールから変更・参照ができない「モジュール内部専用の変数」という位置づけである点です。「モジュール内のプライベート変数」と考えると理解しやすいです。

1. localsの基本

# locals.tf locals { # 環境名とプロジェクト名を組み合わせてプレフィックスを生成 prefix = "${var.env}-${var.project}" # 全リソースに付与する共通タグ common_tags = { Environment = var.env Project = var.project ManagedBy = "terraform" } }

定義したlocalsはlocal.変数名という形式で参照します(var.と混同しないよう注意してください)。

resource "aws_instance" "web" { ami = var.ami_id instance_type = var.instance_type tags = merge(local.common_tags, { Name = "${local.prefix}-web" }) } resource "aws_instance" "app" { ami = var.ami_id instance_type = var.instance_type tags = merge(local.common_tags, { Name = "${local.prefix}-app" }) }

local.common_tagsを1箇所で定義することで、タグの追加・変更が全リソースに一括反映されます。

2. mapを使った環境別の値切り替え

localsとvariableを組み合わせて、環境ごとに異なる値を辞書形式で定義するパターンも便利です。

locals { # 環境名をキーにしてインスタンスタイプをマッピング instance_type_map = { dev = "t3.micro" stg = "t3.small" prd = "t3.large" } # var.envで現在の環境のインスタンスタイプを選択 selected_instance = local.instance_type_map[var.env] } resource "aws_instance" "web" { ami = var.ami_id instance_type = local.selected_instance # envに応じたタイプが自動選択 }

3. localsを使うべき場面の判断基準

同じ式・計算結果を2箇所以上に書いていたらlocalsで抽出するサインです。次の表を判断基準にしてください。
状況 使うべき要素
外部から値を渡したい(環境名・リージョン等) variable{}
variableを加工した中間値(prefix・タグマップ等)を使いまわしたい locals{}
モジュール内部でのみ使い、呼び出し元に見せたくない計算値 locals{}(外部から変更不可)
作成後のリソース属性を外部に公開したい output{}

output{}でモジュールの出力値を設計する

output{}は、Terraformが管理するリソースの属性値を外部に公開するための機能です。ルートモジュールでの確認用途のほか、モジュール化した構成では呼び元が子モジュールの出力を参照するために不可欠です。

1. outputの基本

# outputs.tf output "vpc_id" { description = "作成したVPCのID" value = aws_vpc.main.id } output "web_instance_public_ip" { description = "Webインスタンスのパブリック IP" value = aws_instance.web.public_ip }

terraform apply後、定義したoutputの値がターミナルに表示されます。後から確認するにはterraform outputコマンドを使います。

$ terraform output vpc_id = "vpc-0abcdef1234567890" web_instance_public_ip = "54.238.xxx.xxx" # JSON形式で取得 $ terraform output -json

2. sensitive = trueでシークレット値を保護する

DBのパスワードや秘密鍵など、機密性の高い値をoutputにする場合はsensitive = trueを設定します。

output "db_password" { description = "RDSインスタンスのパスワード" value = aws_db_instance.main.password sensitive = true # terraform apply の出力とterraform showでは隠蔽される }

sensitiveを設定すると、terraform applyの出力上では「(sensitive value)」と表示されます。ログへの漏洩を防ぐためにも、パスワードやAPIキーを含むoutputには必ずsensitive = trueをつける習慣を持ってください。

3. モジュールの出力を呼び元から参照する

モジュール化された構成では、子モジュールのoutputを呼び元のルートモジュールから参照できます。outputには「呼び元が実際に必要とする値だけを公開する」ことが重要で、モジュール内部のリソースIDや計算値を無差別に公開すると、呼び元との結合が密になりリファクタリングが困難になります。

# modules/vpc/outputs.tf(子モジュール側) output "public_subnet_id" { value = aws_subnet.public.id } # ルートモジュールのmain.tf(呼び元) module "vpc" { source = "./modules/vpc" env = var.env } resource "aws_instance" "web" { ami = data.aws_ami.amazon_linux.id subnet_id = module.vpc.public_subnet_id # module.<名前>. で参照 }

data{}ソースで既存リソースを参照する

data{}は、Terraformで管理していない既存のリソースをコードから参照するための機能です。「Terraformで作った」ものではなく「すでにAWSに存在する」リソースをコード上で扱いたいときに使います。

1. data sourceの基本 -- 既存VPCのID取得

# 既存のVPCをタグで検索して参照する data "aws_vpc" "existing" { filter { name = "tag:Name" values = ["existing-production-vpc"] } } # 取得したVPCのIDを使ってサブネットを作成 resource "aws_subnet" "new" { vpc_id = data.aws_vpc.existing.id cidr_block = "10.0.100.0/24" availability_zone = "ap-northeast-1a" }

参照方法はdata.タイプ.名前.属性の形式です。

2. AMI IDをdata sourceで動的に取得する

AMI IDをハードコードすると、AMIが更新されるたびに手動で書き換える必要があります。data sourceを使えば常に最新のAMIを自動選択できます。

data "aws_ami" "amazon_linux" { most_recent = true owners = ["amazon"] filter { name = "name" values = ["al2023-ami-*-x86_64"] } } resource "aws_instance" "web" { ami = data.aws_ami.amazon_linux.id # 最新AMIが自動選択される instance_type = var.instance_type }

3. aws_caller_identityでAWSアカウントIDを動的に取得する

マルチアカウント構成でIAMポリシーやリソースARNにアカウントIDを埋め込む場合、アカウントIDをハードコードするとアカウント間でコードが使い回しできなくなります。aws_caller_identityを使えばplan実行時のAWSアカウントIDを動的に取得できます。

# 現在のAWSアカウントIDをdata sourceで取得 data "aws_caller_identity" "current" {} locals { account_id = data.aws_caller_identity.current.account_id } # ARN内にアカウントIDをハードコードせず動的に埋め込む resource "aws_iam_policy" "example" { policy = jsonencode({ Version = "2012-10-17" Statement = [{ Effect = "Allow" Action = ["s3:GetObject"] Resource = "arn:aws:s3:::my-bucket-${local.account_id}/*" }] }) }

4. resource{}とdata{}の使い分け

resource{}:Terraformで作成・変更・削除するリソース(tfstateで追跡される)
data{}:既存リソースを参照するだけ(tfstateでは作成・変更は行われない)

「Terraformに管理させるか、参照だけするか」が判断基準です。既存の共有VPCやIAMロールなど、別チームが管理するリソースはdata sourceで参照するのが原則です。

lifecycle{}のprecondition・postconditionで実行時アサーションを追加する

variable validationは入力変数の形式チェックに優れていますが、planの冒頭でしか評価されず、参照できるのは入力変数の値のみです。「このAMI IDがそのリージョンに存在するか」「作成したセキュリティグループのVPC IDが期待値と一致するか」といった実行時のコンテキストに依存した条件は検証できません。

Terraform 1.2で導入されたprecondition・postconditionはこのギャップを埋めます。lifecycleブロック内にアサーションを記述することで、設定ミスをapply段階で即座に検知できます。現場での安全なIaC運用はvariable validationとprecondition/postconditionの多段防御が鉄則です。

1. variable validationとpreconditionの評価タイミングを理解する

4つの仕組みを「いつ」「何を」検証するかで整理します。
仕組み 評価タイミング 参照できる値 失敗時の動作
variable validation planの冒頭 入力変数の値のみ planを即停止
precondition リソース評価の直前 変数・data sourceの参照値 applyを即停止
postcondition リソース作成・更新の直後 作成後の属性(self) applyを停止(ロールバックなし)
check block plan/apply完了後 data source・リソース属性 Warningのみ・applyは続行
実務での選択基準を整理します。入力値の形式・許可値の制限はvariable validationを使います。複数変数の相互依存チェックやdata sourceの参照結果を条件に含めたい場合はpreconditionを使います。AWSリソースの作成後属性を検証したい場合はpostconditionを使い、外部サービスとの整合性を定期監視したい場合はcheck block(Terraform 1.5+)を使います。

2. preconditionでリソース作成前の条件をチェックする

preconditionはlifecycleブロック内に記述します。conditionがfalseになった瞬間、applyが停止してerror_messageが表示されます。次の例は、data sourceで取得したAMIのアーキテクチャを検証して、インスタンスタイプとの不整合を実行前に検知します。

# data sourceでAMIの実体を取得してpreconditionで検証する data "aws_ami" "selected" { most_recent = true owners = ["amazon"] filter { name = "image-id" values = [var.ami_id] } } resource "aws_instance" "web" { ami = data.aws_ami.selected.id instance_type = var.instance_type lifecycle { precondition { # AMIアーキテクチャとインスタンスタイプの整合性を実行前に検証する condition = ( can(data.aws_ami.selected.architecture == "x86_64") && startswith(var.instance_type, "t3.") ) error_message = "t3系インスタンスにはx86_64 AMIが必要です。AMIのアーキテクチャ: ${data.aws_ami.selected.architecture}" } } }

preconditionが失敗したときのエラー出力は次のようになります。どのファイルの何行目かまで示されるため、error_messageを人間が読める内容にしておくことが運用上の鉄則です。

$ terraform apply Planning failed. Terraform encountered an error while generating this plan. | Error: Resource precondition failed | | on main.tf line 24, in resource "aws_instance" "web": | 24: condition = ( | | t3系インスタンスにはx86_64 AMIが必要です。AMIのアーキテクチャ: arm64

3. postconditionでリソース作成後の状態を検証する

postconditionはリソースの作成・更新が完了した直後に評価されます。postcondition内ではselfを使って、今まさに作成・更新されたリソース自身の属性を参照できます。これはpreconditionでは使えないpostcondition固有の機能です。

resource "aws_security_group" "web" { name = "web-sg" vpc_id = var.vpc_id ingress { from_port = 443 to_port = 443 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } lifecycle { postcondition { # selfで作成されたリソース属性を参照して検証する condition = self.vpc_id == var.vpc_id error_message = "セキュリティグループのVPC IDが期待値と異なります。expected: ${var.vpc_id}, actual: ${self.vpc_id}" } } }

注意が必要なのは、Terraformはデフォルトでリソースのロールバックを行わない点です。postconditionが失敗しても、すでに作成されたリソースはAWS上に残ります。次回のapplyで状態を修正するか、手動でリソースを削除する必要があります。

4. check blockで継続的な状態監視をする(Terraform 1.5+)

Terraform 1.5で導入されたcheck blockは、特定のリソースに紐付くのではなくインフラ全体の状態をterraform planの実行ごとに継続的に検証します。条件がfalseになってもWarningとして報告されるだけでapplyは続行します。「壊れたら止める」ではなく「定期的に状態を監視する」ための仕組みです。

# Terraform 1.5以降: checkブロックでALBエンドポイントを継続監視する check "https_health_check" { data "http" "lb_endpoint" { url = "https://${aws_lb.main.dns_name}/health" } assert { condition = data.http.lb_endpoint.status_code == 200 error_message = "ロードバランサーのヘルスチェックが200を返していません。status: ${data.http.lb_endpoint.status_code}" } }

check blockはterraform planを実行するたびにassertが走るため、「前回のapply以降に外部の状態が変わって整合性が崩れていないか」を継続的に確認できます。

変数ファイルの推奨構成パターン

実務で崩れにくいファイル構成を紹介します。

project/ ├── main.tf # resource{}ブロックを中心に記述 ├── variables.tf # variable{}をすべてここに集約 ├── locals.tf # locals{}を集約(mainに書いてもよいが分離を推奨) ├── outputs.tf # output{}をすべてここに集約 ├── provider.tf # provider{}とbackend{}の設定 ├── versions.tf # required_version・required_providersのバージョン制約 ├── terraform.tfvars # デフォルト(dev)の変数値(自動読み込み) ├── stg.tfvars # ステージング環境用(-var-file指定が必要) └── prd.tfvars # 本番環境用(-var-file指定が必要)

このうちversions.tfは省略されがちですが、チーム開発では重要です。TerraformのバージョンとプロバイダーのバージョンをGit管理することで、「メンバーごとにTerraformのバージョンが違う」「プロバイダーが勝手にアップデートされた」という問題を防止できます。

# versions.tf terraform { required_version = ">= 1.5.0" required_providers { aws = { source = "hashicorp/aws" version = ">= 5.0.0" } } }

重要:terraform.tfvarsは自動で読み込まれますが、stg.tfvarsやprd.tfvarsは必ず-var-file=prd.tfvarsのように明示指定が必要です。「自動読み込みされると思っていたら本番用の値が使われなかった」というミスは頻発します。

また、prd.tfvarsにはパスワードやシークレットキーを書かず、これらはTF_VAR_変数名という環境変数かAWS Secrets Managerを使って注入する運用が推奨されます。Gitリポジトリにシークレットをコミットしないようにするためにもprd.tfvarsは.gitignoreへの追加を検討してください。

よくあるエラーと対処法

1. "No value for required variable"

Error: No value for required variable on variables.tf line 5: 5: variable "env" { The root module input variable "env" 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のないvariableに値が渡されていない
対処:-var='env=dev' オプションか .tfvars ファイルで値を指定する。CI/CD環境ではTF_VAR_env=devという環境変数でも設定できる。

2. "Variables may not be used here"

Error: Variables not allowed on variables.tf line 6, in variable "env": 6: default = var.aws_region Variables may not be used here.

原因:variable{}の定義内でvar.を使おうとした(循環参照)
対処:variableのdefaultにはリテラル値のみ指定できる。可変的なデフォルトが必要な場合はlocals{}で計算する。

3. data sourceのフィルタが一致しない

Error: Your query returned no results. Please change your search criteria and try again. with data.aws_vpc.existing, on main.tf line 3, in data "aws_vpc" "existing":

原因:data sourceのfilter条件に一致するリソースがAWS上に存在しない
対処:AWSコンソールまたはAWS CLIで対象リソースの存在とタグ名を確認してから再実行する。

# タグで既存VPCを確認する(AWS CLI) $ aws ec2 describe-vpcs --filters "Name=tag:Name,Values=existing-production-vpc" --query 'Vpcs[*].{ID:VpcId,Name:Tags[?Key==`Name`]|[0].Value}'

4. sensitive変数がCI/CDログに出力されてしまう

原因:outputにsensitive = trueを設定していない、またはscript内でterraform outputを実行したログが保存されている
対処:機密値を含むoutputには必ずsensitive = trueを追加する。CI/CDでoutputを取得する場合はterraform output -rawやjqを使って特定の値のみ取り出し、ログマスクの設定も合わせて行う。

5. preconditionのconditionで評価エラーが発生する

precondition/postconditionのconditionに参照エラーが起きる式を書くと、error_messageより先にTerraformの実行エラーになります。can()関数でラップすると、評価エラー自体をfalseとして扱えるため、意図したerror_messageが表示されるようになります。

# NG: data.aws_ami.selectedが取得できない場合に評価エラーが発生する condition = data.aws_ami.selected.architecture == "x86_64" # OK: can()でラップすることで評価エラーをfalseに変換する condition = can(data.aws_ami.selected.architecture == "x86_64")

6. モジュールのoutputを呼び元で参照できない

Error: Unsupported attribute on main.tf line 20, in resource "aws_instance" "web": 20: subnet_id = module.vpc.aws_subnet.public.id This object does not have an attribute named "aws_subnet".

原因:子モジュールのリソースをmodule.vpc.aws_subnet.public.idのように直接参照しようとした。モジュール内部のリソースは外部から直接参照できない。
対処:子モジュール側のoutputs.tfにoutputブロックを追加して値を公開し、呼び元ではmodule.vpc.public_subnet_idのようにmodule.名前.output名の形式で参照する。

本記事のまとめ

HCL変数設計の要素をまとめます。

要素 用途 参照・記述方法
variable{} 外部から注入する入力値。型・デフォルト・バリデーションを定義する var.変数名
locals{} 内部で使う中間値・共通タグなど。DRY化とコード整理に使う(外部変更不可) local.変数名
output{} モジュールから外部へ公開する値。sensitive指定で機密値を保護する module.名前.output名
data{} 既存リソースをコードから参照する(作成・変更は行わない) data.タイプ.名前.属性
precondition リソース作成前に実行時コンテキストを検証する。data sourceの結果も参照可能 lifecycle { precondition }
postcondition リソース作成後の属性(self)を検証する。ARN・VPC IDの整合性確認に使う lifecycle { postcondition }

設計の基本原則は4つです。

・ハードコードを見つけたらvariableに置き換え、値はtfvarsで注入する
・同じ式や加工ロジックを複数箇所に書いたらlocalsに抽出する
・モジュール化したらoutputで外部インターフェースを定義し、呼び元はmodule.名前.output名で参照する
・Terraformで管理していないリソースの参照はdata sourceで行い、resourceに混在させない

さらに、variable validationとprecondition/postconditionを組み合わせた多段防御が、現場での安全なIaC運用の鉄則です。入力値の形式はvalidationで弾き、実行時コンテキストはpreconditionで確認し、作成後の属性はpostconditionで検証する。この3段構えを習慣化することで、「applyが通ったのに想定と違う状態になっていた」という事後対応型のトラブルを大幅に減らせます。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、Terraformの変数設計からCI/CDパイプライン統合・モジュール設計まで、実務で使えるIaCスキルをハンズオン形式で習得できるセミナーを開催しています。
>> Terraform実践セミナーの詳細はこちら

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録
宮崎 智広

この記事を書いた人

宮崎 智広(みやざき ともひろ)

株式会社イーネットマーキュリー代表。現役のLinuxサーバー管理者として20年以上の実務経験を持ち、これまでに累計3,100名以上のエンジニアを指導してきたLinux教育のプロフェッショナル。「現場で本当に使える技術」を体系的に伝えることをモットーに、実践型のLinuxセミナーの開催や無料マニュアルの配布を通じてLinux人材の育成に取り組んでいる。

趣味は、キャンプにカメラ、トラウト釣り。好きな食べ物は、ラーメンにお酒。休肝日が作れない、酒量を減らせないのが悩み。最近、ドラマ「フライトエンジェル」を観て涙腺が崩壊しました。