Simplifying Infrastructure with Terraform and Terragrunt

Infrastructure as Code (IaC) has become a game-changer for DevOps and cloud management. While Terraform is one of the most popular IaC tools, managing complex infrastructures across multiple environments can still be challenging. This is where Terragrunt comes in.

In this post, we'll explore how Terragrunt simplifies Terraform management, allowing you to DRY (Don't Repeat Yourself) out your infrastructure code, manage state efficiently, and automate infrastructure deployments across environments.

What is Terraform?

Terraform, developed by HashiCorp, is an open-source IaC tool that allows you to define, manage, and provision infrastructure in a consistent and repeatable manner. It uses a declarative language called HCL (HashiCorp Configuration Language) to define infrastructure resources.

Terraform is known for its ability to create and manage resources on multiple cloud platforms, including AWS, Azure, and GCP. The infrastructure definitions are stored in .tf files and executed through the terraform CLI. It is highly scalable and allows users to manage both small-scale and enterprise-level infrastructure.

Challenges with Terraform in Complex Infrastructures

While Terraform is powerful, there are several challenges when managing large-scale or multi-environment infrastructures:

  • Duplicated Code: Repetitive Terraform code across environments like dev, staging, and prod.
  • State Management: Keeping track of infrastructure state for multiple environments.
  • Config Reusability: Difficulty in creating reusable modules and configurations.
  • Environment Isolation: Managing isolated environments with different configurations is cumbersome without strict organizational structures.

These challenges often lead to complex setups that are difficult to maintain over time.

Introducing Terragrunt

Terragrunt is a thin wrapper for Terraform designed to solve some of these common challenges. It focuses on:

  • DRY Principle: It helps you reduce code duplication by using a shared configuration layer across different environments.
  • Better State Management: Automates the backend configuration for storing Terraform state remotely (e.g., S3 for AWS).
  • Environment Management: Provides a simple way to manage multiple environments by injecting environment-specific variables and configurations.

Terragrunt uses a terragrunt.hcl configuration file, which helps organize and reuse infrastructure code effectively.

Benefits of Using Terragrunt with Terraform

Here’s why Terragrunt is a great addition to your Terraform setup:

  • Modular Structure: Keep your Terraform modules DRY by applying common configurations in one place.
  • Simplified State Management: Terragrunt automatically configures remote backends, ensuring that state is centralized and secure.
  • Easy Environment Management: Manage multiple environments (dev, stage, prod) with minimal code duplication.
  • Dependency Handling: Terragrunt allows you to define and manage resource dependencies, improving orchestration.

Step-by-Step Implementation

Now, let's walk through how to implement Terraform with Terragrunt.

Step 1: Install Terraform and Terragrunt

Before we begin, you need to install both Terraform and Terragrunt.

  1. Install Terraform: https://learn.hashicorp.com/tutorials/terraform/install-cli
  2. Install Terragrunt: You can install Terragrunt using Homebrew (for macOS) or by downloading the binary.
# MacOS
$ brew install terragrunt

# Linux
$ wget https://github.com/gruntwork-io/terragrunt/releases/download/v0.31.0/terragrunt_linux_amd64
$ chmod +x terragrunt_linux_amd64
$ mv terragrunt_linux_amd64 /usr/local/bin/terragrunt

Step 2: Set Up a Simple Terraform Project

Create a basic Terraform project that provisions an AWS EC2 instance:

main.tf:

provider "aws" {
  region = "us-east-1"
}

resource "aws_instance" "example" {
  ami           = "ami-12345678"
  instance_type = "t2.micro"
}

Run the usual Terraform commands:

terraform init
terraform apply

Step 3: Refactor Terraform Code with Terragrunt

Now, let’s refactor the above Terraform code using Terragrunt to support multiple environments (e.g., dev and prod).

Create a terragrunt.hcl file for each environment.

Example directory structure:

/infrastructure
  └── /live
      └── /dev
          └── terragrunt.hcl
      └── /prod
          └── terragrunt.hcl

In terragrunt.hcl:

terraform {
  source = "../../modules/aws-instance"
}

inputs = {
  instance_type = "t2.micro"
}

This allows you to use the same terragrunt.hcl structure for different environments while modifying only the necessary inputs like instance type, region, or AMI.

Step 4: Manage Multiple Environments with Terragrunt

By using the terragrunt.hcl files in separate folders (/dev and /prod), you can easily deploy different configurations for different environments while reusing the same Terraform codebase.

To apply configurations for the dev environment:

cd infrastructure/live/dev
terragrunt apply

To apply configurations for production:

cd infrastructure/live/prod
terragrunt apply

This ensures isolated, environment-specific configurations with minimal code duplication.

Best Practices for Terraform and Terragrunt

Here are some best practices for using Terraform and Terragrunt:

  • Use Remote State Backends: Always store your state remotely (e.g., S3, GCS) to prevent state corruption.
  • Use Terragrunt for Shared Configurations: Utilize terragrunt.hcl to define shared backends, variables, and environments.
  • Version Your Infrastructure Code: Use version control (e.g., Git) for all Terraform and Terragrunt files to track changes and collaborate effectively.
  • Modularize Terraform Code: Break down your infrastructure into reusable modules.
  • Lock Provider Versions: Ensure stability by locking provider versions in your Terraform configurations.

Conclusion

Terraform, combined with Terragrunt, offers a powerful and scalable solution for managing infrastructure as code. While Terraform is excellent on its own, Terragrunt simplifies state management, reduces code duplication, and helps manage multi-environment infrastructures efficiently.