Skip to main content

Terraform Workspaces

In Terraform, a workspace is a feature that allows you to manage multiple "state" environments within a Terraform configuration. Each workspace maintains its own state, allowing you to deploy and manage infrastructure configurations independently.

Workspaces are useful in several scenarios:

  • Environment Isolation: Workspaces enable you to have separate environments within a Terraform configuration. Each workspace can have its own set of resources and configurations.

  • Parallel Development: Workspaces facilitate parallel development by allowing different team members to work on different workspaces concurrently without interfering with each other's changes.

  • Testing and Experimentation: Workspaces are helpful for testing and experimentation. You can create temporary workspaces to test changes or new configurations without affecting the main production environment.

  • State Management: Workspaces manage separate states for each environment. This helps in maintaining clarity and avoiding conflicts when multiple environments are being managed.

  • Deployment Strategies: Workspaces can be used to implement different deployment strategies. For example, you might use separate workspaces for blue-green deployments or canary releases.

To work with workspaces in Terraform, you can use commands like terraform workspace new, terraform workspace select, and terraform workspace delete to create, switch between, and delete workspaces respectively. Atmos automatically manages Terraform workspaces for you when you provision components in a stack.

Terraform Workspaces in Atmos

Atmos automatically calculates Terraform workspace names and uses workspaces to manage top-level stacks. By default, Atmos uses the stack name as the Terraform workspace when provisioning components in the stack. For example, consider the following manifest for the component vpc in the stack ue2-dev:

stacks/ue2-dev.yaml

vars:
# Context variables that define the Atmos stack `ue2-dev`
environment: ue2
stage: dev

components:
terraform:
vpc:
metadata:
# Point to the Terraform component in `components/terraform/vpc`
component: vpc
# Define the variables specific to this component
vars:
name: my-vpc
ipv4_primary_cidr_block: 10.9.0.0/18

When you provision the vpc component in the stack ue2-dev by executing the following command:

atmos terraform apply vpc -s ue2-dev

Atmos computes the workspace name to be ue2-dev. Any Atmos Terraform command other than init, using this stack, will cause Atmos to select this workspace, creating it if needed. (This leaves the workspace selected as a side effect for subsequent Terraform commands run outside of Atmos. Atmos version 1.55 took away this side effect, but it was restored in version 1.69.)

The exception to the default rule (using the stack name as Terraform workspace) is when we provision more than one instance of the same Terraform component (with the same or different settings) into the same stack by defining multiple Atmos components. In this case, Atmos calculates the Terraform workspace for each component by joining the stack name with the component name.

For example, the following manifest shows how to define two Atmos components, vpc/1 and vpc/2, which both point to the same Terraform component vpc, in the stack ue2-dev:

stacks/ue2-dev.yaml

vars:
# Context variables that define the Atmos stack `ue2-dev`
environment: ue2
stage: dev

components:
terraform:
# Atmos component `vpc/1`
vpc/1:
metadata:
# Point to the Terraform component in `components/terraform/vpc`
component: vpc
# Inherit the defaults for all VPC components
inherits:
- vpc/defaults
# Define/override variables specific to this `vpc/1` component
vars:
name: vpc-1
ipv4_primary_cidr_block: 10.9.0.0/18

# Atmos component `vpc/2`
vpc/2:
metadata:
# Point to the Terraform component in `components/terraform/vpc`
component: vpc
# Inherit the defaults for all VPC components
inherits:
- vpc/defaults
# Define/override variables specific to this `vpc/2` component
vars:
name: vpc-2
ipv4_primary_cidr_block: 10.10.0.0/18

When you provision the components by executing the commands:

atmos terraform apply vpc/1 -s ue2-dev
atmos terraform apply vpc/2 -s ue2-dev

Atmos computes the workspace names as ue2-dev-vpc-1 and ue2-dev-vpc-2 respectively, and selects the appropriate workspace for each component (again, creating it if needed). This is done because the same Terraform component vpc is used as the workspace prefix (in case of AWS S3 backend, folder in the S3 state bucket), and it's necessary to have different subfolders (ue2-dev-vpc-1 and ue2-dev-vpc-2 instead of just ue2-dev) to store the Terraform state files.

Terraform Workspace Override in Atmos

You can override Terraform workspaces for Atmos components by using metadata.terraform_workspace and metadata.terraform_workspace_pattern attributes. For example:

stacks/ue2-dev.yaml

vars:
environment: ue2
stage: dev

components:
terraform:
vpc/1:
metadata:
component: vpc
# Override Terraform workspace
terraform_workspace: "vpc-1-workspace-override"

vpc/2:
metadata:
component: vpc
# Override Terraform workspace
terraform_workspace_pattern: "{environment}-{stage}-{component}-workspace-override"

When you provision the components by executing the commands:

atmos terraform apply vpc/1 -s ue2-dev
atmos terraform apply vpc/2 -s ue2-dev

Atmos sets the Terraform workspace vpc-1-workspace-override for the vpc/1 component, and ue2-dev-vpc-2-workspace-override for the vpc/2 component.

The following context tokens are supported by the metadata.terraform_workspace_pattern attribute:

  • {namespace}
  • {tenant}
  • {environment}
  • {region}
  • {stage}
  • {attributes}
  • {component}
  • {base-component}
tip

For more information on Atmos base and derived components, and to understand the {base-component} token, refer to Atmos Component Inheritance

References