TrademarkTrademark
Features
Documentation

Understanding Terraform & OpenTofu Workspaces

Learn about Terraform and OpenTofu workspaces
Ryan FeeJuly 21, 2024
Understanding Terraform & OpenTofu Workspaces
Key takeaways
  • Terraform workspaces let you run many instances of the same Terraform code, each with its own isolated state file, to manage environments like dev, staging, and production.
  • Workspaces are managed with CLI commands such as terraform workspace new, list, and select, and the terraform.workspace variable can adjust configuration based on the active workspace.
  • Local workspaces store state files on the local filesystem, while remote backends like Scalr, S3, or HCP Terraform handle workspace state separation automatically.
  • In Scalr and HCP Terraform, workspaces are richer entities encompassing state, variables, run history, and access controls, making them better suited to team and complex environments.

Most Terraform projects eventually need more than one environment. You have development, staging, and production, and you'd rather not copy the same configuration into three separate directories to keep their state apart. Workspaces are Terraform's built-in answer: one set of code, a separate state file per workspace. This post covers what workspaces are, how to use them, and how the picture changes once you run them through a remote backend like Scalr or Terraform Cloud.

What are Terraform Workspaces

Terraform workspaces let you create many instances of your infrastructure from the same Terraform code. Each workspace keeps its own state file, so you can manage different environments without duplicating the configuration. That comes in handy when you need several copies of the same setup, whether for different stages of development or for separate clients.

The Basics of Workspaces

By default, Terraform operates in a workspace called "default." You're working within this default workspace when you run Terraform commands without specifying a workspace. However, you can create additional workspaces to manage different states of your infrastructure.

To create a new workspace, you can use the following command:

terraform workspace new <workspace_name>

This command creates a new workspace with the specified name and switches to it. You can list all available workspaces using:

terraform workspace list

To switch between workspaces, use:

terraform workspace select <workspace_name>

Benefits of Using Terraform Workspaces

  1. Simplified Code Management: Workspaces allow using the same Terraform code across different environments. This reduces code duplication and makes maintaining consistency across your infrastructure easier.
  2. Isolated State Files: Each workspace maintains its own state file, ensuring that changes in one environment don't affect others. This isolation helps prevent accidental modifications to production environments during development or testing.
  3. Easy Environment Switching: With a simple command, you can switch between different environments, making it convenient to work on multiple configurations without changing your working directory or code.
  4. Improved Collaboration: Team members can work on different environments simultaneously without interfering with each other's work, as each workspace has its own state.

Working with Terraform State in Workspaces

When you create a new workspace and execute a Terraform apply, Terraform generates a new state file specific to that workspace. The state file is crucial as it keeps track of the current state of your infrastructure and helps Terraform determine what changes need to be made to reach the desired state defined in your configuration.

In a local setup, Terraform stores these state files in a directory named terraform.tfstate.d within your working directory. Each workspace gets its own subdirectory named after the workspace, containing the state file for that particular workspace.

For example, if you have workspaces named "dev" and "prod," your directory structure might look like this:

├── main.tf
├── variables.tf
├── outputs.tf
├── terraform.tfstate.d
│   ├── dev
│   │   └── terraform.tfstate
│   └── prod
│       └── terraform.tfstate
└── .terraform

Remote State Management with Workspaces

Local state works fine for an individual project or a small team. Once more people are involved, remote state storage tends to be the better fit. Terraform can store state in several remote backends, including Scalr, Amazon S3, Azure Blob Storage, and HashiCorp's Terraform Cloud.

When using a remote backend with workspaces, the backend typically handles the separation of state files for different workspaces. For example, if you're using an S3 backend, you might configure it like this:

In this setup, Terraform will automatically manage separate state files for each workspace within the specified S3 bucket. The actual path to the state file will include the workspace name, ensuring isolation between different environments.

Alternatively, in Scalr, you would configure it like this:

In this setup, a workspace is created in Scalr where the state is stored, run history is kept, and all items associated with that Terraform deployment are kept. In tools like Scalr and HCP Terraform, you aren't just storing the state remotely; you are doing all operations remotely so teams can have a central place to deploy Terraform.

Using Workspace Names in Your Terraform Code

Workspaces also let you read the active workspace name inside your Terraform code. With it, you can adjust the configuration depending on which workspace is selected.

Terraform provides a special variable terraform.workspace that contains the name of the current workspace. You can use this variable to set values or make decisions in your Terraform code.

For example, you might use it to set different resource names or tags:

In this example, the EC2 instance will be tagged with the name of the current workspace, making it easy to identify which environment it belongs to.

Workspace-Specific Variables

While the terraform.workspace variable is useful, you might want more fine-grained control over your configuration. You can achieve this by defining workspace-specific variables in your Terraform code.

For instance, you could create a map of variables for different environments:

In this setup, the instance type will be selected based on the current workspace, allowing you to easily manage different configurations for different environments.

Data Sources and Workspaces

Data sources in Terraform allow you to fetch information from existing resources or external services. When working with workspaces, you can use data sources to retrieve information specific to each environment.

For example, you might use a data source to fetch the appropriate VPC ID for each environment:

This approach allows you to maintain environment-specific resources outside of your Terraform code while still referencing them appropriately in each workspace.

Best Practices for Using Terraform Workspaces

  1. Use Consistent Naming Conventions: Adopt a clear and consistent naming convention for your workspaces. This makes it easier for team members to understand the purpose of each workspace.
  2. Limit the Number of Workspaces: While workspaces are powerful, having too many can become confusing. Consider using separate Terraform configurations for significantly different environments or projects.
  3. Use Remote State Storage: For team environments, always use remote state storage to ensure all team members are working with the most up-to-date state information.
  4. Implement State Locking: Use a backend, such as Scalr or HCP Terraform, that supports state locking to prevent concurrent changes to the same code.
  5. Document Workspace Usage: Clearly document how workspaces are used in your project, including any workspace-specific variables or configurations.
  6. Use Scalr or Terraform Cloud for Advanced Features: For larger teams or more complex setups, consider using Scalr or Terraform Cloud, which offer advanced workspace management features and collaboration tools.

Workspaces in Scalr or Terraform Cloud

The core concept of Terraform workspaces is similar between local usage and Scalr, but there are some important distinctions in how they're implemented and used:

Core Similarities:

  1. Purpose: In both cases, workspaces are used to manage multiple instances of your infrastructure using the same Terraform configuration.
  2. Isolation: Each workspace maintains its own state, allowing for separate environments or configurations.
  3. Naming: Workspaces are identified by unique names in both local and Scalr setups.

Key Differences:

  1. Implementation: Local: Workspaces are essentially different state files in a local directory. Scalr: Workspaces are more complete entities, encompassing state, variables, run history, and access controls.
  2. Management: Local: Managed via CLI commands (e.g. terraform workspace new, terraform workspace select). Scalr: Managed through the web UI, API, or Terraform CLI with a remote backend configuration.
  3. Scope: Local: Workspaces are specific to a local working directory. Scalr: Workspaces are environment-wide and can be accessed by team members with appropriate permissions.
  4. Feature Set: Local: Basic workspace functionality for state isolation. Scalr: Enhanced features like variable sets, run triggers, PR automation, and team access controls.
  5. State Storage: Local: State files are stored on the local filesystem. Scalr: State is stored remotely and managed by Scalr.

The underlying idea of isolating state and configuration is the same. Scalr just builds more around it, treating a workspace as a unit of management rather than a single state file. That extra functionality isn't present in local workspaces, which is why Scalr tends to fit team environments and larger infrastructures better.

Moving from local workspaces to Scalr means trading the bare CLI workflow for one built around collaboration.

Conclusion

Terraform workspaces give you a way to manage several environments from one set of code. They cut down on duplication, keep each environment's state separate, and make it easier for a team to work in parallel. On a small project the CLI workspaces are usually enough. As things grow, a remote backend like Scalr or Terraform Cloud takes over the state separation and adds the access controls and run history that a team needs.

Workspaces are one piece of a larger Terraform workflow, so weigh them against how your team actually works before committing to a pattern.

About the author
Ryan Feedirector of platform engineering at Scalr
Ryan Fee is the director of platform engineering at Scalr, with over 15 years of experience improving infrastructure experiences at companies large and small.