joseph goksu
Terraform Best Practices
Published on

Terraform Best Practices

Things I've learned while working with Terraform for the last 3 years.
Authors

Overview

Hello terraformers,

Terraform is a great Infrastructure as Code tool. I've been using it for a long time and have considerable knowledge of it.

In this blog post, I'd want to share my own experience. As I previously said, this is based on my personal experience rather than explaining the industry standards.

Everything started with a simple issue. I stored my state in my local machine when I first started using Terraform. Somehow, the state became corrupted, and I had to manually remove AWS resources. We all learn from our mistakes, don't we?

After that, I started to check a better way to store the state. I found it later. The answer was simple: remote state management.

We have an unified cloud architecture for the entire platform at my job, but in the terraform implementation, each AWS resource has multiple terraform states. We currently have almost 139 resources. As a result, it became extremely complex and difficult to maintain. I discovered it was incorrect and began refactoring the implementation. I also decided to discontinue the use of community modules and consolidate all repositories into a single folder.

So, I put the modules together, and I started to implement the best practices.

Platform Repository Folder Structure

That is how I designed the folder structure:

repository-stucture
├── main.tf
├── variables.tf
├── outputs.tf
├── providers.tf
├── module_name
│   ├── main.tf
│   ├── variables.tf
│   ├── outputs.tf
│   ├── providers.tf (optional)
├── module_2_name
│   ├── main.tf
│   ├── variables.tf
│   ├── outputs.tf
│   ├── providers.tf (optional)

In a monorepo, each module is its own folder. It allowed me to keep all of the Terraform files in one location. Also, if I don't want to deploy a specific module, I may pass a boolean flag.

When I started writing my own module from scratch, I found I had complete power. I also learn about more Amazon Web Services (AWS) features. I'm referring to some specific features that I can integrate into my modules.

You should ask yourself those questions.

  • How complicated is your project?
  • How frequently does your infrastructure undergo changes?
  • Which deployment platform or deployment service do you use?
    • AWS CodeDeploy, Kubernetes, or OpenShift require a slightly different approach
  • How environments are grouped?
    • By environment, region, project

These questions will shape how you deploy your infrastructure. It also affects your Terraform code style.

Terraform Best Practices:

  1. Use a remote state to keep your infrastructure in sync (https://www.terraform.io/language/state/remote)
  2. Import existing infrastructure (if you have it)
  3. Use highly rated community modules or write from scratch (https://www.terraform.io/docs/modules/index.html)
  4. Avoid variables hard-coding (Make it dynamic as much as possible)
  5. Tag your Resources (Especially if you have multiple environments)
  6. Always format and validate your code (Vscode extensions, look at below)
  7. Introduce Policy as Code (https://josephgoksu.com/devops/devops-policy-as-code/)
  8. Use a consistent naming convention for your resources (e.g. aws_instance.my_instance)
  9. Implement a Secrets Management Strategy (AWS Secrets Manager, KMS and Hashicorp Vault)
  10. Test your Terraform code with multiple environments (e.g. dev, test, prod)
  11. Keep it Simple (KISS)

Development Environment Setup (VSCode)

I just use two plugins.

  1. Hashicorp Terraform
  2. Terraform

Thanks for reading! Reach out to me on Twitter if you have any questions or comments.

References