Skip to main content

Command Palette

Search for a command to run...

Day 21: Workspaces for Environment Management

Updated
3 min read
Day 21: Workspaces for Environment Management
S

I'm a cloud-native enthusiast and tech blogger, sharing insights on Kubernetes, AWS, CI/CD, and Linux across my blog and Facebook page. Passionate about modern infrastructure and microservices, I aim to help others understand and leverage cloud-native technologies for scalable, efficient solutions.

Welcome to Week 4! This week focuses on advanced Terraform techniques. Today we’ll master workspaces - a powerful feature for managing multiple environments with the same configuration.

🎯 Today’s Goals

  • Understand Terraform workspaces

  • Create and manage workspaces

  • Use workspaces for environment isolation

  • Learn workspace best practices and limitations

🌍 What Are Workspaces?

Workspaces allow you to manage multiple instances of a single configuration. Each workspace has its own state file.

Same Configuration → Multiple Workspaces → Separate States

my-infrastructure/
├── main.tf (shared)
├── terraform.tfstate.d/
│   ├── dev/terraform.tfstate
│   ├── staging/terraform.tfstate
│   └── prod/terraform.tfstate

📚 Workspace Commands

# List workspaces
terraform workspace list
# Show current workspace
terraform workspace show
# Create new workspace
terraform workspace new dev
# Switch workspace
terraform workspace select dev
# Delete workspace (must be empty)
terraform workspace delete dev

🔧 Using Workspaces

Basic Usage

# main.tf
resource "aws_instance" "app" {
  ami           = "ami-12345"
  instance_type = terraform.workspace == "prod" ? "t3.large" : "t2.micro"

  tags = {
    Name        = "app-${terraform.workspace}"
    Environment = terraform.workspace
  }
}

Workspace-Specific Values

locals {
  env_config = {
    dev = {
      instance_type = "t2.micro"
      instance_count = 1
    }
    staging = {
      instance_type = "t2.small"
      instance_count = 2
    }
    prod = {
      instance_type = "t3.large"
      instance_count = 3
    }
  }

  config = local.env_config[terraform.workspace]
}

resource "aws_instance" "app" {
  count = local.config.instance_count

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

  tags = {
    Name = "${terraform.workspace}-app-${count.index}"
  }
}

🧪 Hands-On Lab

Step 1: Create Project

mkdir terraform-workspaces-lab
cd terraform-workspaces-lab

main.tf:

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = "us-east-1"
}

locals {
  environments = {
    dev = {
      instance_type = "t2.micro"
      instance_count = 1
      cidr = "10.0.0.0/16"
    }
    staging = {
      instance_type = "t2.small"
      instance_count = 2
      cidr = "10.1.0.0/16"
    }
    prod = {
      instance_type = "t3.medium"
      instance_count = 3
      cidr = "10.2.0.0/16"
    }
  }

  env = local.environments[terraform.workspace]
}

resource "aws_vpc" "main" {
  cidr_block = local.env.cidr

  tags = {
    Name        = "${terraform.workspace}-vpc"
    Environment = terraform.workspace
  }
}

resource "aws_subnet" "public" {
  vpc_id     = aws_vpc.main.id
  cidr_block = cidrsubnet(local.env.cidr, 8, 1)

  tags = {
    Name = "${terraform.workspace}-subnet"
  }
}

data "aws_ami" "amazon_linux" {
  most_recent = true
  owners      = ["amazon"]

  filter {
    name   = "name"
    values = ["amzn2-ami-hvm-*-x86_64-gp2"]
  }
}

resource "aws_instance" "app" {
  count = local.env.instance_count

  ami           = data.aws_ami.amazon_linux.id
  instance_type = local.env.instance_type
  subnet_id     = aws_subnet.public.id

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

output "workspace" {
  value = terraform.workspace
}

output "vpc_id" {
  value = aws_vpc.main.id
}

output "instance_ids" {
  value = aws_instance.app[*].id
}

Step 2: Use Workspaces

# Initialize
terraform init

# Create dev workspace
terraform workspace new dev
terraform plan
terraform apply -auto-approve

# Create staging workspace
terraform workspace new staging
terraform plan
terraform apply -auto-approve

# Switch to dev
terraform workspace select dev
terraform output

# List all workspaces
terraform workspace list

# View state files
ls -la terraform.tfstate.d/

# Clean up
terraform workspace select dev
terraform destroy -auto-approve

terraform workspace select staging
terraform destroy -auto-approve
terraform workspace select default

terraform workspace delete dev
terraform workspace delete staging

⚖️ Workspaces vs Directories

Workspaces

✅ Same code for all environments ✅ Easy to switch between environments ✅ Less code duplication ❌ All environments must be similar. ❌ Easy to accidentally apply to wrong environment

Separate Directories

✅ Complete isolation ✅ Different configurations per environment ✅ Safer (harder to make mistakes) ❌ More code duplication ❌ Harder to keep in sync

Recommendation

Use directories for production environments:

terraform/
├── dev/
├── staging/
└── prod/

Use workspaces for:

  • Feature branches

  • Temporary environments

  • Testing

  • Development

📝 Summary

Today you learned:

  • ✅ Terraform workspaces

  • ✅ Workspace commands

  • ✅ Environment-specific configurations

  • ✅ Workspaces vs directories

🚀 Tomorrow: Terraform Import & Moving Resources


← Day 20: Remote State | Day 23: Terraform Import →

More from this blog

S

StackOps - Diary

33 posts

Welcome to the StackOps - Diary. We’re dedicated to empowering the tech community. We delve into cloud-native and microservices technologies, sharing knowledge to build modern, scalable solutions.