Terraform different backend for each project

Viewed 802

I'm a bit of a newbie with Terraform and still working my way through the documentation, have not yet been able to find a way to accomodate the set up I need to achieve for a specific solution and hoping that some kind soul may be able to give me a push in the right direction.

I'm trying to manage a single set of paramaterised templates which deploy everything needed to support a new application we are working on in GCP. What I am trying to achieve is being able to deploy those templates to three different environments, each environment being in a distinct GCP project, by itself.

The plan is, as per recommendations, run terraform and pass in

a) The specific .tfvars file depending on the environment/project being deployed to (dev/test/prod).

b) Use the -chdir parameter to tell Terraform to pick up all the templates from 'infra-common' folder.

The tricky part is that we want each environment (gcp project) to host it's own state file in gcs/storage.

I had been looking at workspaces but it appears that workspaces will just create state subfolders on a single backend.

Question: Can this be done or is there a better way to do it?

Thanks!

2 Answers

You can use --backend-config for this. Here's how you can achieve the desired behavior:

  • Create a .config file for each environment (dev.config, test.config, prod.config) which contain the name of the gcs bucket (which must already exist) for the respective environment
  • Specify the common backend in a single remote_state.tf file

Here's how it would look:

config/dev.config:

bucket  = "tf-state-dev"

config/test.config:

bucket  = "tf-state-test"

config/prod.config:

bucket = "tf-state-prod"

remote_state.tf:

terraform {
  backend "gcs" {
    prefix  = "terraform/state"
  }
}

then, you can run the init. So for example, for dev this would look like:

$ terraform init --backend-config=config/dev.config

then, you can create a workspace for the environment:

$ terraform workspace new dev

With this approach, you can use a single set of templates (you can in fact configure dynamic variables based on the current workspace).

What you could do (we have a project with a similar setup with a different cloud provider), is:

  • use infra-common as a module
  • instead of working with .tfvar files per environment, use a separate root module per environment which invokes infra-common as sub-module.

Your folder structure could look like:

project
|-- dev
|   `-- main.tf
|-- modules
|   `-- infra-common
|       |-- main.tf
|       `-- variables.tf
|-- test
|   `-- main.tf
`-- prod
    `-- main.tf

dev/main.tf

terraform {
  backend "gcs" {
    bucket  = "tf-state-dev"
    prefix  = "terraform/state"
  }
}

module "stage" {
  source = "../modules/infra-common"

  env      = "dev"
  some_var = "value"
}

prod/main.tf

terraform {
  backend "gcs" {
    bucket  = "tf-state-prod"
    prefix  = "terraform/state"
  }
}

module "stage" {
  source = "../modules/infra-common"

  env      = "prod"
  some_var = "value"
}
Related