Terraform Workspace とは? – 複数環境管理の新標準
Terraform Workspaceは、同一のTerraformコード構成から複数の異なるインフラ環境を管理するための機能です。開発(dev)、ステージング(staging)、本番(prod)といった複数の環境を、コードの重複なく効率的に管理できます。
workspace が解決する 3 つの課題
- コード管理の複雑さ
- 従来:環境ごとに異なるディレクトリやリポジトリが必要
- 解決後:同一コードベースで複数環境を管理可能
- メリット:コードの一元管理による保守性向上
- リソース分離の確実性
- 従来:環境の分離にタグや命名規則のみを使用
- 解決後:workspace単位で完全な論理分離を実現
- メリット:誤った環境へのデプロイを防止
- 状態管理の煩雑さ
- 従来:環境ごとに異なるstate fileを手動管理
- 解決後:workspaceが自動的にstate管理を実施
- メリット:状態管理の自動化によるヒューマンエラー防止
従来の環境管理との比較
管理項目 | 従来の方式 | Workspace方式 | メリット |
---|---|---|---|
コード管理 | 環境ごとにディレクトリ作成 | 単一コードで複数環境 | メンテナンス工数削減 |
環境分離 | 命名規則による論理分離 | workspace単位の完全分離 | セキュリティ向上 |
設定値管理 | 環境変数やファイル | workspace変数 | 一元管理が容易 |
デプロイ管理 | 手動での環境選択 | workspaceでの自動制御 | オペレーションミス防止 |
実務での具体的な活用例:
# workspace変数を使用した環境別設定 locals { env = terraform.workspace instance_type = { default = "t2.micro" staging = "t2.medium" production = "t2.large" } } resource "aws_instance" "app_server" { instance_type = local.instance_type[local.env] tags = { Environment = local.env } }
この方式により、同一のコードベースから環境に応じた適切なリソースをデプロイできます。コードの重複を避けながら、各環境の要件に合わせたカスタマイズが可能となります。
Terraform Workspace の基本的な使い方
workspace 作成から削除までの流れ
基本的なworkspaceのライフサイクル管理コマンド:
# 現在のworkspace一覧を表示 $ terraform workspace list * default # 新しいworkspaceの作成 $ terraform workspace new staging Created and switched to workspace "staging"! # workspace切り替え $ terraform workspace select production # workspace削除(すべてのリソースが破棄された後のみ可能) $ terraform workspace delete staging
環境変数の便利な使い方
workspaceに応じた設定値の管理方法:
# variables.tf variable "instance_sizes" { type = map(string) default = { default = "t2.micro" staging = "t2.medium" production = "t2.large" } } # main.tf resource "aws_instance" "web" { instance_type = var.instance_sizes[terraform.workspace] tags = { Name = "${terraform.workspace}-web-server" Environment = terraform.workspace } }
環境変数による制御:
# 環境別の変数設定 $ export TF_WORKSPACE=staging $ export TF_VAR_region="ap-northeast-1" # 特定環境のみで実行する場合の条件分岐 $ [ "$TF_WORKSPACE" = "production" ] && terraform apply
状態管理の基礎知識
状態ファイルの管理ベストプラクティス:
- バックエンド設定
terraform { backend "s3" { bucket = "terraform-states" key = "project/terraform.tfstate" region = "ap-northeast-1" # workspace毎に異なるDynamoDBテーブルでロック管理 dynamodb_table = "terraform-locks" } }
- 状態の確認方法
# 現在の状態を確認 $ terraform show # 状態ファイルのバックアップ $ terraform state pull > backup.tfstate # 特定リソースの状態確認 $ terraform state list $ terraform state show aws_instance.web
- 状態管理の重要ポイント
項目 | 推奨設定 | 理由 |
---|---|---|
バックエンド | S3 + DynamoDB | 状態の永続化とロック機能 |
暗号化 | 必須 | セキュリティ確保 |
バージョニング | 有効 | 復旧可能性の確保 |
アクセス制御 | IAMポリシー | 権限の最小化 |
これらの基本操作を理解することで、複数環境の効率的な管理が可能になります。特に本番環境では、状態管理の設定を慎重に行うことが重要です。
実践的なWorkspace活用術
本番・ステージング・開発環境の分離
# environments/main.tf locals { environment_config = { default = { instance_type = "t2.micro" instance_count = 1 backup_retention = 7 } staging = { instance_type = "t2.medium" instance_count = 2 backup_retention = 14 } production = { instance_type = "t2.large" instance_count = 3 backup_retention = 30 } } config = local.environment_config[terraform.workspace] } resource "aws_instance" "app" { count = local.config.instance_count instance_type = local.config.instance_type lifecycle { prevent_destroy = terraform.workspace == "production" } }
環境ごとの設定値管理テクニック
- 階層化された変数管理
# config/common.tfvars region = "ap-northeast-1" project = "microservice-app" # config/production.tfvars environment = "production" vpc_cidr = "10.0.0.0/16" enable_monitoring = true # 実行コマンド terraform plan \ -var-file="config/common.tfvars" \ -var-file="config/${terraform.workspace}.tfvars"
- 条件付きリソースプロビジョニング
resource "aws_cloudwatch_metric_alarm" "high_cpu" { count = terraform.workspace == "production" ? 1 : 0 alarm_name = "${terraform.workspace}-high-cpu" comparison_operator = "GreaterThanThreshold" evaluation_periods = "2" metric_name = "CPUUtilization" threshold = "80" }
バックエンドの共有戦略
- workspace対応のバックエンド設定
terraform { backend "s3" { bucket = "company-terraform-states" key = "microservices/terraform.tfstate" region = "ap-northeast-1" encrypt = true dynamodb_table = "terraform-locks" workspace_key_prefix = "environments" # 環境ごとに異なるキープレフィックス } }
- 状態共有のベストプラクティス
共有項目 | 推奨設定 | 注意点 |
---|---|---|
State格納 | 環境別のS3パス | キーの重複防止 |
ロック管理 | 共通DynamoDBテーブル | テーブル名の標準化 |
暗号化 | KMSによる暗号化 | 鍵の権限管理 |
アクセス制御 | IAMロール制御 | 最小権限の原則 |
- 実装例:環境別の状態分離
# backends/workspace.tf data "terraform_remote_state" "shared" { backend = "s3" config = { bucket = "company-terraform-states" key = "environments/${terraform.workspace}/shared.tfstate" region = "ap-northeast-1" } } # 共有リソースの参照 resource "aws_security_group" "app" { vpc_id = data.terraform_remote_state.shared.outputs.vpc_id tags = { Environment = terraform.workspace ManagedBy = "terraform" } }
このアプローチにより、環境分離とリソース共有の両立が実現できます。
Workspace のベストプラクティス
命名規則とタグ付けの標準化
locals { standard_tags = { Environment = terraform.workspace Project = var.project_name ManagedBy = "terraform" Team = var.team_name CostCenter = var.cost_center } } resource "aws_vpc" "main" { cidr_block = var.vpc_cidr tags = merge( local.standard_tags, { Name = "${terraform.workspace}-main-vpc" } ) }
命名規則ガイドライン:
要素 | パターン | 例 |
---|---|---|
Workspace名 | {env}-{region}-{purpose} | prod-ap-northeast-1-app |
リソース名 | {workspace}-{resource}-{count} | prod-web-server-01 |
タグキー | PascalCase | CostCenter, Environment |
アクセス制御とセキュリティ対策
- IAMポリシー設定
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:ListBucket", "s3:GetObject", "s3:PutObject" ], "Resource": [ "arn:aws:s3:::terraform-states", "arn:aws:s3:::terraform-states/environments/${aws:username}/*" ], "Condition": { "StringEquals": { "aws:RequestedWorkspace": ["staging", "development"] } } } ] }
- 環境別のセキュリティ制御
resource "aws_security_group" "app" { name = "${terraform.workspace}-app-sg" dynamic "ingress" { for_each = terraform.workspace == "production" ? ["10.0.0.0/8"] : ["0.0.0.0/0"] content { from_port = 443 to_port = 443 protocol = "tcp" cidr_blocks = [ingress.value] } } }
コスト最適化のためのワークスペース設計
- 環境別リソースサイジング
locals { sizing = { development = { instance_type = "t3.micro" autoscaling = { min = 1 max = 2 } } production = { instance_type = "t3.large" autoscaling = { min = 2 max = 10 } } } } resource "aws_autoscaling_group" "app" { min_size = local.sizing[terraform.workspace].autoscaling.min max_size = local.sizing[terraform.workspace].autoscaling.max instance_type = local.sizing[terraform.workspace].instance_type lifecycle { create_before_destroy = true } }
- コスト管理ポリシー
resource "aws_budgets_budget" "cost_limit" { count = terraform.workspace == "production" ? 1 : 0 name = "${terraform.workspace}-monthly-budget" budget_type = "COST" limit_amount = terraform.workspace == "production" ? "1000" : "100" limit_unit = "USD" time_period_start = "2024-01-01_00:00" time_unit = "MONTHLY" notification { comparison_operator = "GREATER_THAN" threshold = 80 threshold_type = "PERCENTAGE" notification_type = "FORECASTED" } }
セキュリティとコスト最適化のチェックリスト:
- [ ] 環境別のIAMロールを使用
- [ ] S3バケットの暗号化を有効化
- [ ] セキュリティグループの制限を環境別に設定
- [ ] 自動スケーリングの上限を環境別に制御
- [ ] コストアラートを適切なしきい値で設定
- [ ] 未使用リソースの自動停止を設定
よくあるトラブルと解決策
stateロックのキャッシュ解消法
- ロック解除手順
# ロック状態の確認 $ terraform force-unlock -force LOCK_ID # DynamoDBのロックエントリ確認 $ aws dynamodb get-item \ --table-name terraform-locks \ --key '{"LockID": {"S": "terraform-state/workspace-name"}}'
ロックトラブル対策:
terraform { backend "s3" { dynamodb_table = "terraform-locks" lock_timeout = "5m" # エラー時の再試行設定 retry_max = 5 retry_wait_min = 5 } }
環境中の設定漏れ防止策
- 変数検証の実装
variable "environment_type" { type = string description = "Environment type (production/staging/development)" validation { condition = contains(["production", "staging", "development"], var.environment_type) error_message = "環境タイプは production, staging, development のいずれかである必要があります。" } } locals { required_tags = { Environment = terraform.workspace Owner = var.owner CostCenter = var.cost_center } # タグの存在チェック validate_tags = [ for required_key in keys(local.required_tags) : contains(keys(var.tags), required_key) ] }
- 自動チェック用のnull_resource
resource "null_resource" "validation" { count = terraform.workspace == "production" ? 1 : 0 lifecycle { precondition { condition = var.backup_retention_days >= 30 error_message = "本番環境ではバックアップ保持期間は30日以上必要です。" } } }
リソース依存関係の管理方法
- 明示的な依存関係定義
# 依存関係の明示的な定義 resource "aws_instance" "web" { depends_on = [aws_vpc.main, aws_subnet.public] instance_type = "t3.micro" subnet_id = aws_subnet.public.id lifecycle { create_before_destroy = true prevent_destroy = terraform.workspace == "production" } } # データソースを使用した依存関係管理 data "terraform_remote_state" "vpc" { backend = "s3" config = { bucket = "terraform-states" key = "vpc/${terraform.workspace}/terraform.tfstate" } }
- モジュール間の依存関係制御
module "database" { source = "./modules/database" vpc_id = module.vpc.vpc_id subnet_ids = module.vpc.private_subnet_ids providers = { aws = aws.primary } } # クロスリージョン依存関係 provider "aws" { alias = "dr" region = "ap-northeast-2" } module "dr_database" { source = "./modules/database" providers = { aws = aws.dr } depends_on = [module.database] }
トラブルシューティングチェックリスト:
- [ ] State lockが残っていないか確認
- [ ] バックエンドの接続設定を確認
- [ ] 必須タグの設定漏れがないか確認
- [ ] リソース間の依存関係が適切か確認
- [ ] ライフサイクル設定が環境に適しているか確認