techblog

Terraform Workspaceで実現する環境分離とリモートステート連携

Terraform Workspaceを使った複数環境の分離方法とリモートステート連携の実践ガイド。同一コードベースでprod/stg環境を管理し、ワークスペース間でステートをS3バックエンド参照する具体的な手順を用いて解説します。

Terraform Workspaceで実現する環境分離とリモートステート連携

目次

  1. はじめに
  2. Terraform Workspaceとは
  3. 動作確認内容
  4. 流れ
    1. 環境準備
      1. S3バケットの作成
      2. 検証用Terraformファイルの作成
      3. プロジェクト初期化
    2. prodワークスペースの作成と適用
    3. stgワークスペースの作成と適用
    4. S3バケット内の状態確認
  5. まとめ

はじめに

こんにちは、今回は、より実践的な内容として、Terraformでの環境分離についてお話ししたいと思います。

Terraformを利用して、複数環境の構築をする際、環境間の設定差異などを考慮する必要があり、単一環境と比べて管理方法などが複雑になってくることがあります。

今回、紹介するTerraform Workspaceを利用する事でどの様にして環境間の分離を実現し、リモートステートを連携させるかについて紹介します。

なお、Terraformで環境分離する手法として、今回紹介する、ワークスペースによる分離ファイルレイアウトによる分離 など複数存在しますが、今回はワークスペースを利用した方法にフォーカスして紹介します。

Terraform Workspaceとは

Terraform Workspaceを使うと、Terraformの状態を管理するステートファイルを複数作成でき、ワークスペースごとに名前を付けて同じコードベースで複数の環境を管理できます。

動作確認内容

Terraform Workspaceは、同一フォルダ内で複数のワークスペースを作成し管理する機能になります。

環境間のリソース参照を実現するため、最初に参照元となるprodワークスペースを作成します。

次に参照先のstgワークスペースを作成し、stgワークスペースからprodワークスペースのリモートステートを参照する動作確認を行います。

流れ

環境準備

事前作業として、AWS CLIコマンドを使用し、Terraformのステートファイルを管理するS3バケットを作成します。

S3バケットの作成

export BUCKET=terraform-workspace-demo01
export REGION=ap-northeast-1

  • バケット作成
aws s3api create-bucket \
  --bucket "$BUCKET" \
  --region "$REGION" \
  --create-bucket-configuration LocationConstraint="$REGION"
  • バージョニング有効化
aws s3api put-bucket-versioning \
  --bucket "$BUCKET" \
  --versioning-configuration Status=Enabled

検証用Terraformファイルの作成

以下の内容でmain.tfファイルを作成します。

terraform {
  required_version = "1.11.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.89.0"
    }
  }
}

provider "aws" {
  region = "ap-northeast-1"
}

locals {
  env = terraform.workspace
}

# ここがVPC作成定義(各workspaceで独立したVPCが作成されます)
resource "aws_vpc" "main" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_hostnames = true
  enable_dns_support   = true
  tags = {
    Name        = "${local.env}-vpc"
    Environment = local.env
    ManagedBy   = "Terraform"
  }
}

# このworkspaceで作成したVPCのID
output "vpc_id" {
  description = "各workspaceで作成したVPCのID"
  value       = aws_vpc.main.id
}

# 環境間参照デモ: prodのstateを、prod以外のworkspaceから参照
data "terraform_remote_state" "prod" {
  count     = terraform.workspace == "prod" ? 0 : 1
  backend   = "s3"
  workspace = "prod"
  config = {
    bucket               = "terraform-workspace-demo01" # backend.tfと同じ
    region               = "ap-northeast-1"
    encrypt              = true
    workspace_key_prefix = "env"
    key                  = "stack/terraform.tfstate"
  }
}

# prodのVPC IDを表示(prod自身ではnull)
output "prod_vpc_id" {
  description = "prod workspace の VPC ID(prod以外で表示)"
  value       = try(data.terraform_remote_state.prod[0].outputs.vpc_id, null)
}

次に、以下の内容でbackend.tfファイルを作成します。

terraform {
  backend "s3" {
    bucket               = "terraform-workspace-demo01" # 一意のS3バケット名に置換
    region               = "ap-northeast-1"
    encrypt              = true
    use_lockfile         = true  # DynamoDB不要のS3ネイティブロック
    workspace_key_prefix = "env" # S3上: env/<workspace>/stack/terraform.tfstate
    key                  = "stack/terraform.tfstate"
  }
}

プロジェクト初期化

Terraformのプロジェクトを初期化します。

正常に成功すると、S3バックエンドが設定され、Terraformの初期化が完了します。

terraform init

Initializing the backend...

Successfully configured the backend "s3"! Terraform will automatically
use this backend unless the backend configuration changes.

...{中略}

Terraform has been successfully initialized!

...{中略}

prodワークスペースの作成と適用

terraform workspace new {環境名}コマンドを使用して、任意のワークスペース名を作成できます。

terraform workspace new prod

Created and switched to workspace "prod"!

You're now on a new, empty workspace. Workspaces isolate their state,
so if you run "terraform plan" Terraform will not see any existing state
for this configuration.

terraform workspace listコマンドで、現在のワークスペースを確認します。

今回の場合、defaultワークスペースとprodワークスペースが存在することが確認できます。

defaultワークスペースはTerraform初期化時に自動的に作成されるワークスペースかつ削除できないため、こちらのワークスペースは利用せずにprodワークスペースを利用します。

terraform workspace list

  default
* prod

terraform plan 実行後、terraform apply を実行し、prodワークスペースのVPCを作成します。

...{中略}

aws_vpc.main: Creating...
aws_vpc.main: Still creating... [10s elapsed]
aws_vpc.main: Creation complete after 12s [id=vpc-01f858cac1ff4826c]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Outputs:

vpc_id = "vpc-01f858cac1ff4826c"

適用後、以下AWS CLIコマンドでterraform applyで作成されたVPCを確認します。

Nameタグがprod-vpcであることが確認できます。

aws ec2 describe-vpcs --vpc-ids vpc-01f858cac1ff4826c --query 'Vpcs[].{VpcId:VpcId, State:State, CidrBlock:CidrBlock, IsDefault:IsDefault, Name: Tags[?Key==`Name`].Value | [0]}' --output table

CidrBlockIsDefaultNameStateVpcId
10.0.0.0/16Falseprod-vpcavailablevpc-01f858cac1ff4826c

stgワークスペースの作成と適用

同様に、terraform workspace new {環境名}コマンドを使用して、stgワークスペースを作成します。

terraform workspace new stg

Created and switched to workspace "stg"!

You're now on a new, empty workspace. Workspaces isolate their state,
so if you run "terraform plan" Terraform will not see any existing state
for this configuration.

terraform workspace listコマンドで、現在のワークスペースを確認します。

stgワークスペースが作成されていることが確認でき、stgワークスペースに切り替わっていることが確認できます。

terraform workspace list

  default
  prod
* stg

terraform plan 実行後、terraform apply を実行し、stgワークスペースのVPCを作成します。

...{中略}

aws_vpc.main: Creating...
aws_vpc.main: Still creating... [10s elapsed]
aws_vpc.main: Creation complete after 11s [id=vpc-04184270516210ce1]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Outputs:

prod_vpc_id = "vpc-01f858cac1ff4826c"
vpc_id = "vpc-04184270516210ce1"

情報

  • stgワークスペースではterraform_remote_stateデータソースを利用して、prodワークスペースのVPC IDを参照しています。
  • prod_vpc_id出力値にprodワークスペースで作成されたVPC IDが表示されていることが確認できます。

適用後、以下AWS CLIコマンドでterraform applyで作成されたVPCを確認します。

Nameタグがstg-vpcであることが確認できます。

aws ec2 describe-vpcs --vpc-ids vpc-04184270516210ce1 --query 'Vpcs[].{VpcId:VpcId, State:State, CidrBlock:CidrBlock, IsDefault:IsDefault, Name: Tags[?Key==`Name`].Value | [0]}' --output table

CidrBlockIsDefaultNameStateVpcId
10.0.0.0/16Falsestg-vpcavailablevpc-04184270516210ce1

S3バケット内の状態確認

S3バケット内に、ワークスペースごとにステートファイルが保存されていることが確認できます。

aws s3api list-objects --bucket terraform-workspace-demo01 --query 'Contents[].{Key: Key, Size: Size, LastModified: LastModified}' --output table

KeyLastModifiedSize
env/prod/stack/terraform.tfstate2025-11-09T08:34:05+00:001981
env/stg/stack/terraform.tfstate2025-11-09T08:58:20+00:003386

まとめ

Terraform Workspaceを利用する事で、同一コードベースで複数環境の分離を実現できることが確認できました。

ディレクトリを分けることなく、環境ごとにワークスペースを切り替えるだけで、環境分離が可能になるため、管理が容易になる点がメリットです。

反面、同一リソースを作成しない場合は、ワークスペースごとに条件分岐をコードに追加する必要があるため、コードが複雑になる点がデメリットとなります。