Terraform Workspaces 101

Allan Denot
DNX Labs
Published in
3 min readMay 4, 2019

--

The art of deploying the same stack multiple times without code duplication

Photo by Jason Wong on Unsplash

Let’s say you create a network foundation using our module:

You deploy it:

terraform init
terraform apply

All good. You get the resources deployed to your AWS account, in the us-east-1 region.

Now let’s say you need to deploy the exact same stack into another account?

You could duplicate the files and deploy again, but now you have 2 code bases to maintain. 🤔

That’s where workspaces comes to play.

Before deploying for the first time, let’s create a workspace:

We created a workspace called labs-us-east-1 to represent the account (labs) and region (us-east-1) we are deploying. Basic commands are:

# shows existing workspace and which one is selected (*):
terraform workspace list
# creates and selects a new workspace:
terraform workspace new <workspace name>
# select an existing workspace:
terraform workspace select <workspace name>

Next step, just deploy normally:

terraform init
terraform apply

The state file will be saved under a folder with the workspace name:

Note: If you use the S3 backend to store state files remotely in an S3 bucket, workspaces work the same way. It creates a prefix in your bucket, usually:

/env:/<workspace_name>/<key>

Now, next time you want to deploy this stack into another account or region, simply type:

terraform workspace new prod-us-east-1# switch credentials to production account, and:
terraform init
terraform apply

Choosing parameters per workspace

Our terraform code we have a variable vpc_cidr = “10.1.0.0/16” . What if we want to have a different value per workspace?

Let’s create a special type of variable called local and select the value based on the current workspace:

The local env is a dictionary where its keys match workspace names.

terraform.workspace is a built-in that returns the current workspace name. We use this to select from the dictionary at:

workspace = "${local.env[terraform.workspace]}"

So local.workspace["vpc_cidr"] will resolve to:

  • 10.1.0.0/16 when workspace is labs-us-east-1
  • 10.0.0.0/16 when workspace is prod-us-east-1

And same for the other parameters name and multi_nat in our example.

Conclusion

Hopefully, this article was helpful in some way.

Please leave your feedback below as well as anything you would like to see added.

We work at DNX Solutions and help to bring a better cloud and application experience for digital native startups in Australia.

Our current focus areas are: AWS, Well-Architected Solutions, Containers, ECS, Kubernetes, Continuous Integration/Continuous Delivery and Service Mesh.

We are constantly hiring cloud engineers for our Sydney office, focusing on cloud-native concepts.

Check our open source projects at https://github.com/DNXLabs and follow us on our Twitter or Linkedin

--

--

Allan Denot
DNX Labs

Cloud, container platforms and occasionally ML