Another view on Terraform DRY: Part 1
As the size of the infrastructure grows and terraform code becomes more complex, maybe you have several environments spanning multiple regions.
Having to maintain all of this code between environments becomes more error prone, and you will end up with staging environment that are different than the production ones.
Also, is a really good practice to refrain yourself to run this code on your own machine and staple it to CI/CD like Gitlab-CI or Jenkins. Since my CI workers are ephemeral I won’t use Terraform Workplaces.
Consider the following file structure, which defines two environments (stg, prd) and two regions (us-east-1, eu-west-1)
1 | vpc |
The contents of each environment will be identical since they all use the same .tf
files, except perhaps for a few settings that will be defined with variables (e.g. the prod environment may run bigger or more servers and staging could have a smaller vpc length).
Each region and environment will have their own Terraform State Files
(or tfstate
) defined in remote_backend.tfvars
file. You can pass the flag -backend-config=...
during terraform init
to setup your remote backend. Keep in mind that since our CI runners are ephemeral we are always starting fresh with no .terraform
directory.
1 | terraform init -backend-config ${VAR_DIR}/${ENV}/${REGION}/remote_backend.tfvars |
The contents of remote_backend.tfvars
will look like this:
1 | ➜ cat vpc/vars/prd/us-east-1/remote_backend.tfvars |
With each level of terraform.tfvars
, will overwrite the previous ones. This means that the lower terraform.tfvars
will take over the previous ones.
This will allow us to configure variables that are global to all environments and regions and have variables that are exclusive to a single environment.
For example:
1 | ├── vars |
This will allow me to have 3 tiers of tags variables, very useful when you want to have all your resources properly tagged for cost analysis.
1 | ➜ cat vpc/vars/terraform.tfvars |
1 | ➜ cat vpc/vars/stg/terraform.tfvars |
1 | ➜ cat vpc/vars/stg/us-east-1/terraform.tfvars |
In the case of the variable foo
the value that will take precedence is bar2
To load all these variables we will need to pass terraform plan
action the variables in the order we want, e.g.
1 | terraform plan -var-file ./vars/terraform.tfvars -var-file ./vars/stg/terraform.tfvars -var-file ./vars/stg/us-east-1/terraform.tfvars -out terraform.tfplan |
To apply my plan I only need to point terraform to the plan file, because the plan file already have all the necessary variables and configuration to work.
1 | terraform apply terraform.tfplan |