DEV Community

Diogo Souza da Silva
Diogo Souza da Silva

Posted on • Originally published at Medium on

Terraform workspaces and locals for environment separation

Terraform is this amazing tool to provision and manage changes on your cloud infrastructure while following the great practice of keeping your infrastructure-as-code.

One common need on infrastructure management is to build multiple environments, such as testing and production, with mostly the same setup but keeping a few variables different, like networking and sizing.

The first tool help us with that is terraform workspaces. Previously called environments, it allows you to create different and independent states on the same configuration. And as it’s compatible with remote backend this workspaces are shared with your team.

As an example, let’s work with the following simple infrastructure:

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

resource "aws\_instance" "my\_service" {
 ami="ami-7b4d7900"
 instance\_type="t2.micro"
}

Now we have defined a single aws ec2 instance andterraform apply will have your testing server up.

But that is only one environment, in this simple example one might think that it would be ok to simple replicate and call one service “testing_my_service” and the other “prod_my_server”, but this approach will quickly lead to confusion as your setup grows in complexity and more resources are added.

What you can do instead is use workspaces to separate them.

terraform workspace new production

With this, you are now in production workspace. This one will have the same configuration, since we are in the same folder and module of terraform, but nothing created. Thus, if you terraform apply it will create another server with the same configuration but not changing the previous workspace.

To go back to testing you can terraform workspace select default , since we are using default as the testing environment to make sure we are not working on production by mistake.

But, obviously, there are differences between testing and production, and the first approach would be to use variables and an if switch on the resources. Instead a better approach would be to use the recently introduced terraform locals to keep resources lean of logic:

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

locals {
 env="${terraform.workspace}"

counts = {
 "default"=1
 "production"=3
 }

instances = {
 "default"="t2.micro"
 "production"="t4.large"
 }

instance\_type="${lookup(local.instances,local.env)}"
 count="${lookup(local.counts,local.env)}"
}

resource "aws\_instance" "my\_service" {
 ami="[ami-7b4d7900](https://console.aws.amazon.com/ec2/home?region=us-east-1#launchAmi=ami-7b4d7900)"
 instance\_type="${local.instance\_type}"
 count="${local.count}"
}

The main difference from variables is that locals can have logic in them instead of in the resources, while variables allow only values and pushed the logic into the resources.

One thing to keep in mind is that terraform is rapidly evolving and is worth to keep an eye on it’s changes to make sure you making the most of it.

Top comments (0)