I’m working with Terraform for a few weeks now and while our solution is growing, I constantly scratch my head on how to use Terraform in “the best way” (for our project).
When deploying your infrastructure in multiple, separated stages (e.g. DEV, QAT, PROD) there is always the struggle between flexibility, reproducibility (of deployments), and reduction of redundancy (in the Terraform configuration).
In most Terraform examples you find on the web or in literature, you’ll find a folder structure like
live
|- dev
|- qat
|- prod\
with each sub-folder hosting a terraform root module.
IMO, this solution prefers flexibility over reproducibility and reduction redundancies. It probably also helps to reduce complexity within referenced modules. That’s fine.
However, one could argue, that Terraform Workspaces (CLI, not cloud) could be an alternative approach, that prefers reproducibility and reduction redundancies over flexibility.
But then the Terraform documentation states that workspaces are not suitable for staging scenarios (pointing out the probably separated backends for each stage).
From https://www.terraform.io/docs/state/workspaces.html#when-to-use-multiple-workspaces:
In particular, organizations commonly want to create a strong separation between multiple deployments of the same infrastructure serving different development stages (e.g. staging vs. production) or different internal teams. In this case, the backend used for each deployment often belongs to that deployment, with different credentials and access controls. Named workspaces are not a suitable isolation mechanism for this scenario.
Instead, use one or more re-usable modules to represent the common elements and then represent each instance as a separate configuration…
I do not agree on that argument.
While it is probably true, that the backends are separated by stage, the backend information can easily be injected (e.g. via environment variables). So, it is possible to deploy the same configuration to different stages with different backends, as long as the deploying entity has the proper permissions (or different service principals are used for deployment to each stage).
Of course, writing to different backends makes the use of workspaces pointless (you’ll only have one state in the backend and there is no need for disambiguation of the name) but it wouldn’t hurt, either.
Are there further arguments against using a single Terraform configuration for staging (with or without using workspaces)?
Which approach do you follow and why?
Thanks a lot!