HashiCorp公式の公開資格としてはAssociateが中心だが、本稿では上位レベル(Pro相当)を想定し、実務の難所を軸に学習観点をまとめる。
試験対策だけでなく、Terraform Cloud/EnterpriseやS3+DynamoDBバックエンド運用など、現場の標準パターンで説明する。
上位レベルでは、HCLを書けることに加え、モジュールの公開品質、ステート運用(ロック・分離・移行)、変更の安全性(create_before_destroy、replace_triggered_by、moved)、ポリシー適用、そしてCIによる自動化と監査可能性が問われる。Terraform Open SourceとTerraform Cloud/Enterprise(TFC/E)の差も把握しておきたい。
出題イメージとしては、単一ワークスペースの単純構成ではなく、複数環境・複数ワークスペース・リモートステート・チーム権限・タグや規約の強制・モジュールバージョニング・プロバイダ更新など、スケールと変更を前提にした意思決定が多い。
| 領域 | Associateの深さ | 上位レベル想定の深さ | 実務観点 |
|---|---|---|---|
| モジュール設計 | 基本的な変数/出力 | 公開品質・条件・バージョニングと破壊的変更の扱い | 後方互換とドキュメントを維持しつつ設計変更を出す |
| ステート/バックエンド | init/refreshの理解 | S3+DynamoDB/TFCのロック・分離・移行戦略 | 障害時の復旧手順とdrift対応、キー設計 |
| 変更管理 | plan/applyの基本 | create_before_destroy・replace_triggered_by・movedの組合せ | 無停止を狙いつつコスト/速度のバランス |
| ガバナンス | 基本的なWorkspace理解 | Sentinel/OPAと権限設計、変数セット、監査ログ | 組織標準の強制と例外承認プロセス |
| 自動化/監査 | validate/planの実行 | JSONプランの保管、署名、承認ゲート、再現性 | 証跡とロールバックのしやすさ |
Terraform上位レベルの責務マップ
最低限のルート構成スケルトン(バージョン/プロバイダ制約)
terraform {
required_version = ">= 1.4, < 2.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = var.region
}
module "network" {
source = "appcorp/network/vpc"
version = "~> 2.4"
cidr_block = var.vpc_cidr
}
上位レベルでは、モジュールは「使える」だけでなく「安心して更新できる」ことが重要。変数のバリデーション、pre/post条件、デフォルトの整備、命名と出力の後方互換、明確なバージョニング規約が要点となる。破壊的変更はメジャー更新とし、movedでのアドレス移行を併用して影響を最小化する。
README、サンプル、バージョン互換表を揃え、registryに公開する場合は使用例を実行可能に保つ。内部向けでも、CHANGELOGとアップグレードガイドを必ず用意する。
条件・検証を備えたモジュール断片
variable "subnet_cidrs" {
type = list(string)
validation {
condition = length(var.subnet_cidrs) >= 2
error_message = "少なくとも2つのサブネットCIDRが必要です。"
}
}
locals {
default_tags = merge(var.default_tags, {
managed-by = "terraform"
module = "appcorp/network"
})
}
resource "aws_subnet" "this" {
for_each = toset(var.subnet_cidrs)
vpc_id = var.vpc_id
cidr_block = each.value
tags = local.default_tags
lifecycle {
precondition {
condition = can(cidrnetmask(each.value))
error_message = "CIDRの形式が不正です。"
}
}
}
moved {
from = aws_subnet.old
to = aws_subnet.this
}
output "subnet_ids" {
description = "作成されたサブネットのID一覧"
value = values(aws_subnet.this)[*].id
}
ステートは真実の源泉。上位レベルでは、リモートバックエンドでのロック、権限、キー戦略(環境・リージョン・システム単位の分離)を設計し、障害時の復旧手順を標準化する。S3+DynamoDBはオンプレ/マルチアカウントでも定番、Terraform Cloud/Enterpriseはロックと実行管理、ポリシー、監査が統合される。
移行と保守では、terraform state mv/import、モジュールのmovedを使い分ける。drift対応は安易な-state rmや手動修復に走らず、原因を特定し、必要ならignore_changesやプロバイダの力学(差分計算)を理解して調整する。
代表的バックエンド設定と運用コマンド
# S3 + DynamoDB ロック
terraform {
backend "s3" {
bucket = "tfstate-prod"
key = "network/prod/ap-northeast-1/terraform.tfstate"
region = "ap-northeast-1"
dynamodb_table = "tfstate-lock"
encrypt = true
}
}
# Terraform Cloud (remote) バックエンド
terraform {
cloud {
organization = "appcorp"
workspaces {
name = "network-prod"
}
}
}
# 運用スニペット
# 既存リソースを宣言と紐付け(import)
terraform import aws_subnet.this["10.0.1.0/24"] subnet-abc123
# アドレス移行(state mv)
terraform state mv aws_subnet.old["10.0.1.0/24"] aws_subnet.this["10.0.1.0/24"]
# 差分のJSON化(監査用)
terraform show -json plan.out > plan.json
不可避な置換が発生する変更でも、停止やリスクを抑える工夫ができる。lifecycleのcreate_before_destroy、ignore_changesで外部制御値の差分を抑制、replace_triggered_byで意図したタイミングでの置換を誘発する。プロバイダ依存のブルーグリーンやローリング更新は、モジュールの抽象で包み隠蔽するのが安全だ。
targetはデバッグや段階リリースの補助に留め、恒常運用の前提にしない。多段変更は、モジュールのバージョンを刻み、movedと出力互換を活用してリスクを分割する。
置換順序と差分抑制のHCL例
resource "aws_launch_template" "app" {
name_prefix = "app-"
image_id = var.ami
instance_type = var.instance_type
user_data = var.user_data
lifecycle {
create_before_destroy = true
ignore_changes = [
user_data, # 外部で都度差し替える場合にドリフト抑制
tags["temporary"]
]
replace_triggered_by = [
var.force_recreate_token # 任意のトークンで安全側置換
]
}
timeouts {
create = "20m"
delete = "20m"
}
}
Terraform Cloud/Enterpriseでは、Sentinelで計画に対する組織ポリシーを強制できる。タグ必須、コスト上限制約、許可されたリージョンやプロバイダのみ許可などをコード化し、ワークスペースやポリシーセットで適用範囲を制御する。Open Source環境では、OPA/RegoとConftestをCIに組み込み、同様の検査を行う。
権限は最小権限を原則に、VCS連携時はトリガ権限とState閲覧権限を慎重に分離する。変数セットやSensitive変数を用い、資格情報をコード外で注入し、監査ログで操作の追跡性を確保する。
Sentinelの簡易ポリシー例(タグ必須)
import "tfplan/v2" as tfplan
main = rule {
all tfplan.resources as r {
r.mode is "managed" implies has_required_tags(r)
}
}
has_required_tags = func(r) {
all r.applied.resources as inst {
inst.change.after.tags is not null and
inst.change.after.tags["owner"] is not null and
inst.change.after.tags["env"] in ["dev", "stg", "prod"]
}
}
CIではinit/validate/planを分離し、プランはバイナリアーティファクトとして保存、レビュー後にapplyにのみ使用する。静的解析(tflintなど)やポリシー検査(OPA/Checkov)を早期に回し、重いplanは変更が確定した段階で実行する。VCSの保護ルールと組み合わせ、再現性と証跡を担保する。
障害調査は、plan/show -jsonによる差分の機械読解、TF_LOGやproviderのデバッグフラグ、並列度やAPIレート制限の調整から着手する。インポートは、近年のimport blockが利用可能な環境ならコード側で宣言し、計画に組み込んで手順を見える化する。
GitHub Actionsでの基本パイプライン例
name: terraform-ci
on:
pull_request:
paths: ["infra/**"]
jobs:
plan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: hashicorp/setup-terraform@v3
with:
terraform_version: 1.6.6
- run: terraform -chdir=infra init -input=false
- run: terraform -chdir=infra validate
- run: terraform -chdir=infra plan -input=false -out=plan.out
- run: terraform -chdir=infra show -json plan.out > plan.json
- uses: actions/upload-artifact@v4
with:
name: tf-plan
path: infra/plan.out
apply:
if: github.ref == 'refs/heads/main' && github.event_name == 'workflow_dispatch'
needs: plan
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: hashicorp/setup-terraform@v3
- uses: actions/download-artifact@v4
with:
name: tf-plan
path: infra
- run: terraform -chdir=infra init -input=false
- run: terraform -chdir=infra apply -input=false "plan.out"
Pro
問題 1
複数ワークスペース(dev/stg/prod)で利用される内部モジュールをリファクタリングし、リソースのアドレスが aws_subnet.old から aws_subnet.this に変わった。すべての環境で再作成やダウンタイムを避けつつ、安全に移行したい。最も適切な対応はどれか。
正解: A
moved ブロックはリソースアドレスの変更を宣言的に移行し、再作成を避けられる。モジュールの新バージョンとして配布すれば、各ワークスペースで計画・適用時に自動でstateが更新される。state rm は破壊的で復旧が難しく、-target は恒常的な移行手段ではない。新規ワークスペース作成は不要かつリスクが大きい。
SentinelとOPAのどちらを使うべきですか?
Terraform Cloud/Enterpriseを使うならSentinelで実行時ポリシーを一元管理するのが自然です。Open Source中心のCIであればOPA/Rego(Conftest)を採用し、plan前に静的検査として実行します。併用も可能で、開発段階はOPA、本番はSentinelのように役割分担できます。
Terraform Cloudを使わずに安全なロックは可能ですか?
はい。S3バックエンドにDynamoDBロックを組み合わせるのが定番です。S3はバージョニングと暗号化を有効化し、DynamoDBテーブルはスループットとアラートを適切に設定します。競合を避けるため、CIは単一ジョブに直列化し、人手実行と重複しない運用ルールを整備してください。
モジュールとプロバイダのバージョン固定はどの程度が適切ですか?
モジュールは互換性を考慮して~>でマイナー範囲に固定し、破壊的変更はメジャー更新で受け取ります。プロバイダは障害回避のために~>の範囲指定、あるいは短期的にはピン留めして検証→段階的に緩める方針が現実的です。CHANGELOGと検証用の環境での事前適用を徹底してください。
NicheeLab編集部
データエンジニアリング・クラウド資格の専門家。Databricks・Snowflake等の認定資格を保有し、実務経験に基づいた問題作成・解説を行っています。NicheeLab運営。
Terraform HCL 構文の基礎:Block / Attribute / Expression を正しく使い分ける
Terraform Associate で頻出の HCL 構文を、ブロック・属性・式の3視点で整理。実務で迷いがちな書き...
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...