20 Best Practices to Improve Terraform Workflow | Part 1

Terraform is one of the most commonly used tools for managing Infrastructure as Code (IaC), allowing us to apply changes to our infrastructure securely and predictably. Getting started with Terraform may feel a little daunting at first, but you'll soon have a basic understanding of the tool and can start running commands, creating and refactoring Terraform code. Along the way, many new users face nuances and questions about how to properly structure their code, use advanced features, apply software development best practices in the IaC process, and more.
 

In this article, we'll discuss best practices for managing IaC with Terraform to help you take your Terraform skills to the next level. Click the Seal blog to read more technical articles about Terraform .
 

How to build a Terraform project

Before we start discussing some best practices for Terraform, let's look at some strategies for building Terraform projects. In the world of Terraform, there is no right or wrong way to build a configuration, and most of the suggested structures you find online are highly subjective. When deciding how to set up your Terraform configuration, the most important thing is to understand your infrastructure needs and use cases, and develop a solution that works for your team and project .
 

If we are dealing with a small project with limited infrastructure components, it is more appropriate to keep the Terraform configuration as much as possible. In such cases, we can configure only the necessary files for the root module, i.e. the configuration files that exist in the root directory. A small project can contain only these files main.tf, variables.tf, README.md. Some other files you may find convenient to use include: outputs.tf(for defining output values ​​for your project), versions.tf(for 收集配置的任何固定版本)以及providers.tf to configure options related to the providers you use, especially if you have multiple providers .
 

Our main entry point is where main.tf, in the simple use case, we can add all our resources. We variables.tfdefine variables in and terraform.tfvarsassign values ​​to them in . We use files outputs.tfto declare output values.
 


 

When dealing with larger projects, it becomes more complex and we need to figure out the best structure for the project.
 

Start by breaking down the Terraform code into reusable components that different teams can use and customize accordingly. We can achieve this by creating separate modules for the infrastructure part, which should be reused across different environments, projects, and teams.
 

A common practice is to separate modules based on ownership and responsibility, rate of change, and ease of management . For each module, we need to define its inputs and outputs and document them thoroughly so that users can use them effectively. We can then leverage outputsand terraform_remote_stateto reference values ​​across modules or even different Terraform states.
 

Note that using terraform_remote_statea data source means accessing the entire state snapshot, which may raise security issues. Another option for sharing parameters between different states is to leverage external tools [1] to publish and consume the data, such as Amazon SSM Parameter Store or HashiCorp Consul.
 

Next you need to decide whether to keep all Terraform code in a single repository (monorepo) or separate the Terraform configuration into multiple code repositories. Both methods have disadvantages and advantages. There is a current trend to avoid huge single repositories and use separate configurations for faster module development and flexibility.
 

Often, we have to deal with a lot of different infrastructure environments, and there are multiple ways to handle this in Terraform. A suitable and easy-to-follow approach is to configure Terraform separately for different environments . This way different environments have their own state that can be tested and managed independently, while shared behavior is implemented through shared or remote modules. One option is to use separate directories for each environment and keep separate state for each directory. Another option is to keep all Terraform configurations in the same directory and pass different environment variables for each environment to parameterize the configuration accordingly.
 

Here you can find example structures for three different environments per directory: production , staging , and testing . Each environment has its own state and is managed separately from other environments while leveraging common or shared modules. Although this approach introduces some code duplication, we gain greater clarity, environment isolation, and scalability.
 


 

Generally speaking, we want to define a Terraform configuration with limited range and blast radius for a specific owner. To minimize risk, we should try to break projects into small workspaces/stacks and segment access to them using role-based access control (RBAC).
 

Terraform best practices

In the previous section, we discussed some general IaC best practices. We explored some options for optimizing Terraform code based on our organizational structure and needs. Here we'll delve into the specific points of taking your Terraform code to the next level, hoping to provide you and your team with tips and guidance on experimenting, researching, and implementing practices that make sense for your use cases.
 

Use remote status

It's okay to use local state when doing some trial and error, and anything above that can use remote shared state locations. Using a remote backend for status is one of the first best practices you should adopt when working in a team . Choose an option that supports status locking to prevent multiple people from changing status at the same time. Treat state as immutable and avoid manual state changes. Make sure you have stateful backups that are available in the event of a disaster. For some backends (such as AWS S3), versioning can be enabled for fast and easy state restoration.
 

Use existing sharing and community modules

Check whether there are already modules with suitable use cases and avoid reinventing the wheel by writing the required modules yourself, which can save a lot of time. You can check the Terraform Registry [2] for available modules. Terraform has a large and mature community, and users can also use the power of the community to solve problems. Enthusiastic users can also help the community by improving it or reporting issues.
 

Import existing infrastructure

If you take over a project that's a few years old, chances are that some parts of its infrastructure were created manually. Don't worry, you can import your existing infrastructure into Terraform and avoid managing your infrastructure from multiple endpoints.
 

Avoid hardcoding variables

Please try to avoid hardcoding variables. Think about it if it wouldn't make more sense to define the value you assign directly as a variable for future changes. More importantly, verify that you can get the property value from the data source without setting it explicitly. For example, instead of finding the AWS Account ID from the console and terraform.tfvarssetting it in:

aws_account_id=”99999999999”

 

We can get the account ID from the data source.

data "aws_caller_identity" "current" {}

locals {
    account_id = data.aws_caller_identity.current.account_id
}

 

Always format and verify

Long-term consistency is critical in IaC , and Terraform provides us with tools to help us achieve this goal. Remember to run terraform fmt and terraform validate to properly format your code and catch any missed issues. Ideally this should be done automatically via a CI/CD pipeline or pre-commit hook.
 

Use consistent naming conventions

There are many suggestions for Terraform code naming conventions available online. The most important thing isn't the rules themselves, but finding ones your team is familiar with and working together to keep them consistent. See below for a list of easy-to-follow rules:

  • Use underscore _ as a separator and use lowercase letters in the name.

  • Try not to repeat resource types in resource names.

  • For single-valued variables and properties, use singular nouns. For a list or map, use a plural noun to indicate that it represents more than one value.

  • Always use descriptive names for variables and outputs, and remember to include descriptions.
     

In the next section, we'll continue exploring more best practices for managing IaC with Terraform.
 

Original link:
https://spacelift.io/blog/terraform-best-practices

参考链接:
1.https://developer.hashicorp.com/terraform/language/state/remote-state-data#alternative-ways-to-share-data-between-configurations

2.https://registry.terraform.io/browse/modules

 

Guess you like

Origin blog.csdn.net/SEAL_Security/article/details/132965435