Terraform workspace to deploy multiple environment stack

David Cheong
7 min readNov 28, 2020

--

When working with infrastructure, we always have to deal multiple environment such as development, staging, production or UAT, as a system engineer or infrastructure engineer, we always want to make sure that all our deployed environment should work the same and can be repeatedly deploy without any code changing or complicated logic required.

Terraform is a great tools that help us to deal with the infrastructure as well as dealing with multiple environment by introduce the workspace command.

To use terraform workspace to deploy the same stack to different environment, you can either add in logic in your code to differentiate the environment that you are working on, then grab respective value for your resource configuration.

Another method is you can supply different variable file for difference environment.

By default, Terraform maintain a single workspace call the default workspace, all your state will be store to this workspace without you need to specify it. But if you want to work with multiple workspace, then you need to manually create the terraform workspace to manage it.

Terraform workspace can be managed by the terraform workspace set of command, to create a new workspace and switch to it, you can use terraform workspace new; to switch to the workspace you want to working with, you can use terraform workspace select.

In this demo, I will deploying 1 EC2 in t2.nano for my dev environment, and t3a.nano for my production environment. I will also demo on 2 ways how you can manage the configuration for both environment.

Using 1 variable file for all the workspace

In this example, I will do the following few step:

  1. Create the ec2.tf to write the ec2 resource script
  2. Create the vars.tf to declare all the variable
  3. Create the dev and prod workspace
  4. Deploy the resource by pass in the respective value
  5. Clear up all the resources (optional)

First, we create the ec2.tf to write your terraform script into, in this method, I will use the terraform lookup function to select the variable value base on terraform workspace name.

provider "aws" {
region = "ap-southeast-1"
}

resource "aws_instance" "myec2" {
ami = var.ami
instance_type = lookup(var.instance_type, terraform.workspace)
tags = {
Name = lookup(var.ec2_name, terraform.workspace)
}
}

Next, we need to create the variable file which I named it as vars.tf, in this file, I will create the instance_type variable as map type, then set the default value for difference workspace name

variable "ami" {
type = string
default = "ami-0c20b8b385217763f"
}

variable "instance_type" {
type = map
default = {
default = "t2.micro",
prod = "t3a.nano",
dev = "t2.nano"
}
}

variable "ec2_name" {
type = map
default = {
default = "",
prod = "prod_ec2_workspace_demo",
dev = "dev_ec2_workspace_demo"

}
}

We need to initialized the terraform project by using terraform init

Next we need to create the workspace for different environment, we can use terraform workspace new to create our first development workspace.

The workspace “dev” is now created, we can continue to create for prod workspace.

There are only few subcommands available for terraform workspace, which are new, list, show, select and delete.

You can list all the workspace using the terraform workspace list command, by default, terraform will create the default workspace.

Now using terraform workspace select dev to move to dev workspace

To deploy our resources, just enter the command

terraform apply --auto-approve

Login to AWS EC2 console, you should see the first ec2 already deployed successfully.

Now let’s switch over to the prod environment to deploy the production resource. To switch over to prod workspace, enter the following command

terraform workspace select prod

Now we already in the prod workspace, we can deploy the resources for prod environment using the apply command

terraform apply --auto-approve

Login to EC2 console you should see 2 instance is running now, 1 is dev_ec2_workspace_demo, another 1 is prod_ec2_workspace_demo.

Terraform actually store the state of difference workspace in difference directory under terraform.tfstate.d.

Now both of our dev and prod resources already deployed successfully, next we need to clean up everything including the workspace. To do so, you need to go to each workspace, use the terraform destroy to delete all the resources deployed, then delete the workspace using terraform workspace delete dev and terraform workspace delete prod

Using difference variable file for each environment

In this example, I will do the following few step:

  1. Create the ec2.tf to write the ec2 resource script
  2. Create the vars.tf to declare all the variable
  3. Create dev.tfvar to pass in the dev environment value
  4. Create prod.tfvar to pass in the prod environment value
  5. Create the dev and prod workspace
  6. Deploy the resource by pass in the respective value
  7. Clear up all the resources (optional)

Same as previous example, I will create the ec2.tf to write the script

provider "aws" {
region = "ap-southeast-1"
}

resource "aws_instance" "myec2" {
ami = var.ami
instance_type = var.instance_type
tags = {
Name = var.ec2_name
}
}

Creating 3 variable in the vars.tf file, all the variable will be type of string

variable "ami" {
type = string
default = "ami-0c20b8b385217763f"
}

variable "instance_type" {
type = string
default = "t2.micro"
}

variable "ec2_name" {
type = string
default = ""
}

prod.tfvar file

instance_type = "t3a.nano" 
ec2_name = "prod_ec2_workspace_demo"

dev.tfvar file

instance_type = "t2.nano" 
ec2_name = "dev_ec2_workspace_demo"

Create both of the prod and dev workspace using terraform workspace command

Once our workspace is ready, then we can select the prod workspace to deploy our resources to, to deploy the resource using the variable file, we need use the option -var-file.

terraform apply --auto-approve --var-file prod.tfvar

Login to EC2 console to confirm the instance deployed successfully.

Next, we need to switch over to the dev workspace and deploy the resource by supplying the var-file as well.

terraform workspace select devterraform apply --auto-approve --var-file dev.tfvar

Again, we log into the EC2 console to check again, both of our resource are successfully deployed to the AWS.

Now both of our dev and prod resources already deployed successfully, next we need to clean up everything including the workspace. To do so, you need to go to each workspace, use the terraform destroy to delete all the resources deployed, then delete the workspace using terraform workspace delete dev and terraform workspace delete prod

In this demo, I showing 2 way of on how you can manage the configuration variable, 1 is using the lookup function to grab the variable base on the terraform workspace, but this may involve more code changing in your terraform project, but the seconds method which using the variable files may involve less code change for your project.

Both way also working fine but you may just choose which method suit your use case the most.

For myself, I prefer the 2nd method where there is only minimum code change required, when I first design and write my code, I just write it as single environment, I no need to consider the logic on select which parameter to be use, when I want to deploy the resource to another environment, I just supplying the respective value then everything will be working exactly the same.

A small additional tips when dealing with the variable file, you can always supply the file using the -var-file filename.tfvars, but if you only deal with 1 single tfvars, by entering the same file name repeatedly seem not convenience, you can always renamed your file to terraform.tfvars or any file name end with the extension .auto.tfvars. By doing so, everytime when you try to run your terraform apply, you no need to explicitly define your variable file.

Originally published at https://tech.david-cheong.com on November 28, 2020.

--

--

No responses yet