DevOps - Terraform



In this chapter, we will look at the basic ideas of Terraform. We will talk about its structure, configuration files, and how we manage state. We will also look at why using Terraform modules is good for reusability. We will see how we can use Terraform in CI/CD pipelines. Finally, we will share best practices to make the most of Terraform in our DevOps workflows.

Understanding Infrastructure as Code (IaC)

Infrastructure as Code or IaC is an important DevOps practice. It helps us manage our infrastructure with code instead of doing things by hand. With IaC, we can define, create, and manage our infrastructure using easy configuration languages. This gives us more consistency, repeatability, and the ability to grow.

Common IaC Tools

Here are some of the common IaC tools −

  • Terraform − A tool for building, changing, and tracking infrastructure.
  • Ansible − A tool for managing configurations and orchestration.
  • CloudFormation − A special IaC tool for AWS to set up resources.

When we use IaC, we can have faster deployment cycles and better management of our infrastructure.

Terraform Architecture and Components

We will discuss how Terraform works. It uses a client-server structure with some important parts. This helps us manage our infrastructure better.

Following are the key components of Terraform architecture:

  • Terraform CLI is the command-line tool we use to run Terraform commands. We can manage our infrastructure and work with configuration files here.
  • Providers are plugins that help Terraform connect with different cloud services like AWS, Azure, or Google Cloud. Each provider has its own resources that we can use.
  • Resources are the basic building blocks in Terraform. They represent services in the cloud or parts of infrastructure. For example, we can create EC2 instances or S3 buckets. Here is a sample configuration −
resource "aws_instance" "example" {
   ami = "ami-0c55b159cbfafe01e"
   instance_type = "t2.micro"
}

State Files − These are JSON files that keep track of the current state of our infrastructure. They are very important for linking real-world resources to our configuration.

Modules − These are groups of resources that we use together. They help us reuse code and keep things organized. Here is an example −

module "vpc" {
  source = "./modules/vpc"
  cidr_block = "10.0.0.0/16"
}

Backend − This is where we store our state file. It can be local or remote like S3 or Terraform Cloud. This helps us work together and manage the state.

Understanding these parts is very important for us to use Terraform well in a DevOps setting.

Writing Terraform Configuration Files

We write Terraform configuration files using HashiCorp Configuration Language (HCL). This language is easy for humans to read and also works well for machines. These files help us define the infrastructure resources we want to create and manage.

A Terraform configuration usually has these main parts

Provider Block − This shows which cloud provider we are using. For example, we can use AWS or Azure.

provider "aws" {
   region = "us-west-2"
}

Resource Block − This part tells us what resources we want to create.

resource "aws_instance" "web" {
   ami = "ami-0c55b159cbfafe1f0"
   instance_type = "t2.micro"
}

Output Block − This shows information after we run the configuration.

output "instance_ip" {
   value = aws_instance.web.public_ip
}

Variables and Inputs

We can define variables to make our configurations easier to reuse −

variable "instance_type" {
   description = "Type of instance"
   default = "t2.micro"
}

We can use these variables in our resource definitions −

resource "aws_instance" "web" {
   ami = "ami-0c55b159cbfafe1f0"
   instance_type = var.instance_type
}

Managing Terraform State

Managing Terraform state is very important. It helps us track the resources that our configurations create and lets us change them correctly. Terraform keeps a state file called terraform.tfstate. This file shows the current state of our infrastructure. If we manage it well, we can keep everything consistent and avoid configuration drift.

Let's understand some of its key concepts −

  • State File − This is a JSON file. It connects resources in our configurations to the real-world items.
  • Remote State − When we store the state file remotely, like in AWS S3, Azure Blob Storage, or Terraform Cloud, it helps us work together better and protects us from losing data.

Best Practices for State Management

Use Remote Backends − This helps us with locking and versioning. Here is an example configuration for AWS S3 −

terraform {
   backend "s3" {
      bucket  = "my-terraform-state"
      key = "terraform.tfstate"
      region = "us-east-1"
      dynamodb_table = "terraform-locks"
   }
}

State Locking − This stops multiple actions at the same time that could mess up the state.

State Encryption − We should make sure sensitive data in the state file is encrypted when it is stored.

State Commands

  • terraform state list − This command shows us the resources in the state.
  • terraform state show <resource> − This command gives details about a specific resource.
  • terraform state rm <resource> − This command removes a resource from the state but does not destroy it.

Terraform Modules and Reusability

Terraform modules as boxes that hold different resources we use together. They help us make parts that we can use again. This makes our code easier to manage and we do not have to write the same thing over and over again.

A module usually has the following three files −

  • tf − This file has the resource definitions.
  • tf − This file defines the input variables.
  • tf − This file shows the outputs from the module.

You can use modules by writing a module block in our Terraform configuration files −

module "vpc" {
   source = "./modules/vpc"
   cidr_block = "10.0.0.0/16"
   availability_zones = ["us-west-2a", "us-west-2b"]
}

Example of a Simple Module

# modules/vpc/main.tf
resource "aws_vpc" "main" {
   cidr_block = var.cidr_block
}
# modules/vpc/variables.tf
variable "cidr_block" {
   description = "CIDR block for the VPC"
   type = string
}
# modules/vpc/outputs.tf
output "vpc_id" {
   value = aws_vpc.main.id
}

Using modules the right way can make our Terraform setups easier and helps us follow good practices in managing our infrastructure.

Implementing Terraform in CI/CD Pipelines

We can use Terraform in CI/CD pipelines to automate how we set up our infrastructure. This helps us keep things consistent and allows us to deploy quickly. Here is a simple way to add Terraform to our CI/CD workflows:

Now let's understand the steps to integrate Terraform

  • First, make sure that your CI/CD tool like Jenkins, GitLab CI, or GitHub Actions can access the right credentials. This will let it talk to our cloud provider.
  • Keep your Terraform configuration files in a version-controlled repository like Git. It is a good idea to use environment variables or secret management tools to manage sensitive data like API keys.
  • Run terraform plan to make a plan for execution. This shows us what changes will happen without applying them.
terraform init
terraform plan -out=tfplan

We can add a step for manual approval for important changes. Then, run terraform apply to set up the infrastructure.

terraform apply tfplan

You should add tests to check if the infrastructure works after you deploy it. If you need to, then clean up resources with terraform destroy.

CI / CD Tool Integration Examples

GitHub Actions −

name: Terraform CI
on:
  push:
    branches:
      - main
jobs:
  terraform:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v2
      - name: Set up Terraform
        uses: hashicorp/setup-terraform@v1
        with:
          terraform_version: 1.0.0
      - name: Terraform Init
        run: terraform init
      - name: Terraform Plan
        run: terraform plan

Best Practices for Terraform in DevOps

We need to use Terraform well in a DevOps setting. This means we should follow some best practices. This helps us keep our work easy to manage, grow, and work together. Here are some important tips −

Organize Configuration Files − We should arrange our Terraform files in a clear way. It helps to use different folders for each environment like dev, staging, and prod.

 main.tf
 variables.tf
 outputs.tf
 dev/
    main.tf
 prod/
    main.tf

You can make reusable modules for common parts of your infrastructure. This helps us follow the DRY principle, which means Don't Repeat Yourself.

It is important to use remote state storage like AWS S3 with DynamoDB for locking. This helps us work together safely and avoid problems. Here is an example of a backend setup

terraform {
   backend "s3" {
      bucket = "my-terraform-state"
      key = "statefile.tfstate"
      region = "us-east-1"
      dynamodb_table = "terraform-locks"
   }
}

You should frequently run terraform fmt and terraform validate commands. This keeps the code quality good and easy to read.

Conclusion

In this chapter, we looked at the important parts of Terraform in the DevOps framework. We talked about Infrastructure as Code (IaC) principles. We also covered Terraform architecture, how to write configurations, state management, module reusability, and how to integrate it into CI/CD pipelines.

Advertisements