# Terraform面接対策完全ガイド2026:Infrastructure as Codeの必須知識 > Terraform面接で頻出する質問を網羅的に解説します。ステート管理、モジュール設計、CI/CDパイプラインまで、IaC面接の合格に必要な知識を実践的なコード例とともに紹介します。 - Published: 2026-04-14 - Updated: 2026-04-14 - Author: SharpSkill - Tags: terraform, infrastructure-as-code, devops, iac, interview - Reading time: 12 min --- Terraformの面接では、クラウドインフラを宣言的に管理する能力、ステートの安全な取り扱い、再利用可能なモジュールの設計力が試されます。Terraform 1.14でモジュールソースへの変数使用がサポートされ、HCP Terraformがマネージド実行プラットフォームとして拡張を続ける2026年において、面接官は基礎的なHCL知識と進化するIaCエコシステムへの理解の両方を候補者に求めています。 > **面接官が本当に評価するポイント** > > Terraformの面接で構文の暗記が問われることはほとんどありません。重要な評価領域は、ステート管理戦略、モジュール設計パターン、シークレットの取り扱い、そして本番環境におけるplan/applyサイクルについて論理的に説明できる能力です。 ## すべての候補者が知るべきTerraformの基本概念 ### Terraformとは何か、他のIaCツールとの違い Terraformは、HCL(HashiCorp Configuration Language)で記述された設定ファイルを通じてクラウドリソースを管理する宣言的なInfrastructure as Codeツールです。AnsibleやシェルスクリプトなどのImperativeなツールとは異なり、Terraformは現在のインフラストラクチャを追跡するステートファイルを維持し、変更を適用する前に差分("plan")を計算します。 主な差別化要因として、Terraformはクラウドに依存しない設計(AWS、Azure、GCP、数百のプロバイダーに対応)、適用前に計画を確認するワークフローによる予期せぬ変更の防止、内部の有向非巡回グラフ(DAG)によるリソース依存関係の管理が挙げられます。 また、エコシステムの変化についても把握しておく必要があります。2023年にHashiCorpがBSLライセンスを採用して以降、Linux Foundation傘下でオープンソースフォークであるOpenTofuが登場しました。両ツールは同じHCL構文を共有していますが、機能面では分岐が進んでいます。Terraform 1.14はHCPとのプラットフォーム統合に注力し、OpenTofu 1.9はステート暗号化と動的バックエンドを優先しています。 ### Terraformワークフロー:init、plan、apply、destroy 4つの基本コマンドが、すべてのTerraformオペレーションのライフサイクルを形成します。 ```bash # 1. 初期化 - プロバイダーとモジュールのダウンロード terraform init # 2. 計画 - 変更内容を確認(実際の変更は行わない) terraform plan -out=tfplan # 3. 適用 - 計画された変更を実行 terraform apply tfplan # 4. 破棄 - 管理対象リソースをすべて削除 terraform destroy ``` `terraform init`はプロバイダープラグインのダウンロードとバックエンドの初期化を行います。`terraform plan`は希望する状態(設定ファイル)と実際の状態(ステートファイル)を比較し、変更セットを出力します。`terraform apply`はその変更セットを実行します。`-out`オプションでplanをファイルに保存することで、レビュー済みの正確なplanが適用されることを保証でき、CI/CDパイプラインでは必須の手法です。 ## ステート管理:最も頻出する面接トピック ### Terraformステートとは何か、なぜ重要なのか Terraformステートは、設定リソースを実際のインフラストラクチャオブジェクトにマッピングするJSONファイル(`terraform.tfstate`)です。ステートがなければ、Terraformは何が存在し、何が変更され、何を削除すべきかを判断できません。 ステートにはリソースID、属性値、依存関係のメタデータが含まれています。ステートを失うことは、Terraformが管理対象リソースすべての追跡を失うことを意味し、すべてのオブジェクトを手動でインポートするか、最悪の場合、コストが発生し続ける孤立したクラウドリソースが残る事態につながります。 ### 本番環境でのステート管理の推奨方法 ローカルのステートファイルは、チーム環境では許容されません。本番環境の標準的な構成では、ロック機能を持つリモートバックエンドを使用します。 ```hcl # backend.tf terraform { backend "s3" { bucket = "company-terraform-state" key = "prod/networking/terraform.tfstate" region = "eu-west-1" dynamodb_table = "terraform-locks" encrypt = true } } ``` この構成では、サーバーサイド暗号化を有効にしたS3にステートを保存し、DynamoDBをステートロックに使用します。ロック機能により、2人のエンジニア(または2つのCIパイプライン)が同時に`apply`を実行してステートが破損することを防止できます。 HCP Terraform(旧Terraform Cloud)は、追加のインフラストラクチャなしでステートの保存、ロック、実行履歴、RBACを一括管理するマネージドサービスです。HashiCorpエコシステムにすでに投資している組織にとっては、S3バケットやDynamoDBテーブルの運用負荷を解消する選択肢となります。 ### ステートファイルのベストプラクティス - `terraform.tfstate`をバージョン管理にコミットしてはなりません。データベースパスワードやAPIキーなどのシークレットが平文で含まれる可能性があります。 - バックエンドで保存時の暗号化を有効にします(S3 SSE、GCS暗号化、Azure Storage暗号化)。 - 環境ごとに個別のステートファイルを使用します。dev、staging、productionに対して単一のステートファイルを使うことは、誤った環境の破壊を招く原因となります。 - ステートロックを実装します。ロックをサポートするすべてのリモートバックエンドで有効にすべきです。 - `terraform state list`と`terraform state show`を使用して、ステートを変更せずに確認できます。 > **ステートファイルの災害復旧** > > ステートバックエンドでのバージョニング(S3バージョニング、GCSオブジェクトバージョニング)を必ず有効にしてください。バックアップのない状態でステートファイルが破損したり誤って削除された場合、復旧には数時間におよぶ手動の`terraform import`作業が必要になる可能性があります。 ## モジュール:再利用可能なインフラストラクチャコンポーネント ### Terraformモジュールの仕組み モジュールは、リソースのセットをカプセル化する`.tf`ファイルを含むディレクトリです。すべてのTerraform設定は技術的にモジュール(ルートモジュール)であり、子モジュールはルートモジュールから呼び出され、再利用性の促進と標準の統一を実現します。 ```hcl # main.tf - モジュールの呼び出し module "vpc" { source = "terraform-aws-modules/vpc/aws" version = "5.16.0" name = "production-vpc" cidr = "10.0.0.0/16" azs = ["eu-west-1a", "eu-west-1b", "eu-west-1c"] private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"] public_subnets = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"] enable_nat_gateway = true single_nat_gateway = true } ``` Terraform 1.14では大きな改善が導入されました。モジュールの`source`および`version`属性で変数やlocalsを使用できるようになったのです。これは以前はハードな制約であり、動的なモジュールソーシングにはTerragruntなどの回避策が必要でした。 ### 優れたモジュール設計の原則 本番品質のモジュールは以下の原則に従います。 - **明確な入出力**:すべての変数にdescription、型制約、適切な場合はデフォルト値を設定します。outputsは下流のモジュールが必要とする値を公開します。 - **最小限のスコープ**:モジュールは1つの論理コンポーネント(VPC、データベースクラスター、Kubernetesネームスペース)を管理し、環境全体を管理するものではありません。 - **ハードコードされた値の排除**:プロバイダー設定、リージョン、アカウントID、環境固有の値は変数から取得し、モジュール内部のリテラル値は使用しません。 - **バージョン管理されたリリース**:公開モジュールはセマンティックバージョニングを使用します。`version = "5.16.0"`を固定することで、予期しない破壊的変更を防止します。 ## ワークスペース、環境、プロジェクト構成 ### 複数環境の管理方法 3つの一般的なパターンがあり、それぞれ異なるトレードオフを持っています。 | パターン | メカニズム | 適用場面 | リスク | |---------|-----------|---------|-------| | ワークスペース | `terraform workspace select prod` | シンプルなプロジェクト、環境間で同一設定 | ステートバックエンドを共有、誤ったワークスペースでの`apply`が容易 | | ディレクトリ分離 | 個別の`dev/`、`staging/`、`prod/`ディレクトリ | 環境間の完全な分離 | ディレクトリ間のコード重複 | | Terragrunt | DRYラッパーによるバックエンド設定生成 | 大規模マルチアカウント構成 | 追加ツールへの依存 | 共有モジュールを用いたディレクトリごとの環境分離が、本番環境では最も一般的なアプローチです。各環境ディレクトリには、異なる変数値で同じモジュールを呼び出す`main.tf`が含まれ、それぞれ独立したステートファイルを持ちます。 ### `terraform workspace`とディレクトリ分離の違い ワークスペースは、同一バックエンド内に名前付きのステートファイルを作成します。`terraform workspace select staging`でワークスペースを切り替えると、Terraformが読み書きするステートファイルが変更されますが、設定自体は同一のままです。 ワークスペースの制約は、同じバックエンド設定とプロバイダー設定を共有する点にあります。ディレクトリ分離はより強い境界を提供し、各環境が異なるAWSアカウント、異なるステートバックエンド、さらには異なるプロバイダーバージョンを使用できます。厳格な影響範囲の制御が求められる規制環境では、ディレクトリ分離がより安全な選択です。 ## プロバイダー、データソース、リソースのライフサイクル ### プロバイダーとは何か、どのように設定するか プロバイダーは、HCL設定を特定のプラットフォームに対するAPI呼び出しに変換するプラグインです。AWSプロバイダーはAWS APIを呼び出し、KubernetesプロバイダーはKubernetes APIサーバーと通信します。 ```hcl # providers.tf terraform { required_providers { aws = { source = "hashicorp/aws" version = "~> 5.80" } } } provider "aws" { region = var.aws_region default_tags { tags = { Environment = var.environment ManagedBy = "terraform" Team = var.team_name } } } ``` `~> 5.80`のバージョン制約はパッチアップデート(5.80.x)を許可しますが、マイナーバージョンの更新はブロックし、安定性とセキュリティパッチのバランスを保ちます。`default_tags`ブロックは、プロバイダーが作成するすべてのリソースに一貫したタグ付けを適用する機能で、ガバナンスやコスト配分に関する面接の議論でよく取り上げられるポイントです。 ### データソースとリソースの違い リソース(`resource`ブロック)はインフラストラクチャの作成、更新、削除を行います。データソース(`data`ブロック)は、既存のインフラストラクチャを管理せずに読み取ります。 ```hcl # データソース - 既存のAMIを読み取る(作成は行わない) data "aws_ami" "ubuntu" { most_recent = true owners = ["099720109477"] # Canonical filter { name = "name" values = ["ubuntu/images/hvm-ssd-gp3/ubuntu-noble-24.04-amd64-server-*"] } } # リソース - データソースを使用してEC2インスタンスを作成 resource "aws_instance" "web" { ami = data.aws_ami.ubuntu.id instance_type = "t3.micro" } ``` データソースは`plan`の段階で評価されるため、共有インフラストラクチャの参照(他チームが作成したVPC)、動的な値の取得(最新のAMI ID)、外部設定の読み取り(SSMパラメーター、Vaultシークレット)に活用できます。 > **ライフサイクルメタ引数** > > 面接で頻繁に登場する3つのライフサイクルルールがあります。`create_before_destroy`(ゼロダウンタイムでの置換)、`prevent_destroy`(データベースなどの重要リソースの保護)、`ignore_changes`(ASGの希望キャパシティなど、Terraform外で変更されたフィールドのドリフト回避)です。 ## 高度なトピック:Import、Movedブロック、テスト ### `terraform import`の仕組みと使用場面 `terraform import`は、既存のクラウドリソースをTerraformリソースブロックに関連付けます。典型的なシナリオは、インフラストラクチャが手動(ClickOps)または別のツールで作成され、チームがTerraformで管理したいケースです。 Terraform 1.5以降では、CLIのみのワークフローに代わり、設定ファイル内に`import`ブロックを直接記述できるようになりました。 ```hcl # import.tf import { to = aws_s3_bucket.legacy_data id = "my-legacy-bucket-name" } resource "aws_s3_bucket" "legacy_data" { bucket = "my-legacy-bucket-name" } ``` このブロックを含めて`terraform plan`を実行すると、既存のバケットをステートに取り込むplanが生成されます。この宣言的なインポート方法はプルリクエストでレビュー可能で、再現性があり、ステートへの直接的なCLIアクセスを必要としません。 ### `moved`ブロックとは Terraformコードのリファクタリング(リソースの名前変更、モジュールへの移動)では、従来`terraform state mv`コマンドが必要でした。`moved`ブロックはこれを宣言的に処理します。 ```hcl # リソースの名前を"web"から"app"に変更 moved { from = aws_instance.web to = aws_instance.app } ``` Terraformはplan時にこの移動を認識し、ステートを自動的に更新するため、削除と再作成のサイクルを回避できます。大規模な設定をモジュールに再構成する際に非常に有用な機能です。 ### Terraformテストの仕組み Terraform 1.6以降には、`.tftest.hcl`ファイルを使用するネイティブテストフレームワークが組み込まれています。 ```hcl # tests/vpc.tftest.hcl run "creates_vpc_with_correct_cidr" { command = plan assert { condition = aws_vpc.main.cidr_block == "10.0.0.0/16" error_message = "VPC CIDR block does not match expected value" } } run "creates_three_private_subnets" { command = plan assert { condition = length(aws_subnet.private) == 3 error_message = "Expected 3 private subnets" } } ``` Terraform 1.14では、関数を受け入れるモックブロック、失敗したテストのデバッグ用の`skip_cleanup`、分離されたテストステート用のrunブロック内のバックエンドブロックが追加されました。ネイティブテストにより、基本的な検証にTerratestなどの外部ツールを使用する必要がなくなりました。 ## CI/CDパイプラインにおけるTerraform ### 本番環境のTerraformパイプラインの構成 堅牢なCI/CDパイプラインは、すべての段階で安全性を確保します。 1. **Lintと検証**:`terraform fmt -check`と`terraform validate`で構文の問題を検出します。 2. **PR時のplan実行**:すべてのプルリクエストで`terraform plan`を実行し、出力をPRコメントとして投稿します。レビュー済みのplanなしにapplyは行いません。 3. **ポリシーチェック**:OPA(Open Policy Agent)、Sentinel(HCP Terraform)、Checkovなどのツールで、planを組織ポリシー(パブリックS3バケットの禁止、暗号化の必須化、必須タグ)に照らして検証します。 4. **マージ時のapply実行**:PRの承認とポリシーチェックの通過後、保存されたplanファイルから`terraform apply`が自動実行されます。 5. **ステートバックアップ**:apply後、パイプラインはステートの整合性を検証し、バックエンドのバージョニングが新しいステートバージョンを記録します。 本番環境に対して、ローカルマシンから`terraform apply`を実行すべきではありません。すべての本番applyはパイプラインを通じて行われるのが原則です。 ## まとめ Terraform面接対策の重要なポイントを整理します。 - ステート管理は最も重要なトピックです。面接に臨む前に、リモートバックエンド、ロック、暗号化、災害復旧戦略を十分に理解しておく必要があります。 - モジュール設計はジュニアとシニアの候補者を分ける要素です。明確なインターフェースと最小限のスコープを持つ、再利用可能でバージョン管理されたモジュールの構築能力を示すことが重要です。 - plan/applyワークフローを深く理解する必要があります。planをファイルに保存する理由、DAGが実行順序を決定する仕組み、`-target`の動作(およびその使用を控えるべき理由)を説明できるようにしてください。 - Terraform 1.14は、モジュールソースでの変数使用、テスト機能の拡張、HCPとのより緊密な統合をもたらします。最新機能に言及することで、エコシステムへの積極的な関与を示すことができます。 - TerraformとOpenTofuの状況について正直に対応する必要があります。ライセンスの分裂、機能の分岐、各ツールが適する場面を理解していることは、構文知識を超えたアーキテクチャの成熟度を示します。 - [DevOps面接の基本](/blog/devops/essential-devops-interview-questions)をTerraform固有の知識と合わせて説明する練習が有効です。面接官はIaCの質問と幅広いインフラトピックを組み合わせることがよくあります。 - [Kubernetesデプロイメント](/blog/devops/kubernetes-deploying-first-application)の概念も確認してください。TerraformはKubernetesワークロードが実行されるクラスターのプロビジョニングに頻繁に使用されます。 --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/ja/blog/devops/terraform-interview-questions-infrastructure-as-code