When working with such an advanced provisioning software as Terraform, it’s easy to get overwhelmed. What are the best practices to follow? What mistakes should I avoid? That is why Iguana Solutions’ expert team compiled the Top 3 Terraform Dos and Don’ts to help organizations to embrace this amazing open-source Infrastructure As Code tool created by HashiCorp.
Terraform: Top 3 Best Practices
Let’s start with the basics, which are the 3 best practices that you should always follow when working with Terraform.
1. Read Terraform documentation
Reading the documentation is hands down the most underrated best practice when working with Terraform. One of the aspects that differentiate Terraform from other projects is the incredible work that HashiCorp has done with the official documentation. At Iguana Solutions, we do not hesitate to rate the Terraform documentation as one of the most valuable sources of knowledge and resources you can find online.
Whether you have questions regarding HCL syntax, Terraform configuration, API, VCS integration, or Terraform workspaces, the official documentation should be your starting point. This saves you many hours of research and may even prevent you from making mistakes when using configurations or tips that are no longer valid in the most recent versions of Terraform.
In other words, by reading the official Terraform documentation, you benefit from:
- Using the latest resources
- Avoiding using “best practices” that are no longer recommended
- Avoiding making mistakes or introducing discrepancies when using code that is no longer valid
- Improve the security of your code
2. Design modules to be “Generic.”
It is almost a constant in all programming languages to promote the use of “reusable code.” After all, isn’t that one of the advantages of using a structured programming language in the first place?
Well, as obvious as it may seem, many developers fall into the trap of not designing modules to be generic; instead, they create modules to solve individual requirements in an environment. What usually happens in these cases is that as the organization’s infrastructure grows (and therefore the number of requirements and environments), you will have to rewrite a good part of the code. Even worse, the code will become more complicated than it should be due to the countless versions and modifications to each module.
You may be wondering, how can this situation be avoided? The answer is simple, making sure the modules are as generic as possible. You can tell if a module is generic by looking at its characteristics. Usually, generic modules share the following features:
- They are reusable; hence they are called “generic.”
- They generally perform a single job.
- They are well documented so that they can be easily modified.
To illustrate this concept, consider a module responsible for importing an SSH public key file into AWS. This would be a reusable module since it can be used in any environment (development, production, staging, etc). In addition to that, it does only one job (importing an SSH public key file into AWS) so it would be very easy to document it properly.
3. Automate everything
Process automation is one of the core principles of DevOps. In fact, in one of our previous articles, 4 Ways Terraform Can Improve DevOps Adoption, we already mentioned how Terraform allows you to automate infrastructure provisioning. On this occasion, we will reinforce this concept by echoing the official documentation “Terraform Recommended Practices,” where this process is discussed in depth.
It is no coincidence that automation is such an important concept as to be considered a Best Practice. Using the command line or custom scripts to edit your infrastructure is not a viable long-term solution. Results are not always reproducible, not to mention the human error in performing all these complex processes manually.
To go deeper, it is important to consider IaC like any other development process and you should include IaC under your usual CI/CD pipelines. It is the key to secure Infrastructure deployment. CI /CD pipelines ease collaborative work between your different teams. It provides tools to set best practices rules for code check and peer reviewing. And the most important thing, it is the guarantee to work on the same version of the IaC stack and to share the current state of your deployments. It allows you to define several environments to validate your work before going on Production.
DevOps’ principles tell us that modern infrastructure must be scalable and must not depend on manual processes. In other words, if you are going to use Terraform, then you should get the most out of it by automating all of your provisionings. At Iguana Solutions, we know that this is not easy. Still, it is the only way to follow the DevOps guidelines and the foundational practices that make Infrastructure As Code (IaC) so useful.
If you are interested in migrating from manual provisioning to a semi-automatic process or migrating from a semi-automatic procedure to one that complies with the principles of IaC, at Iguana Solutions, we will be happy to help you.
Terraform: Top 3 Mistakes To Avoid
Just as important as best practices are the mistakes to avoid. In this section, we are going to discuss the most common among developers.
1. Store secrets in plaintext
Arguably, one of the most common mistakes when using Terraform is storing sensitive information in plain text. This error is common in both newbies and experienced developers. The reason? They forget that anyone with access to the repository could obtain these secrets.
Fortunately, fixing this security flaw is relatively straightforward.
- Exclude all files prone to storing sensitive data (.tfstate, crash.log, * override.tf *, .terraformrc, terraform.rc). Github offers a .gitignore that can be very useful in this regard
- Encrypt all the secrets that you store in your version control system. This can be accomplished using tools like Git-crypt, BlackBox, SOPS, or Transcrypt. Depending on your development environment, some of them may be better suited than others, so we recommend delving into secret management tools for Git encryption.
- Another valid alternative is using an external secret manager. In Iguana Solutions, our favorites are AWS Secrets Manager and Vault developed by HashiCorp, the same company behind Terraform.
2. Not documenting your code
As with any other programming language, documenting the code is considered a best practice. Why? Simple. As the infrastructure grows, new configurations are introduced to the existing components, new services are added, more nodes are added, and other changes that little by little increase the complexity of the tfstate files exponentially.
Take into account another important aspect. In most cases, it is not one person but several who add or modify the code. In other words, different developers, with different visions of how to solve a problem, implement their own solutions based on their experience.
For each of these developers, their code makes sense, but what about the others? Since you can obtain the same result using different paths, it is common for two people to disagree or simply do not understand why a particular change is being made to the code.
The simplest solution to this problem is to establish a clear policy regarding code documentation. That is why Iguana Solutions’ experts suggest documenting each change introduced in the code using your company’s policies. This recommendation is valid regardless of the coding language. Whether you prefer to use the HashiCorp Configuration Language (HCL) or JSON, the goal is the same, making the code as easy to understand as possible.
Finally, documenting the code will make debugging it a lot easier, which will improve the efficiency of the development cycle.
3. Using the wrong directory or repository structure
This is possibly one of the most controversial points since it has a lot to do with the “recommended” way of structuring Terraform’s files and configurations. While Terraform is flexible about using any organization method for its files, in our experience, certain directory and repository structures can potentially cause a lot of inconveniences when scaling your infrastructure.
But what does this mean in practice? Well, according to the official Terraform documentation, the best way to organize your code and the structure of your repositories is to use an organization that favors the isolation of dependencies and modularity.
In fact, the Terraform documentation proposes a straightforward solution: “… If your organization does not have a strong preference, we recommend using separate repositories for each configuration and using the private module registry to share modules. This allows for faster module development since you don’t have to update every configuration that consumes a module at the same time as the module itself …”
Simply put, to avoid unnecessary headaches as your organization grows, our suggestion is to avoid at all costs using the “monorepo” approach and instead favor keeping each Terraform configuration in a separate repository.
At Iguana Solutions we love Terraform so much that our amazing team has developed the official OpenNebula provider which is now available on the OpenNebula github and listed on the official Terraform providers list!
Need help or expertise for your next project involving Terraform? Contact us!