【版】terraform planの使い方完全ガイド2024 〜エラー対処から本番運用まで〜

terraform planとは?初心者でもわかる基礎知識

terraform planが必要な理由と主なメリット

Terraform planは、Infrastructure as Code(IaC)を実践する上で最も重要なコマンドの1つです。このコマンドは、Terraformの実行計画を確認するためのものであり、実際のインフラ変更を行う前の「事前確認」として機能します。

主な役割と重要性

  1. 変更内容の可視化
  • 追加されるリソース(+で表示)
  • 変更されるリソース(~で表示)
  • 削除されるリソース(-で表示)
  • 置き換えが必要なリソース(-/+で表示)
  1. リスク軽減
  • 意図しない変更の早期発見
  • 本番環境への影響度の事前評価
  • コスト増加につながる変更の検出

主なメリット

メリット説明
安全性の向上実際の適用前に変更内容を確認できる
コスト管理リソースの追加・変更による費用への影響を事前に把握
チーム協業変更内容をチームで共有・レビュー可能
監査対応インフラ変更の履歴として活用可能

実行環境の準備方法と基本的なコマンド体系

実行環境の準備

  1. Terraformのインストール
# macOSの場合
brew install terraform

# Linuxの場合
wget https://releases.hashicorp.com/terraform/1.7.0/terraform_1.7.0_linux_amd64.zip
unzip terraform_1.7.0_linux_amd64.zip
sudo mv terraform /usr/local/bin/
  1. AWS認証情報の設定
# AWS CLIの設定
aws configure

# または環境変数での設定
export AWS_ACCESS_KEY_ID="your_access_key"
export AWS_SECRET_ACCESS_KEY="your_secret_key"
export AWS_DEFAULT_REGION="ap-northeast-1"

基本的なコマンド体系

Terraform planを効果的に使用するための基本的なコマンドフロー:

  1. 初期化(必須)
terraform init  # プロバイダーのダウンロードと初期化
  1. 構文チェック(推奨)
terraform fmt   # コードフォーマットの統一
terraform validate  # 構文の検証
  1. 実行計画の確認
terraform plan  # 基本的な実行計画の確認
terraform plan -out=plan.tfplan  # 実行計画の保存

実践的な利用シーン

1. 新規環境構築時

# 基本的なEC2インスタンス作成の例
resource "aws_instance" "example" {
  ami           = "ami-0c3fd0f5d33134a76"
  instance_type = "t3.micro"

  tags = {
    Name = "terraform-example"
  }
}

実行結果の例:

Terraform will perform the following actions:

  + aws_instance.example
      id:                           <computed>
      ami:                         "ami-0c3fd0f5d33134a76"
      instance_type:               "t3.micro"
      tags.%:                      "1"
      tags.Name:                   "terraform-example"

2. リソース更新時

# インスタンスタイプの変更
resource "aws_instance" "example" {
  ami           = "ami-0c3fd0f5d33134a76"
  instance_type = "t3.small"  # micro から small へ変更

  tags = {
    Name = "terraform-example"
  }
}

実行結果の例:

Terraform will perform the following actions:

  ~ aws_instance.example
      instance_type:               "t3.micro" => "t3.small"

このように、terraform planは単なる実行計画の確認ツールではなく、インフラストラクチャの変更管理における重要な安全装置として機能します。次のセクションでは、より実践的な使用方法と重要なオプションについて説明していきます。

terraform planの実践的な使い方と重要オプション

基本的なコマンド実行と結果の見方

terraform planコマンドの実行結果は、インフラストラクチャの変更を理解する上で重要な情報を提供します。以下で、基本的な使い方と結果の解釈方法を説明します。

基本的な実行方法

# 基本的な実行
terraform plan

# 実行計画の保存
terraform plan -out=tfplan

# 変数ファイルの指定
terraform plan -var-file="prod.tfvars"

実行結果の見方

実行結果には以下のような記号が表示されます:

記号意味説明
+作成新しいリソースが作成される
削除既存のリソースが削除される
~更新リソースが更新される
-/+再作成リソースが一旦削除され、再作成される

便利なオプションと活用のポイント

重要なオプション一覧

  1. -detailed-exitcode
terraform plan -detailed-exitcode
  • 0: 変更なし
  • 1: エラー
  • 2: 変更あり
  1. -var と -var-file
# 単一の変数指定
terraform plan -var="environment=production"

# 変数ファイルの指定
terraform plan -var-file="production.tfvars"
  1. -target
# 特定のリソースのみを対象
terraform plan -target=aws_instance.web
  1. -refresh
# 状態の更新をスキップ
terraform plan -refresh=false

オプションの活用シーン

オプション使用シーンメリット
-outCI/CD環境計画を保存し、適用時に再実行を防ぐ
-target部分的な変更特定のリソースのみを対象に計画を確認
-var-file環境別の設定環境ごとに異なる設定を管理
-detailed-exitcode自動化プロセススクリプトでの判定が容易

実行計画の詳細な確認方法

1. リソース依存関係の確認

# 依存関係を含む詳細な計画の出力
terraform plan -detailed-exitcode -out=tfplan
terraform show tfplan

2. コスト見積もりの確認

# Infracostを使用したコスト予測
terraform plan -out=tfplan
infracost breakdown --path tfplan

3. セキュリティチェック

# tfsecを使用したセキュリティスキャン
terraform plan -out=tfplan
tfsec .

実践的な使用例

  1. 環境別の設定管理
# development.tfvars
environment = "development"
instance_type = "t3.micro"

# production.tfvars
environment = "production"
instance_type = "t3.small"

# main.tf
resource "aws_instance" "example" {
  ami           = var.ami_id
  instance_type = var.instance_type

  tags = {
    Environment = var.environment
  }
}

実行コマンド:

# 開発環境用の計画
terraform plan -var-file="development.tfvars"

# 本番環境用の計画
terraform plan -var-file="production.tfvars"
  1. 部分的な変更の確認
# 特定のEC2インスタンスのみを対象とした計画
terraform plan -target=aws_instance.web_server -out=web_server.tfplan

# 特定のモジュール内のリソースを対象とした計画
terraform plan -target=module.networking
  1. 詳細な差分の確認
# JSON形式での出力
terraform plan -json | jq

# 人間が読みやすい形式での詳細表示
terraform plan -no-color > plan.txt

これらのオプションと使用方法を理解することで、より効果的なInfrastructure as Codeの実践が可能になります。次のセクションでは、実際の運用で発生しがちなエラーとその対処法について説明していきます。

terraform planのエラー対処法と運用のコツ

よくあるエラーとトラブルシューティング

terraform planを使用する際に発生する一般的なエラーとその解決方法について説明します。

1. 認証関連のエラー

Error: error configuring Terraform AWS Provider: no valid credential sources found

解決方法:

# AWS認証情報の設定
export AWS_ACCESS_KEY_ID="your_access_key"
export AWS_SECRET_ACCESS_KEY="your_secret_key"

# または、AWS CLIの設定
aws configure

# プロファイルの指定
export AWS_PROFILE=production

2. 状態ファイル関連のエラー

Error: Error loading state: state data in S3 does not have the expected content.

解決手順:

  1. バックエンドの設定確認
# backend.tf
terraform {
  backend "s3" {
    bucket = "terraform-state-bucket"
    key    = "terraform.tfstate"
    region = "ap-northeast-1"
    dynamodb_table = "terraform-lock"
  }
}
  1. ロック解除(必要な場合)
# DynamoDBのロック解除
aws dynamodb delete-item \
    --table-name terraform-lock \
    --key '{"LockID": {"S": "terraform-state-bucket/terraform.tfstate"}}'

3. リソース依存関係のエラー

Error: Resource depends on non-existent resource

解決方法:

# 明示的な依存関係の定義
depends_on = [
  aws_vpc.main,
  aws_subnet.public
]

# データソースの使用
data "aws_vpc" "existing" {
  id = var.vpc_id
}

セキュリティリスクの回避方法

1. アクセス権限の最小化

# IAMポリシーの例
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ec2:Describe*",
        "ec2:RunInstances",
        "ec2:TerminateInstances"
      ],
      "Resource": "*"
    }
  ]
}

2. 機密情報の管理

方法使用シーン実装例
環境変数CI/CD環境TF_VAR_database_password="${DB_PASSWORD}"
AWS Secrets Manager本番環境data "aws_secretsmanager_secret_version" "db_password"
HashiCorp Vault大規模環境data "vault_generic_secret" "db_creds"

3. セキュリティスキャンの導入

# tfsecによるセキュリティチェック
tfsec .

# checkovによる追加チェック
checkov -d .

コスト最適化のためのベストプラクティス

1. リソースのライフサイクル管理

# 開発環境のリソース自動停止
resource "aws_instance" "dev" {
  # ... other configurations ...

  lifecycle {
    create_before_destroy = true
  }

  # 自動停止のタグ
  tags = {
    AutoStop = "true"
    Environment = "development"
  }
}

2. コスト見積もりの自動化

# Infracostを使用したコスト予測
terraform plan -out=tfplan
infracost breakdown --path tfplan

# コスト閾値チェック
infracost breakdown --path tfplan --compare-to=baseline.json

3. リソース最適化のベストプラクティス

最適化ポイント実装方法期待効果
インスタンスサイズ自動スケーリング設定必要に応じたリソース調整
ストレージライフサイクルポリシー古いデータの自動アーカイブ
リザーブドインスタンス長期利用リソースの予約コストの大幅削減

実装例:

# 自動スケーリングの設定
resource "aws_autoscaling_group" "web" {
  desired_capacity    = 2
  max_size           = 4
  min_size           = 1
  target_group_arns  = [aws_lb_target_group.web.arn]
  vpc_zone_identifier = aws_subnet.public[*].id

  tag {
    key                 = "Environment"
    value               = var.environment
    propagate_at_launch = true
  }
}

# スケーリングポリシー
resource "aws_autoscaling_policy" "web_scale_out" {
  name                   = "web_scale_out"
  scaling_adjustment     = 1
  adjustment_type        = "ChangeInCapacity"
  cooldown              = 300
  autoscaling_group_name = aws_autoscaling_group.web.name
}

運用のベストプラクティス

  1. 計画的な実行
# 変更の影響範囲の確認
terraform plan -detailed-exitcode

# 変更履歴の保存
terraform plan -out=change_$(date +%Y%m%d_%H%M%S).tfplan
  1. モジュール化による再利用
# 共通モジュールの使用例
module "vpc" {
  source = "./modules/vpc"

  environment = var.environment
  cidr_block  = var.vpc_cidr
}

module "security" {
  source = "./modules/security"

  vpc_id = module.vpc.vpc_id
}

これらの実践的なアプローチを適用することで、より安全で効率的なTerraform運用が可能になります。次のセクションでは、チーム開発における具体的な活用方法について説明していきます。

チーム開発におけるterraform planの活用方法

GitHubとの連携によるワークフロー自動化

1. GitHub Actionsの設定

# .github/workflows/terraform.yml
name: "Terraform"

on:
  pull_request:
    branches: [ main ]
  push:
    branches: [ main ]

jobs:
  terraform:
    name: 'Terraform'
    runs-on: ubuntu-latest

    steps:
    - name: Checkout
      uses: actions/checkout@v2

    - name: Setup Terraform
      uses: hashicorp/setup-terraform@v1
      with:
        terraform_version: 1.7.0

    - name: Configure AWS Credentials
      uses: aws-actions/configure-aws-credentials@v1
      with:
        aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
        aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        aws-region: ap-northeast-1

    - name: Terraform fmt
      id: fmt
      run: terraform fmt -check
      continue-on-error: true

    - name: Terraform Init
      id: init
      run: terraform init

    - name: Terraform Plan
      id: plan
      run: terraform plan -no-color
      continue-on-error: true

    - name: Update Pull Request
      uses: actions/github-script@v6
      if: github.event_name == 'pull_request'
      env:
        PLAN: "${{ steps.plan.outputs.stdout }}"
      with:
        github-token: ${{ secrets.GITHUB_TOKEN }}
        script: |
          const output = `#### Terraform Plan 📝
          <details><summary>Show Plan</summary>

          \`\`\`${process.env.PLAN}\`\`\`

          </details>`;

          github.rest.issues.createComment({
            issue_number: context.issue.number,
            owner: context.repo.owner,
            repo: context.repo.repo,
            body: output
          })

2. プルリクエストワークフロー

  1. ブランチ戦略
# 機能開発用ブランチの作成
git checkout -b feature/add-new-resource

# 変更の作成とコミット
git add .
git commit -m "feat: Add new EC2 instance for web server"

# プルリクエストの作成
git push origin feature/add-new-resource
  1. 自動チェック項目
  • terraform fmt
  • terraform validate
  • terraform plan
  • セキュリティスキャン(tfsec)
  • コスト予測(Infracost)

チームでの承認フローと権限管理

1. IAMポリシーの設定

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "terraform:plan",
        "terraform:apply"
      ],
      "Resource": "*",
      "Condition": {
        "StringEquals": {
          "aws:RequestedRegion": ["ap-northeast-1"]
        }
      }
    }
  ]
}

2. 承認フローの実装

フェーズ担当者確認項目
計画作成開発者リソース構成、依存関係
コードレビューレビュアーコーディング規約、ベストプラクティス
セキュリティレビューセキュリティ担当セキュリティ要件、コンプライアンス
最終承認インフラ管理者本番環境への影響、コスト

3. 環境別の権限設定

# 環境別のバックエンド設定
terraform {
  backend "s3" {
    bucket         = "terraform-state-${var.environment}"
    key            = "${var.project}/${var.environment}/terraform.tfstate"
    region         = "ap-northeast-1"
    dynamodb_table = "terraform-lock-${var.environment}"
    role_arn       = "arn:aws:iam::${var.account_id}:role/terraform-${var.environment}"
  }
}

効率的なレビュープロセスの構築方法

1. レビューチェックリスト

# Terraform Plan レビューチェックリスト

## リソース構成
- [ ] 新規リソースの必要性
- [ ] リソース設定の妥当性
- [ ] 依存関係の正しさ

## セキュリティ
- [ ] IAM権限の最小化
- [ ] セキュリティグループの適切な設定
- [ ] 暗号化設定の確認

## コスト
- [ ] リソースサイズの適切性
- [ ] 予測コストの妥当性
- [ ] コスト最適化の可能性

## 運用性
- [ ] モニタリング設定
- [ ] バックアップ設定
- [ ] メンテナンス性

2. 自動レビューツールの導入

# pre-commit hooks の設定
cat << EOF > .pre-commit-config.yaml
repos:
- repo: https://github.com/antonbabenko/pre-commit-terraform
  rev: v1.83.5
  hooks:
    - id: terraform_fmt
    - id: terraform_validate
    - id: terraform_docs
    - id: terraform_tflint
    - id: terraform_tfsec
EOF

# pre-commit の設定
pre-commit install

3. レビューコメントテンプレート

## Terraform Plan レビュー結果

### 変更概要
- 追加されるリソース: X個
- 変更されるリソース: Y個
- 削除されるリソース: Z個

### 重要な変更点
1. [リソース名]
   - 変更内容:
   - 影響範囲:
   - リスク評価:

### セキュリティ評価
- [ ] セキュリティグループの設定は適切
- [ ] IAM権限は最小限
- [ ] 暗号化設定は要件を満たしている

### コスト評価
- 予測される月額コスト: $XXX
- 前月比: +/-$XXX

### 推奨事項
1. [推奨内容]
   - 理由:
   - 実装案:

### 決定
- [ ] 承認
- [ ] 条件付き承認
- [ ] 要修正

これらの仕組みを導入することで、チームでの効率的なTerraform運用が可能になります。次のセクションでは、より応用的なテクニックと実践例について説明していきます。

terraform planの応用的なテクニックと実践例

大規模環境での実行計画の管理方法

1. ワークスペースの効果的な活用

# 複数環境の構成管理
terraform {
  backend "s3" {
    bucket         = "terraform-state-company"
    key            = "workspaces/${terraform.workspace}/terraform.tfstate"
    region         = "ap-northeast-1"
    dynamodb_table = "terraform-lock"
  }
}

# 環境別の設定
locals {
  workspace_config = {
    development = {
      instance_type = "t3.micro"
      instance_count = 1
    }
    staging = {
      instance_type = "t3.small"
      instance_count = 2
    }
    production = {
      instance_type = "t3.medium"
      instance_count = 3
    }
  }

  config = local.workspace_config[terraform.workspace]
}

2. 大規模実行計画の最適化

# パラレル実行の設定
terraform {
  required_version = ">= 1.7.0"

  backend "s3" {
    bucket         = "terraform-state-company"
    key            = "env/${terraform.workspace}/terraform.tfstate"
    region         = "ap-northeast-1"
    dynamodb_table = "terraform-lock"
  }
}

# リソースのターゲット指定
resource "aws_instance" "web" {
  count = local.config.instance_count

  ami           = data.aws_ami.amazon_linux_2.id
  instance_type = local.config.instance_type

  tags = {
    Name = "web-${count.index + 1}"
    Environment = terraform.workspace
  }

  lifecycle {
    create_before_destroy = true
  }
}

モジュール化されたコードでの使い方

1. 再利用可能なモジュールの設計

# modules/vpc/main.tf
module "vpc" {
  source = "terraform-aws-modules/vpc/aws"

  name = var.vpc_name
  cidr = var.vpc_cidr

  azs             = var.availability_zones
  private_subnets = var.private_subnet_cidrs
  public_subnets  = var.public_subnet_cidrs

  enable_nat_gateway = true
  single_nat_gateway = var.environment != "production"

  tags = merge(
    var.tags,
    {
      Environment = var.environment
      Terraform   = "true"
    }
  )
}

# modules/vpc/variables.tf
variable "vpc_name" {
  type = string
}

variable "vpc_cidr" {
  type = string
}

variable "availability_zones" {
  type = list(string)
}

variable "environment" {
  type = string
}

# モジュールの使用例
module "production_vpc" {
  source = "./modules/vpc"

  vpc_name = "production-vpc"
  vpc_cidr = "10.0.0.0/16"
  availability_zones = ["ap-northeast-1a", "ap-northeast-1c"]
  environment = "production"

  tags = {
    Project = "main-infrastructure"
  }
}

2. モジュールの依存関係管理

# 依存関係を持つモジュールの例
module "security_group" {
  source = "./modules/security"

  vpc_id = module.vpc.vpc_id
  environment = var.environment
}

module "application" {
  source = "./modules/application"

  vpc_id = module.vpc.vpc_id
  security_group_ids = [module.security_group.sg_id]
  subnet_ids = module.vpc.private_subnet_ids

  depends_on = [
    module.vpc,
    module.security_group
  ]
}

本番環境での安全な実行のチェックリスト

1. 実行前の確認事項

## デプロイメント前チェックリスト

### 1. コード品質
- [ ] terraform fmt による整形確認
- [ ] terraform validate によるバリデーション
- [ ] モジュールのバージョン確認

### 2. セキュリティ
- [ ] IAM権限の最小化確認
- [ ] セキュリティグループの設定確認
- [ ] 機密情報の適切な管理

### 3. 可用性
- [ ] バックアップ設定の確認
- [ ] 冗長構成の確認
- [ ] ロールバック手順の準備

### 4. コスト
- [ ] リソースサイジングの確認
- [ ] コスト予測の実施
- [ ] 不要リソースの確認

2. 実装例:安全な実行計画の管理

# 本番環境用の追加チェック
locals {
  is_production = terraform.workspace == "production"

  # 本番環境での必須タグ
  required_tags = {
    Environment  = terraform.workspace
    Owner        = "infrastructure-team"
    CostCenter   = "infrastructure"
    Project      = "main-platform"
  }
}

# タグ付けルールの強制
resource "aws_instance" "example" {
  # ... other configurations ...

  tags = merge(
    local.required_tags,
    var.additional_tags,
    {
      Name = "app-server-${count.index + 1}"
    }
  )

  lifecycle {
    precondition {
      condition     = !local.is_production || var.instance_type != "t3.micro"
      error_message = "Production environment cannot use t3.micro instances."
    }
  }
}

# バックアップ設定の強制
resource "aws_backup_plan" "example" {
  count = local.is_production ? 1 : 0

  name = "production-backup-plan"

  rule {
    rule_name         = "daily-backup"
    target_vault_name = aws_backup_vault.main[0].name
    schedule          = "cron(0 1 * * ? *)"

    lifecycle {
      delete_after = 30
    }
  }
}

3. 大規模環境での実践的なテクニック

# 条件付きリソース作成
locals {
  create_resources = {
    nat_gateway     = var.environment == "production"
    backup          = var.environment == "production"
    monitoring      = contains(["staging", "production"], var.environment)
    alarm           = contains(["staging", "production"], var.environment)
  }
}

# カスタムバリデーション
variable "allowed_instance_types" {
  type = map(list(string))
  default = {
    development = ["t3.micro", "t3.small"]
    staging     = ["t3.small", "t3.medium"]
    production  = ["t3.medium", "t3.large", "m5.large"]
  }
}

# インスタンスタイプのバリデーション
resource "aws_instance" "app" {
  # ... other configurations ...

  lifecycle {
    precondition {
      condition     = contains(var.allowed_instance_types[var.environment], var.instance_type)
      error_message = "Selected instance type is not allowed in this environment."
    }
  }
}

# 複数リージョンでの展開
provider "aws" {
  alias  = "tokyo"
  region = "ap-northeast-1"
}

provider "aws" {
  alias  = "osaka"
  region = "ap-northeast-3"
}

# リージョン別のリソース作成
module "tokyo_infrastructure" {
  source = "./modules/regional-infrastructure"

  providers = {
    aws = aws.tokyo
  }

  environment = var.environment
  region_name = "tokyo"
}

module "osaka_infrastructure" {
  source = "./modules/regional-infrastructure"

  providers = {
    aws = aws.osaka
  }

  environment = var.environment
  region_name = "osaka"
}

これらの応用的なテクニックと実践例を活用することで、大規模な本番環境でも安全かつ効率的なTerraform運用が可能になります。