In a software as a service (SaaS) environment there are generally multiple environments to test code or stage the next release versions. In a cloud hosted solution you will likely see multiple accounts used to segment production from various development and staging environments. Within AWS, the segmentation of environments is considered best practice because it avoids inadvertently interfering with production resources when testing.

Terraform offers a solution to deploy an application to multiple AWS accounts using workspaces. A workspace allows Terraform to use a single configuration to create multiple state files which in turn means deployments across multiple AWS accounts.

In this example I'll show you how to setup Terraform and deploy EC2 instances onto a development and production AWS accounts.


Prerequisites

  • AWS account 1 - Production
  • AWS account 2 - Development
  • AWS account 3 - Administration
  • IAM role within account 1 with rights to create new EC2 instances
  • IAM role within account 2 with rights to create new EC2 instances
  • Terraform v0.13.5

In my example I will be using a total of three AWS accounts. AWS account 3 will function as the administration account. It will be the account that will contain the remote backend S3 bucket for the Terraform state files.


Setting up the Workspace

Before I go and setup the workspaces, let me show you my Terraform configuration file to deploy the EC2 instance. Looks like a standard Terraform configuration file, but notice the terraform.workspace clause in "role_arn" and "Name"? This is key to how Terraform will be able to differentiate between the two accounts.

provider "aws" {
  region  = "us-east-1"
  version = "2.66"

  assume_role {
    role_arn = var.workspace_iam_roles[terraform.workspace]
  }
}

terraform {
  required_version = ">=0.12.0"

  backend "s3" {
    bucket = "REPLACE-WITH-YOUR-TF-STATES-BUCKET-NAME"
    key    = "multi-deploy-test-project/terraform.tfstate"
    region = "us-east-1"
  }
}

variable "workspace_iam_roles" {
  default = {
    prod = "arn:aws:iam::PROD-ACCOUNT-ID:role/terraform"
    dev  = "arn:aws:iam::DEV-ACCOUNT-ID:role/terraform"
  }
}

data "aws_ami" "amzn-linux-2" {
  most_recent = true
  owners      = ["amazon"]

  filter {
    name   = "name"
    values = ["amzn2-ami-hvm-2.0.2020*-x86_64-gp2"]
  }

  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }
}

resource "aws_instance" "ec2_multi" {
  ami           = data.aws_ami.amzn-linux-2.id
  instance_type = "t2.micro"

  tags = {
    Name = "multi-deploy-${terraform.workspace}"
  }
}

In my example Terraform configuration file above, you will be deploying an EC2 instance in the US-EAST-1 region. If you have not done so already please create an S3 bucket that will serve as the remote backend for the Terraform state files.

I will be deploying a t2.micro instance running with the latest version of Amazon Linux 2.

Initialize Terraform to create the base state files.

terraform init

Once the initialization is complete you should be in the default Terraform workspace. To confirm the workspace you can issue the following command. The only workspace available should be "default".

terraform workspace list

Create the workspace for dev.

terraform workspace new dev

Create the workspace for prod.

terraform workspace new prod

You should now have three workspaces when you issue the workspace list command again.

$ terraform workspace list
* default
  dev
  prod

You can also confirm that the remote backend (S3 bucket) has a folder for both dev and prod workspaces.

remotebackend


Deploying the EC2 Instance

Now depending on the workspace, Terraform will deploy using the role specified and as a result will create resources in the corresponding AWS account. We'll go ahead and deploy dev first.

Switch into the dev workspace.

terraform select dev

Create the Terraform plan.

terraform plan -out apply.tfplan

If the plan is created without any error, go ahead and apply the plan.

terraform apply apply.tfplan

Confirm the EC2 instance was created in the dev AWS account by logging into the EC2 console.

dev-ec2

Time to deploy prod's EC2 instance. Switch to the prod workspace.

terraform select prod

Create the Terraform plan.

terraform plan -out apply.tfplan

Once again if no errors occured during the creation of the plan, you may apply the plan.

terraform apply apply.tfplan

As you can see with the magic of workspaces and clever IAM roles, you are able to deploy resources to multiple AWS accounts using a single Terraform configuration.