Terraform Workspaces

Terraform Workspaces

Hello BitsLovers! This article will talk about Terraform Workspaces.

Our terraform workspace tutorial will cover how to use it and when to use it. Also, provide a guide on which commands we can use.

What is terraform workspace?

We learned what terraform state is in our previous article—also, that one state stores one environment, like Production, Dev, or Staging. So, we don’t mix different environments in a single file/state.

The Terraform Workspaces allow us to use the same file (i.e., S3/Consult) with several states within. It means that we can manage several environments with the same configuration (Workspace).

Terraform Workspaces
Terraform Workspaces

Even if you never used workspace explicitly, you already use the “default” workspace. For example, we use the default workspace for every new project, and the default workspace can’t delete this one.

We can switch between different workspaces and perform the terraform against those workspaces.

Terraform Workspaces Example

Let’s declare our remote state, and later we will create a new workspace.

terraform {
  required_version = "0.14.5"
  backend "s3" {
    bucket = "bucket-name"
    key    = "bitslovers/butcket/path/to/terraform.tfstate"
    region = "us-east-1"
  }
}

From here, still the same as what we already know about the state. We can create multiple Terraform Workspaces with that same state, as I mentioned before. 

Let’s now see which command we can use to manage our workspace.

Terraform Workspace Commands

 So, after configuring your terraform state on your main.tf file, let’s run some commands.

Terraform Workspace Init

First, we need to execute init as we do for any project to use the terraform workspace.

terraform init

 Now, let’s see which workspace we are in:

terraform workspace list

output:

* default

Terraform Workspace List

The “terraform workspace list,” as the command suggests, lists all workspaces that we have available. But also, which workspace we are working within is indicated with a start “*” at the beginning. 

Also, to check the current workspace we are working on, we can execute “terraform workspace show”.

terraform workspace show

Output

default

Creating a new Terraform Workspaces

We can create new terraform workspaces like the example below:

Command Usage:

terraform workspace new <workspace-name>
terraform workspace new dev

output:

Created and switched to workspace "dev"!

You're now on a new, empty workspace. Workspaces isolate their state,
so if you run "terraform plan" Terraform will not see any existing state
for this configuration

Switching Between Workspaces

We can use “terraform workspace select” to choose a different workspace that already exists. For example, we can switch from “production” workspace to “dev” workspace.

Usage:

terraform workspace select <workspace-name>

Example

terraform workspace select production

Terraform Workspace Create If Not Exists

Suppose you use Gitlab to deploy Terraform or any other approach to automate our deployment like Shell Script. Sometimes we want to create a terraform workspace if it does not exist yet. Let’s see how we can handle it.

export WORKSPACE_NAME=dev
terraform workspace select $WORKSPACE_NAME || terraform workspace new $WORKSPACE_NAME
terraform plan -input=false -out=myplan.bin

So, if the workspace select command fails in our example above, our “or” logic will automatically call our second command to create the workspace for us. Or if it exists, will select it for us.

Terraform Workspace Variables

Like any Terraform project, we have to specify a set of variables for each environment. In other words, we should have one “terraform.tfvars” for each environment, like Production, QA, and Dev.

Important

When switching between different workspaces, ensure that you have a separate file.tfvars for each workspace, if it’s your case. For example, to execute the planning phase for a specific file:

terraform plan -var-file="terraform.tfvars"

The best approach, in my opinion, is if you manage your project on Git. You can use a different branch for each workspace, and then each branch will contain a different terraform.tfvars file.

In my case, I use GitLab to deploy Terraform Projects. Then, I can easily switch between workspace according to the branch where I triggered the pipeline. See my example below:

deploy:
  image: bitslovers-${CI_COMMIT_REF_NAME}
  stage: deploy
  script:
    - terraform init
    - terraform workspace list
    - terraform workspace select ${CI_COMMIT_REF_NAME} || terraform workspace new ${CI_COMMIT_REF_NAME}
  artifacts:
    paths:
    - myplan.bin
    expire_in: 2 week

The Gitlab CI automatically provides the current branch from the pipeline through the variable CI_COMMIT_REF_NAME. So, we have one workspace with the same branch name. And when we execute the pipeline, we automatically select the workspace we need and don’t need to worry about the terraform.tfvars file that belongs to that branch and contains the correct values for that workspace.

If you use Terraform Could, the paid service on the cloud for Terraform, they provide an excellent feature for that. Check here.

Terraform Workspace Best Practices

When we start to work with Terraform, we need to guarantee that all resources contain a unique name to avoid duplication. And to achieve that, we can use interpolation to define the names of the resources.

For example, the terraform automatically provides the variable terraform.workspace that will give us the current workspace name on the ” plan ” phase. So, we can use interpolation within our configuration. Let’s one example:

resource "aws_security_group" "default" {
  vpc_id = var.vpc_id
  name   = "webserver-${terraform.workspace}"
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
  tags = module.tags.tags
}

If you want to learn more about VPC, check out the full documentation.

In the example above, we create a Security Group with a different name for each workspace name. In that way, we guarantee that we have a new Security Group for different environments. 

Use a Terraform State (backend) only for production.

Our second tip: Consistently execute “terraform workspace show” to check the current workspace. This can avoid critical mistakes in executing Terraform changes on the wrong workspace. For that reason, it’s recommended to have the production environment isolated from other environments. So, we can avoid the risk of executing “terraform destroy” in production, for example.

Conclusion

More significant configurations can use some advanced features Terraform delivers to support decrease complexness and make maintenance more manageable. For example, workspaces permit you to test new extras to your code without handling stable significant deployments. We can also pair workspaces with version control like GitLab and track the code modifications. Utilizing and reusing small modules can also trim coding time but may incur extra costs or time in the future if the module becomes outdated.

Workspaces permit us to make numerous, predictable infrastructures utilizing any Terraform project. Because the state is controlled independently, things stay effortless. Usually, also we can use the ${terraform.workspace} to supply unique values for each environment.

Boost your Terraform skills:

How to use Terraform Modules

How to create complex expressions using Terraform Template.

What is the difference between Locals and Terraform Variables?

How to use the Terraform Data on your modules.

What are the advantages of Terraform Output?

Learn how to create multiple copies from the same resource on Terraform.

How to create a Pipeline on Gitlab to execute a Terraform code?

Leave a Comment

Your email address will not be published. Required fields are marked *

Free PDF with a useful Mind Map that illustrates everything you should know about AWS VPC in a single view.