terraform planとは?初心者でもわかる基礎知識
terraform planが必要な理由と主なメリット
Terraform planは、Infrastructure as Code(IaC)を実践する上で最も重要なコマンドの1つです。このコマンドは、Terraformの実行計画を確認するためのものであり、実際のインフラ変更を行う前の「事前確認」として機能します。
主な役割と重要性
- 変更内容の可視化
- 追加されるリソース(
+
で表示) - 変更されるリソース(
~
で表示) - 削除されるリソース(
-
で表示) - 置き換えが必要なリソース(
-/+
で表示)
- リスク軽減
- 意図しない変更の早期発見
- 本番環境への影響度の事前評価
- コスト増加につながる変更の検出
主なメリット
メリット | 説明 |
---|---|
安全性の向上 | 実際の適用前に変更内容を確認できる |
コスト管理 | リソースの追加・変更による費用への影響を事前に把握 |
チーム協業 | 変更内容をチームで共有・レビュー可能 |
監査対応 | インフラ変更の履歴として活用可能 |
実行環境の準備方法と基本的なコマンド体系
実行環境の準備
- 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/
- 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を効果的に使用するための基本的なコマンドフロー:
- 初期化(必須)
terraform init # プロバイダーのダウンロードと初期化
- 構文チェック(推奨)
terraform fmt # コードフォーマットの統一 terraform validate # 構文の検証
- 実行計画の確認
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"
実行結果の見方
実行結果には以下のような記号が表示されます:
記号 | 意味 | 説明 |
---|---|---|
+ | 作成 | 新しいリソースが作成される |
– | 削除 | 既存のリソースが削除される |
~ | 更新 | リソースが更新される |
-/+ | 再作成 | リソースが一旦削除され、再作成される |
便利なオプションと活用のポイント
重要なオプション一覧
- -detailed-exitcode
terraform plan -detailed-exitcode
- 0: 変更なし
- 1: エラー
- 2: 変更あり
- -var と -var-file
# 単一の変数指定 terraform plan -var="environment=production" # 変数ファイルの指定 terraform plan -var-file="production.tfvars"
- -target
# 特定のリソースのみを対象 terraform plan -target=aws_instance.web
- -refresh
# 状態の更新をスキップ terraform plan -refresh=false
オプションの活用シーン
オプション | 使用シーン | メリット |
---|---|---|
-out | CI/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 .
実践的な使用例
- 環境別の設定管理
# 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"
- 部分的な変更の確認
# 特定のEC2インスタンスのみを対象とした計画 terraform plan -target=aws_instance.web_server -out=web_server.tfplan # 特定のモジュール内のリソースを対象とした計画 terraform plan -target=module.networking
- 詳細な差分の確認
# 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.
解決手順:
- バックエンドの設定確認
# backend.tf terraform { backend "s3" { bucket = "terraform-state-bucket" key = "terraform.tfstate" region = "ap-northeast-1" dynamodb_table = "terraform-lock" } }
- ロック解除(必要な場合)
# 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 }
運用のベストプラクティス
- 計画的な実行
# 変更の影響範囲の確認 terraform plan -detailed-exitcode # 変更履歴の保存 terraform plan -out=change_$(date +%Y%m%d_%H%M%S).tfplan
- モジュール化による再利用
# 共通モジュールの使用例 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. プルリクエストワークフロー
- ブランチ戦略
# 機能開発用ブランチの作成 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
- 自動チェック項目
- 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運用が可能になります。