10

I'd like to setup Terraform to manage dev/stage/prod environments. The infrastructure is the same in all environments, but there are differences in the variables in every environment.

What does an ideal Terraform project structure look like now that workspaces have been introduced in Terraform 0.10? How do I reference the workspace when naming/tagging infrastructure?

ydaetskcoR
  • 53,225
  • 8
  • 158
  • 177
mark
  • 1,953
  • 1
  • 24
  • 47
  • 1
    `Terraform configurations * environments = workspaces`: https://www.terraform.io/docs/enterprise/guides/recommended-practices/part1.html#one-workspace-per-environment-per-terraform-configuration – ecoe May 30 '18 at 17:22

2 Answers2

10

I wouldn't recommend using workspaces (previously 'environments') for static environments because they add a fair bit of complexity and are harder to keep track of.

You could get away with using a single folder structure for all environments, use workspaces to separate the environments and then use conditional values based on the workspace to set the differences. In practice (and especially with more than 2 environments leading to nested ternary statements) you'll probably find this difficult to manage.

Instead I'd still advocate for separate folders for every static environment and using symlinks to keep all your .tf files the same across all environments and a terraform.tfvars file to provide any differences at each environment.

I would recommend workspaces for dynamic environments such as short lived review/lab environments as this allows for a lot of flexibility. I'm currently using them to create review environments in Gitlab CI so every branch can have an optionally deployed review environment that can be used for manual integration or exploratory testing.

ydaetskcoR
  • 53,225
  • 8
  • 158
  • 177
3

In the old world you might have passed in the var 'environment' when running terraform, which you would interpolate in your .tf files as "${var.environment}".

When using workspaces, there is no need to pass in an environment variable, you just make sure you are in the correct workspace and then interpolate inside your .tf files with "${terraform.workspace}"

As for how you'd manage all of the variables, i'd recommend using a varmap, like so:

variable "vpc_cidr" {
  type = "map"

  default = {
    dev = "172.0.0.0/24"
    preprod = "172.0.0.0/24"
    prod = "172.0.0.0/24"
  }
}

This would then be referenced in a aws_vpc resource using a lookup

"${lookup(var.vpc_cidr, terraform.workspace)}"

The process of creating and selecting workspaces is pretty easy:

terraform workspace
Usage: terraform workspace

  Create, change and delete Terraform workspaces.


Subcommands:

    show      Show the current workspace name.
    list      List workspaces.
    select    Select a workspace.
    new       Create a new workspace.
    delete    Delete an existing workspace.

so to create a new workspace for pre production you'd do the following: terraform workspace new preprod

and if you ran a plan, you'd see that there should be no resources. What this will do in the backend is create a new folder to manage the state for 'preprod'.

Matt Childs
  • 149
  • 1
  • 1
  • 7
  • 1
    On a previous project, we used folders to differentiate between environments. So there was a folder called modules with all the modules and then in the providers-folder, we made separate folders per environment (DEV, TEST, PREPRD, ...). Does workspaces mean that this is not necessary anymore? Because the explanation on the TF website is a bit ambiguous in my opinion. – Bjorn121 Sep 13 '17 at 13:40
  • 1
    @Bjorn121 This is what I'm trying to find out, the documentation on their website seems to say this is still recommended from what I understand. Their best practices repo is also outdated. Have you found it out yet? – Shawn Mclean Sep 26 '17 at 07:35