Terraform経験は、インフラをコードで再現し、変更差分をレビューできる人材として評価されます。ただし、HCLを書けることと、安全なState管理、権限分離、CI/CD運用を設計できることは別です。
この記事では、Terraform求人の担当範囲、ポートフォリオに必要な成果物、クラウド知識との組み合わせ方を解説します。コード量ではなく、要件、設計理由、plan、異常時対応まで一続きで示してください。
このページはインフラエンジニア転職完全ガイドの各論です。転職の進め方を最初から確認する場合はそちらへ。
Terraform経験はインフラエンジニア転職でなぜ評価される?
Terraformを使う仕事では、クラウドやネットワークの構成をコードで再現し、変更差分を適用前に確認できます。採用側が評価するのは「Terraformを触った」という事実ではなく、手作業で起きやすい設定差異をどう減らし、変更をレビュー可能にし、同じ環境を再作成できる状態へ変えたかです。
たとえばVPCを作成しただけでは、AWSコンソール操作をTerraformへ置き換えたことしか分かりません。CIDRを変数にした理由、環境ごとのState分離、planで置換対象を見つけたときの対応、適用できる人の制限、障害時の切り戻しまで説明できると、コード作成ではなくIaC運用を理解している証拠になります。
| 示せる段階 | 成果物 | 採用側が確認できること | まだ証明できないこと |
|---|---|---|---|
| 学習 | 小規模なHCLとREADME | resource・variable・outputの基礎 | 商用環境の変更経験 |
| 個人検証 | 構成図、remote Backend、plan、異常試験 | 安全性を考えて構成を作った過程 | 複数人での権限・承認運用 |
| チーム開発 | Pull Request、レビュー履歴、CI結果 | 差分を他者へ説明し修正した経験 | 本番適用の最終判断を担った経験 |
| 実案件 | 設計書、Module、plan承認、変更・復旧記録 | 制約のある環境で変更を完了した担当範囲 | 本人が担当していない工程 |
(出典:What is Terraform?(HashiCorp))
Terraform求人ではどんな仕事を担当する?
Terraform求人の担当業務は、既存コードの修正、新規Moduleの設計、手作業リソースのImport、CI/CD整備、State・権限運用に分かれます。同じ「Terraform経験者募集」でも、変数を変更してplanを取得する仕事と、標準Moduleや適用フローを設計する仕事では責任範囲が異なります。
| 求人タイプ | 主な作業 | 求められる経験 | 評価される成果物 |
|---|---|---|---|
| クラウド構築 | 既存Moduleを使った環境作成、plan確認、試験 | HCL、対象クラウド、Gitの基礎 | 構成図、変更差分、試験結果 |
| クラウド設計 | Module設計、State分割、命名・タグ標準化 | 要件整理、可用性、権限、監視設計 | 方式設計、Module、設計判断記録 |
| DevOps・Platform | CI/CD、Policy、Secret管理、開発者向け基盤 | GitHub Actions等、IAM、レビュー運用 | Pipeline、Branch Protection、運用手順 |
| クラウド移行 | 既存リソースのImport、差分解消、段階移行 | 既存環境調査、State操作、復旧計画 | Import一覧、plan差分、移行・切り戻し手順 |
ポートフォリオではコードと設計意図をどう示す?
ポートフォリオは完成したコードだけでなく、要件、構成図、ディレクトリ、State設計、実行手順、plan結果、異常時の対応、レビュー記録を一式にします。以下の8項目は同じ説明で済ませず、それぞれ別の設計判断と証拠を用意します。
HCLではリソース・data・variable・outputをどう使い分ける?
HCLでは、作成する対象をリソース、既存情報の参照をdata、環境ごとに変える入力をvariable、他Moduleや利用者へ渡す値をoutputとして分けます。読み手が「何を作り、何を外部から受け、何を返すか」を追えることが合格基準です。
悪い例:環境名、CIDR、リージョンをリソースへ直接書き、変数の型や入力チェックがありません。同じ構成を検証環境へ展開するときにコピーが発生し、CIDRの入力ミスもplanまで分かりません。
resource "aws_vpc" "main" {
cidr_block = "10.10.0.0/16"
tags = {
Name = "production-vpc"
}
}
改善例:環境名とCIDRを型付き変数にし、validationで想定範囲を制限します。命名規則をlocalsへまとめれば、リソースごとの文字列連結も減らせます。
variable "environment" {
description = "Deployment environment"
type = string
validation {
condition = contains(["dev", "stg", "prod"], var.environment)
error_message = "environment must be dev, stg, or prod."
}
}
variable "vpc_cidr" {
description = "IPv4 CIDR assigned to the VPC"
type = string
validation {
condition = can(cidrnetmask(var.vpc_cidr))
error_message = "vpc_cidr must be a valid IPv4 CIDR."
}
}
locals {
name_prefix = "crew-${var.environment}"
}
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr
tags = {
Name = "${local.name_prefix}-vpc"
Environment = var.environment
ManagedBy = "terraform"
}
}
output "vpc_id" {
description = "ID of the created VPC"
value = aws_vpc.main.id
}
READMEには、なぜ`dev/stg/prod`以外を拒否するのか、CIDRを誰が決めるのか、命名を変えるとどのリソースに影響するのかを書きます。コード量より、入力元と変更影響を説明できる方が設計意図として伝わります。
Stateでは安全な保管・分離・復旧をどう示す?
StateファイルそのものをGitへ公開するのではなく、remote Backend、ロック、環境分離、最小権限、暗号化、世代管理を設計したことを示します。Stateはリソースアドレスと実リソースの対応や属性を保持し、認証情報などの機密値を含む場合があるためです。
| 確認項目 | 安全な設計 | ポートフォリオで見せるもの | 避ける状態 |
|---|---|---|---|
| 保管場所 | S3・Azure Blob・GCS・HCP Terraform等のremote Backend | Backend方式図と初期化手順 | `terraform.tfstate`をGitへcommit |
| 同時実行 | Backendが対応するState Lockを有効化 | 競合時のエラーと解除判断 | 複数人が同じStateへ同時適用 |
| 環境分離 | dev・stg・prodでStateと権限を分離 | State key・workspace・directoryの対応表 | 全環境を1つのStateで管理 |
| 機密情報 | アクセス制御、暗号化、Secretの外部管理 | IAM方針と`.gitignore` | `sensitive = true`だけで保存されないと誤解 |
| 復旧 | 世代管理、バックアップ、lineage・serial確認 | 破損時の連絡・停止・復旧手順 | 確認せず`terraform state push -force` |
`terraform state pull`はStateを標準出力へ取り出すため、保存先やログに機密情報を残さない注意が必要です。`terraform state push`はremote Stateを上書きする危険な操作なので、本番ではバックアップ、対象workspace、lineage、serial、承認者を確認し、無条件に実行しません。
(出典:State(Terraform)、Style Guide(Terraform))
Backendでは暗号化・ロック・権限をどう設計する?
Backendでは、Stateを置くサービス名だけでなく、暗号化、ロック、アクセス権限、環境分離、障害時の復旧を説明します。Backendの保存先を作る初期処理と、業務リソースを作るTerraformを分離しておくと、State保管先がないため初期化できない循環を避けられます。
terraform {
backend "s3" {
bucket = "example-terraform-state-prod"
key = "network/core/terraform.tfstate"
region = "ap-northeast-1"
encrypt = true
use_lockfile = true
}
}
これは設定例です。bucketは事前作成し、Versioning、暗号化、Public Access Block、Stateと`.tflock`への最小権限を別途設定します。アクセスキーをBackend ブロックへハードコードせず、CIのOIDCや実行環境の認証情報を使います。S3 BackendのDynamoDBロックは現在非推奨のため、既存案件では利用中のTerraformバージョンと移行計画を確認します。
Azure StorageやGCSを使う場合も、開発・検証・本番の保管先またはobject path、暗号化、実行Identity、ロック方式、Versioning相当機能、障害時の復旧手順を表にします。Backend障害中にlocal Stateへ切り替えて適用すると二重管理になるため、復旧まで変更を停止する条件を先に決めます。
(出典:Backend Type: s3(Terraform)、State Backends(Terraform))
Moduleでは再利用性と読みやすさをどう両立する?
Moduleは、複数のリソースを利用者にとって意味のある単位へまとめます。VPC、subnet、route tableをネットワーク基盤として一緒に変更するなら1つのModule候補ですが、リソースを1個ずつModule化すると呼び出し関係が増え、かえって構成を追いにくくなります。
terraform-portfolio/
├── environments/
│ ├── dev/
│ │ ├── backend.tf
│ │ ├── main.tf
│ │ └── terraform.tfvars.example
│ └── prod/
│ ├── backend.tf
│ └── main.tf
├── modules/
│ └── network/
│ ├── main.tf
│ ├── variables.tf
│ ├── outputs.tf
│ └── README.md
└── README.md
module "network" {
source = "../../modules/network"
environment = "dev"
vpc_cidr = "10.10.0.0/16"
public_subnets = {
app-a = "10.10.10.0/24"
app-c = "10.10.20.0/24"
}
}
ModuleのREADMEには、目的、前提、input、output、利用例、作成されるリソース、破壊的変更の有無を書きます。外部ModuleはバージョンやGit tag・commitを固定し、更新時のplanをレビューします。Module間の依存はoutputからinputへ明示し、root moduleでしか分からない暗黙の順序を増やしません。
Plan/Applyでは差分レビューと承認をどう示す?
Plan/Applyでは、`fmt`、`validate`、`plan`、レビュー、承認、`apply`、正常性確認を分けます。`terraform validate`は構文と内部整合性を確認しますが、remote API、実リソース、remote Stateの内容までは検証しないため、`plan`と実環境の試験が必要です。
fmt / validate
plan保存
PRレビュー
承認
同じplanを適用
正常性確認
terraform fmt -check -recursive
terraform init -input=false
terraform validate
terraform plan -input=false -out=tfplan
terraform show -no-color tfplan > plan.txt
# レビューと承認後、plan作成時と同じ実行環境・provider lockで適用
terraform apply -input=false tfplan
本番環境で無条件に実行しないでください。planには機密値が含まれる可能性があるため、保存先と閲覧権限を制限します。`delete`や`replace`、リソース数の想定外変化、IAM・route・Security Groupの変更を重点確認し、作成後に時間が空いた場合は新しいplanを作り直します。失敗時は途中まで作成されたリソース、State Lock、再実行の安全性を確認し、単純に同じ適用を繰り返しません。
(出典:Command: validate(Terraform)、Command: plan(Terraform))
Importでは既存リソースをどう安全にコード管理へ移す?
Importでは、既存リソースをStateへ登録しただけで完了にしません。対象を1件ずつ特定し、対応するリソース定義を作り、import後のplanが意図しない更新・再作成を出さなくなるまで差分を調整します。
import {
to = aws_vpc.existing
id = "vpc-0123456789abcdef0"
}
resource "aws_vpc" "existing" {
cidr_block = "10.20.0.0/16"
enable_dns_support = true
enable_dns_hostnames = true
tags = {
Name = "existing-production-vpc"
}
}
terraform plan
# import対象・resource address・変更差分をレビュー
terraform apply
terraform plan
# 最終的に意図しない差分がないことを確認
CLIの`terraform import ADDRESS ID`はStateへの取り込みだけで、resource configを生成しません。大量Importを一度に行うと、resource addressの誤りやdefault値の差分が混ざったときに原因を切り分けにくくなります。Import一覧、実リソースID、担当者、plan結果、戻し方を記録し、小さい単位で進めます。
(出典:Import(Terraform))
CI/CDでは検査・承認・Secret管理をどう実装する?
CI/CDでは、Pull Request時に`fmt`、`validate`、セキュリティスキャン、planを実行し、結果をレビュー可能にします。本番適用はPRの作成者が自由に実行するのではなく、保護された環境、Approver、短命なクラウド認証、対象branchなどの条件を満たした場合だけ許可します。
name: terraform-check
on:
pull_request:
paths:
- "terraform/**"
permissions:
contents: read
id-token: write
jobs:
plan:
runs-on: ubuntu-latest
defaults:
run:
working-directory: terraform/environments/dev
steps:
- uses: actions/checkout@v4
- uses: hashicorp/setup-terraform@v4
with:
terraform_version: "1.14.0"
- run: terraform fmt -check -recursive
- run: terraform init -input=false
- run: terraform validate
- run: terraform plan -input=false -no-color
これは検査用の簡略例です。実案件ではTerraformと事業者の利用バージョンをリポジトリの方針に合わせ、OIDCのtrust policy、Secretを表示しないログ設定、planの保存期間、scan失敗時の停止、通知先、本番環境の承認条件を追加します。plan失敗時に`continue-on-error`で後続適用へ進む構成は避けます。
(出典:hashicorp/setup-terraform(GitHub))
Gitレビューでは変更理由とplan結果をどう残す?
Gitレビューでは、1つのPull Requestへ無関係な変更を詰め込まず、Issue・設計書・構成図とコード差分を結び付けます。レビュアーが見るのはHCLの書式だけではなく、要件、影響範囲、planの`add/change/destroy`、State移動、権限変更、試験、切り戻しです。
| PRに残す項目 | 記載例 | レビュー観点 |
|---|---|---|
| 変更理由 | 新拠点接続のためdev VPCへprivate subnetを2つ追加 | 要件・Issueと差分が一致するか |
| 構成図 | 変更前後のCIDR、route、接続先 | 重複CIDRや通信経路の漏れがないか |
| plan結果 | 2 add / 0 change / 0 destroy | 置換・削除・権限拡大がないか |
| 試験 | 疎通、名前解決、監視、拒否通信 | 正常系と異常系を確認できるか |
| 切り戻し | 中止条件、削除順、State確認 | 途中失敗から戻せるか |
Branch Protectionで必須checkと必要Approver数を設定し、CODEOWNERSでネットワークやIAMの担当者をレビューerへ含めます。commit履歴は「fix」だけにせず、どの指摘へ対応したか追える単位にします。面接では、指摘を受けてCIDR validationや権限をどう直したかまで説明すると、チームで品質を上げた経験になります。
AWS・Azure・GCP経験とはどう組み合わせる?
Terraformはクラウド設計の代わりではありません。AWSならVPC・IAM・CloudWatch、AzureならVNet・RBAC・Azure Monitor、GCPならVPC・IAM・Cloud Monitoringなど、対象サービスの仕組みを理解したうえでHCLへ落とし込みます。
| 設計論点 | AWS例 | Azure例 | GCP例 | Terraformで示すこと |
|---|---|---|---|---|
| ネットワーク | VPC・Subnet・Route | VNet・Subnet・Route Table | VPC・Subnet・Route | CIDR、通信方向、依存関係 |
| 権限 | IAM Role・Policy | Managed Identity・RBAC | Service Account・IAM | 実行Identityと最小権限 |
| State保管 | S3等 | Azure Blob Storage等 | GCS等 | 環境分離、暗号化、ロック、復旧 |
| 監視 | CloudWatch | Azure Monitor | Cloud Monitoring | 作成後の正常性確認とAlert |
「3クラウドを書ける」と広げるより、まず1クラウドで設計理由と運用まで深く説明し、別クラウドでは同じ要件をどう対応付けるか示す方が伝わります。事業者固有のdefault値やリソース仕様は異なるため、名前だけを置換したHCLをマルチクラウド経験とは扱いません。
IaCをチームで安全に運用できる経験はどう作る?
個人検証でも、開発者とApproverを別アカウントにし、Pull Requestを経由して変更することでチーム運用を再現できます。成果物はコードだけでなく、権限表、Branch Protection、planレビュー記録、失敗時の対応記録まで残します。
- 要件と構成図を決める:CIDR、環境、可用性、費用上限、削除日を記録します。
- remote Backendを用意する:State保管、暗号化、ロック、Versioning、権限を設定します。
- Moduleと環境設定を分ける:input・outputと環境差分をREADMEへ書きます。
- 正常・異常を試す:validation違反、権限不足、State Lock、意図しない交換を記録します。
- PRでレビューする:変更理由、plan、構成図、試験、切り戻しを添付します。
- 適用後を確認する:疎通、監視、タグ、費用、不要リソースの有無を確認し、最後にdestroyします。
失敗を隠す必要はありません。たとえばBackend権限不足で`init`に失敗したなら、エラー、原因、修正したIAM権限、再実行結果を残します。採用側は「一度で成功したか」より、状況を再現して安全に直せるかを確認できます。
Terraform求人票と面接で確認すること
求人では、Terraformの利用有無ではなく、担当者が変更できる範囲とチーム運用を確認します。技術説明と求人判断を混ぜず、以下の質問で実務経験を積める環境かを判定します。
| 確認項目 | 面接で聞く質問 | 良い回答例 | 注意する回答 |
|---|---|---|---|
| 担当工程 | 既存Module利用、Module設計、CI整備のどこまで担当しますか | 入社時と6か月後の担当例を説明できる | 案件次第で具体例がない |
| State | 環境分離、保管、ロック、復旧はどう運用していますか | Backend・権限・障害時手順が決まっている | 各自のPCまたはGitで共有 |
| レビュー | planは誰が何を確認しますか | CODEOWNERS、必須check、Approverが明確 | 作成者が単独で適用 |
| 適用権限 | 本番適用のIdentityと承認条件は何ですか | 短命認証、環境承認、操作ログがある | 共通の長期Access Keyを共有 |
| 既存環境 | 手作業リソースはどうImport・差分解消しますか | 対象一覧、少量実施、plan、復旧手順がある | 全リソースを一括Importする |
| 育成 | 運用担当者がModule設計へ進んだ直近例はありますか | 期間、成果物、レビューerを説明できる | 資格を取れば本人次第 |
未経験者・運用経験者・構築経験者は何を成果物にする?
経験区分によって、Terraformで証明すべき範囲は異なります。実務未経験者は商用経験を装わず再現可能な検証を示し、経験者は担当した判断とチーム運用を具体化します。
| 現在地 | 作る・整理する成果物 | 職務経歴書・面接での伝え方 | 次に狙う求人 |
|---|---|---|---|
| Terraform未経験 | 構成図、HCL、remote Backend、plan、README | 学習環境であり本番経験ではないと明記 | 既存Moduleを使うクラウド構築補助 |
| 運用・手作業構築 | 手作業とHCLの対応表、Import検証、差分記録 | 定型作業をどう標準化したか説明 | クラウド構築、IaC移行 |
| Terraform構築経験 | Module、State設計、PR、異常時復旧 | リソース数より設計判断とレビュー範囲を説明 | Module設計、CI/CD、Platform |
| 設計・リード経験 | 標準化方針、権限、Policy、移行計画、品質指標 | チームの変更事故や工数をどう減らしたか説明 | クラウド設計、SRE、Platform Engineering |
インフラエンジニアがTerraform案件で考えること
手作業で作られた既存VPCをTerraform管理へ移す案件では、HCLを書き始める前に現行リソース、依存関係、変更禁止期間、障害時の連絡先、Stateの保管先を確認します。Import後のplanに大量の差分が出たとき、コードを実環境へ合わせるのか、実環境を標準へ寄せるのかは要件と影響で決めます。
僕が案件の変更手順を見る際は、開始条件だけでなく中止条件を確認します。Terraformなら、想定外の`destroy`・`replace`、State Lockの競合、権限不足、事業者エラーをどの時点で中止理由にするかを先に決めます。適用後も、リソースが存在するだけで完了にせず、通信、名前解決、監視、ログ、費用、タグまで確認します。
(出典:設計構築チャンネルの解説動画(設計構築チャンネル:検証環境がない案件と切り戻し))
Terraform経験をDevOps・SREへどう広げる?
Terraformを変更パイプラインへ組み込むならDevOps、信頼性や運用自動化へ広げるならSREが次の候補です。IaCを目的にせず、変更の再現性、レビュー、復旧へどう使うかで役割を選びます。
Terraform転職で実務経験として示す範囲
Terraform経験は、リソース作成、Module設計、Import、State・Backend運用、権限、CI/CDのどこを担当したかで示します。個人検証は商用経験と分け、コード、plan、レビュー、異常時対応を成果物として提示してください。
| 確認段階 | 確認すること | 証拠・確認先 |
|---|---|---|
| 構成 | 権限、ネットワーク、計算資源、データ、監視 | 構成図と責任分界 |
| 変更 | コード・設定差分、レビュー、適用 | IaC、手順、承認 |
| 障害 | ログ、メトリクス、通信、復旧 | 正常・異常の比較 |
| 求人 | 運用・構築・移行・設計の担当範囲 | 配属実例と成果物 |
まとめ
Terraform経験を転職で示すときは、HCLの行数ではなく、State・Backend・Module・Plan/Apply・Import・CI/CD・Gitレビューをどう安全につないだかを説明します。未経験者は小規模な検証でも、構成図、remote State、コード、plan、異常試験、README、Pull Requestを一式にすれば、学習内容を再現可能な成果物として提示できます。
次に行うことは、応募候補のTerraform求人を3件選び、既存Module利用、Module設計、State運用、CI/CD、本番適用のどこまで担当できるかを比較することです。自分の成果物で証明できる工程と、入社後に経験したい工程が一致する求人から応募します。
