en programming language Web related javascript 10 Terraform best practices for better infrastructure provisioning

10 Terraform best practices for better infrastructure provisioning

Let’s discuss some of the best practices to follow when using Terraform.

Terraform is a very popular open source IaC (Infrastructure as Code) tool for defining and provisioning complete infrastructure.

Terraform was introduced in 2014, but adoption of this tool is increasing globally. More and more developers are learning Terraform to deploy infrastructure within their organizations.

As you start using Terraform, you should adopt best practices to improve the provisioning of your production infrastructure.

If you’re a beginner, check out our Terraform for beginners article.

10 Terraform best practices for better infrastructure provisioning
10 Terraform best practices for better infrastructure provisioning

structuring

If you are working on a large production infrastructure project using Terraform, you need to follow a proper directory structure to handle the complexity that may arise within your project. It’s best to create separate directories for each purpose.

For example, if you are using terraform in a development, staging, and production environment, have separate directories for each.

 @:~$ tree terraform_project/
terraform_project/
├── dev
│ ├── main.tf
│ ├── outputs.tf
│ └── variables.tf
├── modules
│ ├── ec2
│ │ ├── ec2.tf
│ │ └── main.tf
│ └── vpc
│ ├── main.tf
│ └── vpc.tf
├── prod
│ ├── main.tf
│ ├── outputs.tf
│ └── variables.tf
└── stg
├── main.tf
├── outputs.tf
└── variables.tf

6 directories, 13 files

Over time, the configuration of a growing infrastructure becomes complex, so Terraform configurations must also be individualized.

For example, you could write all your Terraform code (modules, resources, variables, outputs) within main.tf file itself, but it’s more readable and understandable if you write separate Terraform code for variables and outputs. It becomes easier.

10 Terraform best practices for better infrastructure provisioning
10 Terraform best practices for better infrastructure provisioning

Naming convention

Terraform uses naming conventions to make it easier to understand.

For example, let’s say you want to create three different workspaces for different environments within your project. So instead of naming them env1, en2, env3, you should call them dev , stage , prod . From the name itself, it is clear that each environment has three different workspaces.

Similar rules must be followed for resources, variables, modules, etc. Terraform resource names must start with the provider name, followed by an underscore and other details.

For example, the resource name for creating a route table Terraform object in AWS is aws_route_table .

Therefore, if you follow naming conventions correctly, even complex code will be easier to understand.

10 Terraform best practices for better infrastructure provisioning
10 Terraform best practices for better infrastructure provisioning

Using shared modules

We highly recommend using the official Terraform modules available. No need to reinvent modules that already exist. It will save you a lot of time and effort. There are many ready-to-use modules in the Terraform registry . Make changes to existing modules as needed.

Also, each module should focus on only one aspect of your infrastructure, such as creating an AWS EC2 instance or configuring a MySQL database.

For example, if you want to use AWS VPC in your Terraform code, you can use it like this – simple VPC

 module "vpc_example_simple-vpc" {
source
= "terraform-aws-modules/vpc/aws//examples/simple-vpc"
version = "2.48.0"
} 
10 Terraform best practices for better infrastructure provisioning
10 Terraform best practices for better infrastructure provisioning

Latest version

The Terraform development community is very active, and new features are released frequently. As with any new major release, we recommend that you continue to use the latest version of Terraform. Easily upgrade to the latest version.

Skipping multiple major releases greatly complicates the upgrade.

Run the terraform -v command to check for new updates.

 @:~$ terraform -v
Terraform v0.11.14
Your version of Terraform is out of date! The latest version
is 0.12.0. You can update by downloading from www.terraform.io/downloads.html 
10 Terraform best practices for better infrastructure provisioning
10 Terraform best practices for better infrastructure provisioning

System state backup

Be sure to back up your Terraform state files.

These files track infrastructure metadata and resources. By default, these files, called terraform.tfstate , are saved locally in your workspace directory.

Without these files, Terraform has no idea what resources are deployed to your infrastructure. Therefore, it is essential to create a backup of the state file. By default, a file named terraform.tfstate.backup is created to store a backup of the state file.

 @:~$ tree terraform_demo/
terraform_demo/
├── awsec2.tf
├── terraform.tfstate
└── terraform.tfstate.backup
0 directories, 3 files

If you want to save the backup state file in a different location, use -backup flag with the terraform command and specify the path to that location.

In most cases, multiple developers are working on a project. Therefore, to allow access to state files, you must store them in a remote location using terraform_remote_state data source.

The following example takes a backup to S3.

 data "terraform_remote_state" "vpc" {
backend = "s3"
config = {
bucket = “s3-terraform-bucket”
key = “vpc/terraform.tfstate"
region = “us-east-1”
   }
}

lock state file

There are several possible scenarios where multiple developers attempt to run Terraform configurations at the same time. This can lead to terraform state file corruption and data loss. A locking mechanism helps prevent that from happening. This ensures that only one person is running the Terraform configuration at a time and there are no conflicts.

Here is an example of using DynamoDB to lock a state file in a remote location.

 resource “aws_dynamodb_table” “terraform_state_lock” {
name = “terraform-locking”
read_capacity = 3
write_capacity = 3
hash_key = “LockingID”

attribute {
name = “LockingID”
type = “S”
   }

}
terraform {
backend “s3” {
bucket = “s3-terraform-bucket”
key = “vpc/terraform.tfstate”
region = “us-east-2”
dynamodb_table = “terraform-locking”
   }
}

The DynamoDB database name and primary key are used to lock the state and maintain consistency when multiple users attempt to access the state file.

Note : Not all backends support locking.

Use self variables

self variable is a special type of variable used when the value of the variable is not known before deploying the infrastructure.

Suppose you want to use the IP address of the instance that is deployed only after the terraform apply command. Therefore, the IP address is not known until the instance is up and running.

In such cases, use the self variable. The syntax to use this is self.ATTRIBUTE . So in this case, use self.ipv4_address as the self variable to get the IP address of the instance. These variables are only allowed in the connection and provisioner blocks of Terraform configuration.

 connection {
host = self.ipv4_address
type = "ssh"
user = var.users[2]
private_key = file(var.private_key_path)
}

Minimize explosion radius

Blast radius is just a measure of the damage that can occur if things don’t go as planned.

For example, if you have some Terraform configurations deployed on your infrastructure and the configurations are not applied correctly, how much damage will it cause to your infrastructure?

Therefore, it is always recommended to push several configurations to your infrastructure at once to minimize the blast radius. So if something goes wrong, the damage to your infrastructure is minimal and can be fixed quickly. Deploying many configurations at once is very risky.

Use var files

terraform allows you to create a file with the extension <em>.</em>tfvars and pass this file to the terraform apply command using the -var-file flag. This is useful for passing variables that you don’t want to include in your terraform configuration code.

It is always recommended to pass variables such as passwords and private keys locally via -var-file rather than storing them within the Terraform configuration or in a remote version control system.

For example, if you want to launch an ec2 instance using terraform, you can pass the access key and secret key using -var-file .

Create a file terraform.tfvars and put your keys in this file.

 @:~$ gedit terraform.tfvars

access_key = "AKIATYWSDFYU5DUDJI5F"
secret_key = "W9VCCs6I838NdRQQsAeclkejYSJA4YtaZ+2TtG2H"

Then use this var file with the terraform command.

 @:~$ terraform apply -var-file=/home//terraform.tfvars

user docker

We recommend using Docker containers to run build jobs for your CI/CD pipeline. Terraform provides official Docker containers that you can use. If you want to change your CI/CD server, you can easily pass the infrastructure around in a container.

Before deploying your infrastructure in production, you can also test it on Docker containers, which are very easy to deploy. Terraform and Docker together provide a portable, reusable, and repeatable infrastructure.

conclusion

We hope these best practices will help you create better Terraform configurations. Implement these in your Terraform project for better results.

An easy-to-understand explanation of “Terraform’s 10 Best Practices for Better Infrastructure Provisioning”! Best 2 videos you must watch

Terraform Cloudを使って分離された環境にプロビジョニングする
https://www.youtube.com/watch?v=dPJuFK_-SEc&pp=ygWGAeOCiOOCiuiJr-OBhOOCpOODs-ODleODqeOCueODiOODqeOCr-ODgeODoyDjg5fj g63jg5Pjgrjjg6fjg4vjg7PjgrDjga7jgZ_jgoHjga4gVGVycmFmb3JtIOOBriAxMCDjga7jg5njgrnjg4gg44OX44Op44Kv44OG44Kj44K5JmhsPUpB
HashiCorp Virtual Strategy Day Japan Vol.2 「リクルートのAWS基盤における Terraform運用 – 実践的な取り組みと組織づくり」
https://www.youtube.com/watch?v=6m7wVnKbQa8&pp=ygWGAeOCiOOCiuiJr-OBhOOCpOODs-ODleODqeOCueODiOODqeOCr-ODgeODoyDjg5fj g63jg5Pjgrjjg6fjg4vjg7PjgrDjga7jgZ_jgoHjga4gVGVycmFmb3JtIOOBriAxMCDjga7jg5njgrnjg4gg44OX44Op44Kv44OG44Kj44K5JmhsPUpB