Terraform CLI workspaces

In this post, we will focus on Terraform workspaces. Workspaces in terraform are the most confusing terminology when you work with Terraform CLI and Terraform cloud. To simplify,

  • Terraform workspaces in CLI refer to maintaining multiple state files for the same configuration directory
  • Workspaces in “Terraform cloud” refers to the infrastructure collection of everything that terraforms needs

Our prime focus is on the first one rather than the other. Let us put forth a scenario to conclude why we need workspaces.

Consider you are using terraform CLI to deploy resources with the configurations defined in a working directory. There is a need to deploy similar resources with different inputs across multiple projects. For example, in AWS we need to create 2 VPCs, one for “Team A” and the other for “Team B”.

Ideally, we need to start creating 2 configuration files for both teams A & B as shown below.

In case of multiple such instances, this will become complicated to copy and paste the same configuration files across multiple projects or environments. At the same time, distinct state files have to be maintained for each project.

Scenario: We need a solution to meet the below:

  • Single configuration directory to deploy repeatable infra and eliminate repeatable steps – updating configuration from version control for each directory separately and reinitializing each directory when you change the configuration
  • Avoid creating multiple working directories to maintain multiple instances of a configuration and save bandwidth and disk space.
  • Maintain completely separate state data for each deployment.

Solution: The answer to solve this problem is creating and using “Workspaces”.

Workspaces help to create a parallel, distinct copy of a set of infrastructure to test a set of changes before modifying production infrastructure.

To solve this, let’s consider the previous VPC example of Team A and Team B. We will create common variable files to address this.

F:\Terraform\Zero phase\vpc_ws1>terraform init

Initializing the backend...

Initializing provider plugins...
- Finding latest version of hashicorp/aws...
- Installing hashicorp/aws v4.53.0...
- Installed hashicorp/aws v4.53.0 (signed by HashiCorp)

Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.

Terraform has been successfully initialized!
F:\Terraform\Zero phase\vpc_ws1>terraform workspace list
* default

By default, all the configurations are executed under the “default” workspace. Now, let’s create 2 workspaces one for Team A and the other for Team B.

F:\Terraform\Zero phase\vpc_ws1>terraform workspace new teamA
Created and switched to workspace "teamA"!

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.

F:\Terraform\Zero phase\vpc_ws1>terraform workspace new teamB
Created and switched to workspace "teamB"!

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.

The VPC resource configuration file needs an input variable of “CIDR Block” to create the VPC. It’s time to play with the variable file. The inputs can be passed to the respective teams based on the “map” type variable as shown below. In this way, you can define input variables for any project or team or environment.

To consume the variable, we have to use the “lookup” function under the “resource block” defined for VPC. Whichever workspace you are in, will be observed by “terraform.workspace” command and that will help to look into the map function defined under ‘variables.tf’ file.

Note: To check the current workspace, run the below command under terraform console; To switch to the required workspace use the “terraform workspace select” command.

F:\Terraform\Zero phase\vpc_ws1>terraform console
> terraform.workspace
"teamB"
F:\Terraform\Zero phase\vpc_ws1>terraform workspace select teamA
Switched to workspace "teamA".

Let us try to apply the configuration for teamA and see the output. If we run terraform plan, you can see below screen, it has considered 10.0.0.0/16 as CIDR based on the above declared variable file.

F:\Terraform\Zero phase\vpc_ws1>terraform workspace select teamA

F:\Terraform\Zero phase\vpc_ws1>terraform plan

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with
the following symbols:
  + create

Terraform will perform the following actions:

  # aws_vpc.team-vpc will be created
  + resource "aws_vpc" "team-vpc" {
      + arn                                  = (known after apply)
      + cidr_block                           = "10.0.0.0/16"
      + default_network_acl_id               = (known after apply)
      + default_route_table_id               = (known after apply)
      + default_security_group_id            = (known after apply)
      + dhcp_options_id                      = (known after apply)
      + enable_classiclink                   = (known after apply)
      + enable_classiclink_dns_support       = (known after apply)
      + enable_dns_hostnames                 = (known after apply)
      + enable_dns_support                   = true
      + enable_network_address_usage_metrics = (known after apply)
      + id                                   = (known after apply)
      + instance_tenancy                     = "default"
      + ipv6_association_id                  = (known after apply)
      + ipv6_cidr_block                      = (known after apply)
      + ipv6_cidr_block_network_border_group = (known after apply)
      + main_route_table_id                  = (known after apply)
      + owner_id                             = (known after apply)
      + tags_all                             = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

───────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions
if you run "terraform apply" now.

If we try to apply the configuration, terraform displays the workspace name (highlighted in red below) where the resources will be deployed.

F:\Terraform\Zero phase\vpc_ws1>terraform apply

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with
the following symbols:
  + create

Terraform will perform the following actions:

  # aws_vpc.team-vpc will be created
  + resource "aws_vpc" "team-vpc" {
      + arn                                  = (known after apply)
      + cidr_block                           = "10.0.0.0/16"
      + default_network_acl_id               = (known after apply)
      + default_route_table_id               = (known after apply)
      + default_security_group_id            = (known after apply)
      + dhcp_options_id                      = (known after apply)
      + enable_classiclink                   = (known after apply)
      + enable_classiclink_dns_support       = (known after apply)
      + enable_dns_hostnames                 = (known after apply)
      + enable_dns_support                   = true
      + enable_network_address_usage_metrics = (known after apply)
      + id                                   = (known after apply)
      + instance_tenancy                     = "default"
      + ipv6_association_id                  = (known after apply)
      + ipv6_cidr_block                      = (known after apply)
      + ipv6_cidr_block_network_border_group = (known after apply)
      + main_route_table_id                  = (known after apply)
      + owner_id                             = (known after apply)
      + tags_all                             = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions in workspace "teamA"?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

aws_vpc.team-vpc: Creating...
aws_vpc.team-vpc: Creation complete after 5s [id=vpc-01ab68f2745abd4ee]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Let’s do similar steps for the other workspace teamB and see whether it has taken the other CIDR address defined in the variable file.

F:\Terraform\Zero phase\vpc_ws1>terraform workspace select teamB
Switched to workspace "teamB".

F:\Terraform\Zero phase\vpc_ws1>terraform apply

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with
the following symbols:
  + create

Terraform will perform the following actions:

  # aws_vpc.team-vpc will be created
  + resource "aws_vpc" "team-vpc" {
      + arn                                  = (known after apply)
      + cidr_block                           = "172.16.0.0/16"
      + default_network_acl_id               = (known after apply)
      + default_route_table_id               = (known after apply)
      + default_security_group_id            = (known after apply)
      + dhcp_options_id                      = (known after apply)
      + enable_classiclink                   = (known after apply)
      + enable_classiclink_dns_support       = (known after apply)
      + enable_dns_hostnames                 = (known after apply)
      + enable_dns_support                   = true
      + enable_network_address_usage_metrics = (known after apply)
      + id                                   = (known after apply)
      + instance_tenancy                     = "default"
      + ipv6_association_id                  = (known after apply)
      + ipv6_cidr_block                      = (known after apply)
      + ipv6_cidr_block_network_border_group = (known after apply)
      + main_route_table_id                  = (known after apply)
      + owner_id                             = (known after apply)
      + tags_all                             = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions in workspace "teamB"?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

aws_vpc.team-vpc: Creating...
aws_vpc.team-vpc: Creation complete after 5s [id=vpc-01b979760bc014d6a]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Let’s see what happens to the “state file” now:

We need two state files one for each workspace – teamA and teamB. You can observe in the below screenshot that there are two folders created and each has “terraform.tfstate” file.

Terraform Workspace

Terraform CLI workspaces help to streamline infrastructure deployment workflows, reduce risk, and enable efficient collaboration between teams.

  • Isolation of state: Workspaces allow you to isolate the state of your infrastructure deployments, enabling you to maintain multiple versions of your infrastructure in parallel.
  • Environment-specific configurations: Workspaces enable you to manage different configurations for different environments (e.g., development, staging, production) using the same codebase.
  • Parallel execution: Workspaces enable you to run multiple deployments in parallel, which can help to speed up the deployment process.
  • Collaboration: Workspaces can be used to enable collaboration between teams by allowing multiple users to work on different versions of the same infrastructure simultaneously.
  • Reduced risk: Workspaces reduce the risk of accidentally overwriting or deleting infrastructure resources by separating them into isolated workspaces.

Note: Below are the questions that may appear in the “HashiCorp Certified: Terraform Associate”. The questions are collected from various sources and the answers are best to my knowledge and might differ from the actuals.

What command should you run to display all workspaces for the current configuration?

  • A. terraform workspace
  • B. terraform workspace show
  • C. terraform workspace list
  • D. terraform show workspace

——————————————————————————————————————–

You would like to reuse the same Terraform configuration for your development and production environments with a different state file for each.

Which command would you use?

  • A. terraform import
  • B. terraform workspace
  • C. terraform state
  • D. terraform init

——————————————————————————————————————–

You have some Terraform code and a variable definitions file named dev.auto.tfvars that you tested successfully in the dev environment. You want to deploy the same code in the staging environment with a separate variable definition file and a separate state file. Which two actions should you perform? (Choose two.)

  • A. Copy the existing terraform.tfstate file and save it as staging.terraform.tfstate
  • B. Write a new staging.auto.tfvars variable definition file and run Terraform with the var-file=”staging.auto.tfvars” flag
  • C. Create a new Terraform workspace for staging
  • D. Create a new Terraform provider for staging
  • E. Add new Terraform code (*.tf files) for staging in the same directory

Explanation: B & C

The requirement is to meet the same code but a different variable file. You need to create a new workspace to accommodate this and pass a new variable file with the var-file option so that the staging environment will use the workspace created and the variable file passed.

error: Content is protected !!