Getty Images/iStockphoto

Manage multiple environments with Terraform workspaces

Terraform workspaces let DevOps teams manage configurations for different environments in a centralized way. Get started with workspaces through hands-on examples in this tutorial.

Terraform is a popular tool for provisioning infrastructure and managing its configuration. With Terraform's ability to capture application configurations in code, you can bring your infrastructure back to the exact same configuration at any time.

This is ideal for maintaining the desired state of your production environment, but what about other environments? For example, if you're testing your application in a staging or development environment before deploying it to production, you might want to mirror the production environment in those setups without changing your code.

Workspaces are a built-in Terraform feature that lets you reuse the same configuration for each environment you have. This makes workspaces an invaluable tool for DevOps teams working with multiple environments.

For example, if you deploy application infrastructure using a CI/CD pipeline, you can use workspaces to deploy a new set of resources to test on without using your production resources. Or if you need to troubleshoot an issue without affecting any other resources, you can deploy your code to a new workspace, then destroy the testing environment from the workspace.

How state works in Terraform

Because state is key to how workspaces function, it's helpful to understand what exactly state is in Terraform before diving into workspaces.

Terraform configurations are stored as one or more files in a single directory. You can use HashiCorp Configuration Language (HCL) to configure resources from one or more providers, such as AWS, Google Cloud or Microsoft Azure.

When you run the terraform plan or terraform apply commands, Terraform checks the resources configured in your HCL against what's contained in the Terraform state. If the resources defined in your Terraform state differ from your infrastructure, Terraform will ask if you want to apply the changes to the resources in your account, then save the new configuration to resources created with Terraform into the state.

Getting started with Terraform workspaces

To follow along with this tutorial, you'll need the following:

  • A Linux or macOS device with Terraform installed. The demos in this tutorial use Terraform version 1.4.5.
  • An AWS account with credentials configured. Although this demo uses AWS, workspaces aren't limited to a specific cloud provider; because they are a language construct, you can use them in any Terraform configuration across any provider.

To start, make a new directory called workspace and a new Terraform file called main.tf by running the Bash commands below. This file and directory will contain your configuration.

mkdir workspace
cd workspace
touch main.tf

Next, enter the configuration below in your main.tf file.

data "aws_ami" "ubuntu" {
  most_recent = true

  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
  }

  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }

  owners = ["099720109477"] # Canonical
}

resource "aws_instance" "web" {
  ami           = data.aws_ami.ubuntu.id
  instance_type = "t3.micro"

  tags = {
    Name = "HelloWorld"
  }
}

Although this sample is from the Terraform AWS provider documentation for creating an Amazon Elastic Compute Cloud (EC2) instance, you can also create other resources if preferred. Once your configuration file is saved, run the command terraform init from your configuration directory.

You might not even realize it, but you're already using a Terraform workspace! When you run the terraform init command, you are placed in a workspace called default -- well, by default. To confirm, check the workspace name by running the command below.

terraform workspace show

Now, running the terraform apply command deploys an EC2 instance with the Name tag HelloWorld using the default workspace, which is saved in that workspace's Terraform state file. The next time you run the terraform apply command, Terraform checks that state file and compares its resources with what's deployed in your AWS account.

Because HelloWorld isn't a good name for an instance running in production -- or any other environment, for that matter -- change the line with the Name tag in your configuration to match the code below.

Name = "${terraform.workspace}-instance"

Making this change enables Terraform to read the name of the workspace and reference it in your configuration. Run the terraform apply command to create an instance tagged with the name default-instance, as shown in Figure 1.

Screenshot from AWS platform showing that an EC2 instance named default instance is running.
Figure 1. After executing the terraform apply command, an EC2 instance called default-instance is successfully created and running.

Making a new Terraform workspace

If you run terraform plan or terraform apply, you'll get a message that says no changes are necessary and your configuration matches your infrastructure, meaning that it matches the infrastructure in the state file under the default workspace.

Create a new workspace for your staging environment by running the command below.

terraform workspace new staging

Once that's done, run terraform workspace show again. You should now see that a new workspace has been created, and you're no longer using the default workspace.

Terraform workspaces don't just create a new name for you to reference -- they also contain their own isolated state files. That means that each environment can use the same configuration files, but the state that tracks which resources are deployed is separate for each workspace.

If you run terraform plan or terraform apply again after creating the new staging workspace, the infrastructure no longer matches. Instead, a new instance is created with the name staging-instance. Although you always start with the default workspace, you can have as many as you want, and they are compatible with most Terraform back ends.

To see all the workspaces you've created, run the command terraform workspace list to get a full list of workspaces for your configuration directory. They are saved in your remote back end if you use one or in the Terraform data directory if you don't.

If you haven't already, apply the configuration for staging-instance. Then, return to the default workspace by running the command below.

terraform workspace select default

Now that you're back in the default workspace, as shown in Figure 2, you can make changes to the infrastructure in this workspace or even destroy it altogether without affecting the resources in the other workspace.

Screenshot of Bash script. The commands show the current workspace, switch to a different workspace, then show the current workspace again to confirm the change.
Figure 2. You can switch between workspaces using the terraform workspace select command.

Run terraform destroy after selecting the default workspace, and then check whether the staging instances are still present.

Changing parameters based on workspace

In a real-world scenario, you might want to make changes between production and staging environments. For example, you might need a larger instance in production to support all your traffic, but only a small one in staging that lets you test on something less expensive.

In Terraform, you can manage these environments with the same configuration files. Go back to your main.tf file and change the instance_type parameter to the value shown below.

instance_type = terraform.workspace == "production" ? "t3.large" : "t3.micro"

Now, select your staging workspace and rerun the terraform apply command. Because you're not in the production workspace, there should be no changes.

Run the command terraform workspace new production, then rerun the terraform apply command from the newly created production workspace. You should now have two different instances, as shown in Figure 3: a t3.micro instance with the staging tag, and a t3.large instance with the production tag.

Screenshot from AWS platform showing two running EC2 instances: a larger instance for production and a smaller instance for staging.
Figure 3. Using multiple workspaces lets you create different instances for different environments.

Using terraform.workspace as a key to create conditions in your configuration lets you make configuration changes across different environments using the same files. You can use this feature to look up differences between your environments -- for example, different virtual private clouds, instance classes or security group rules.

Finally, if you're done with the resources you created in this demo, run the command terraform destroy to remove them. Because each workspace has its own independent state file, you'll need to do this once for each workspace you've made.

Next Steps

Why to use staging environments for IT infrastructure testing

Dive into Terraform basics

Dig Deeper on Systems automation and orchestration