Terraform: Deploying to Multiple Environments



This can be a hot topic of debate, between engineers. Terraform, Terragrunt, Terraform Workspaces, Makefiles... the list goes on. There are plenty of ways to deploy Terraform however, I prefer to use a (slightly more) native approach.
Terraform
Terraform is a great tool that all Cloud Engineers should be aware of. Terraform is an open source IaC (Infrastructure-as-Code) tool that allows engineers to create, change and improve infrastructure. By writing IaC, this allows you to create infrastructure with predictable and reusable results.
Multi-Environment Strategy
No matter what your development or operational processes looks like, it's always recommended to use multiple environments. Using multiple environments ensures that your code and cloud infrastructure is QA'd and tested before it is deployed and made available to end users.
Commonly, you would have at least a development, staging and production environment:
-
Development: A dev environment should be your first line of defence against bugs. Developers & Cloud Engineers can deploy their code and test any new features. Any bugs found can then be dealt with before re-deploying for further testing. You can then repeat this process until you are happy to promote this to staging.
-
Staging: Once the developers and engineers are satisfied with their code and the environment its running upon, you can then decide whether its stable enough to promote. If it is stable, it is then deployed to the staging environment for further testing. This is where manual and automated Quality Assurance (QA) is performed. They will run test cases to detect bugs and run performance tests to highlight areas that should be improved. Any bugs or enhancements can then be reported back to the developers for fixing.
-
Production: Once the code has been thoroughly tested, it is then pushed to production and made available to end-users.
Deployment
All this sounds great - but how do you deploy your Terraform into multiple environments. In an AWS world, your environments are often in different accounts. Plus, you want to make sure your Terraform follows DRY methodologies. Well, there is a native way!
tfbackend and tfvars are your friend.
By using these, and using effective variables in your Terraform, you can simplify your repo and keep your developers happy with faster deployments and releases.
An example repo structure may look like this:
terraform/
├─ environments/
│ ├─ dev/
│ │ ├─ dev.tfbackend
│ │ ├─ dev.tfvars
│ ├─ stg/
│ │ ├─ stg.tfbackend
│ │ ├─ stg.tfvars
│ ├─ prd/
│ │ ├─ prd.tfbackend
│ │ ├─ prd.tfvars
├─ modules/
├─ backend.tf
├─ provider.tf
├─ s3.tf
├─ variables.tf
├─ vpc.tf
├─ README.md