Managing environments through Terraform Workspaces

Terraform Workspaces

Terraform Workspaces provide the ability to have separate state files for environments. Separating the state files provides isolation between multiple environments. While working in one workspace, changes are committed to the state file of a single environment. Therefore, they do not affect resources in another workspace. When managing separate environments and large deployments, this separation is critical for peace of mind.

What is a Terraform Workspace?

We can think of workspaces as a layer of isolation for Terraform state files. Every workspace has its state file. All modifications applied in a particular workspace will never affect resources managed by another. Workspaces are the key to managing multiple independent environments using a single Terraform project.

We can use the current workflow’s name in our configuration files by using the terraform.workspace variable when using workspaces in Terraform.

A fairly common use case is to create scoped names for resources. For example, consider using Terraform to provision an Azure Resource Group. Azure enforces a unique name constraint on Resource Groups in the context of your Azure subscription. (We can have only one Resource Group with the name cool-product). By adding the name of the current workspace (e.g. dev, test, or prod), we enforce the unique name constraint.

Terraform Workspaces in Practice

Creating Workspaces for environments

Every Terraform project comes with a workspace out of the box. When we execute the terraform init, Terraform implicitly creates a new workspace. The name of this workspace is always default. However, we can quickly create a custom workspace using the terraform workspace new command:

# create three new workspace
terraform workspace new dev
terraform workspace new test
terraform workspace new prod

Create a workspace from an existing state file

You can bring in workspaces also for existing Terraform projects. For example, if we already have a state file, use the state option to copy the existing state into the new workspace.

# create a new workspace and pass existing state file
terraform workspace new -state=terraform.tfstate dev

Display the current workspace

To know which workspace we are currently interacting with, execute terraform workspace show. Terraform will quickly print the name of the current workspace.

# get the name of the current workspace
terraform workspace show

List all available workspaces

We can list the available workspaces using the list sub-command:

# list all workspaces
terraform workspace list


How to switch workspace

Switching to a different namespace is super easy in Terraform. Just execute the terraform workspace select command, followed by the name of the desired workspace.

# switch to the dev workspace
terraform workspace select dev

terraform workspace show

Remove a workspace

Sometimes, we want to remove a specific workspace. The sub-command delete is responsible for that. But, first, delete the staging environment and check the list of remaining workspaces. There is only one exception; we can not delete the default namespace.

# delete the staging workspace
terraform workspace delete test

terraform workspace list


Creating the Infrastructure

Finally, let’s get hands-on and create the infrastructure from our written code. Initially, we need to initialize the project using the init subcommand, like so:

terraform init

The init command will install the required dependencies for our project like the cloud provider, plugins, etc.

Next up, we need to switch to the correct environment. For example, let’s change the dev environment for illustration:

terraform workspace select dev

Next, let’s run a plan of our infrastructure to see what resources will be created once we apply the code, there however is an extra variable we need to pass in called the -var-file. This argument takes the tfvars file based on the environment we selected:

terraform plan -var-file environments/dev/dev.tfvars

Finally, let’s apply the infrastructure using the apply sub-command:

terraform apply -var-file environments/dev/dev.tfvars

Faizan Bashir

Principal Engineer | Architecting and building distributed applications in the Cloud | Adventurer

Read More