DEV Community

Cover image for Terraform with Terragrunt to Reduce Duplicate Definitions
Katherine Lin
Katherine Lin

Posted on

Terraform with Terragrunt to Reduce Duplicate Definitions

Infrastructure as Code (IaC) is a critical component in modern cloud deployments, and Terraform has become one of the most popular tools for defining cloud resources. But when you manage complex infrastructure spread across multiple environments, the problem of duplicate code often arises. That’s where Terragrunt comes into play.

In this article, I’ll explain how Terragrunt can help simplify your Terraform workflow, avoid redundancy, and enable reusable cloud infrastructure by deploying resources in multiple modules.

Let's dive in! πŸ—οΈ


What is Terraform?

Terraform is an open-source tool for building, changing, and versioning infrastructure safely and efficiently. It allows users to define cloud resources declaratively using HCL (HashiCorp Configuration Language) and automates the provisioning process across cloud providers like AWS, GCP, and Azure.

While Terraform is extremely powerful, managing different environments like dev, staging, and production can lead to repetitive code as you define similar resources across multiple modules or environments. This is where Terragrunt steps in.


What is Terragrunt?

Terragrunt is a thin wrapper around Terraform that provides extra tools for working with multiple Terraform modules. It simplifies the process of deploying infrastructure by handling things like remote state management, managing dependencies, and reducing duplicate code by using reusable configurations.

In simple terms, Terragrunt helps you DRY (Don't Repeat Yourself) your Terraform code.


Why Use Terragrunt with Terraform?

As your infrastructure grows, you often find yourself writing the same Terraform code over and over for each environment or module. For example, you might define an S3 bucket in dev, staging, and prod environments. This leads to code duplication, which can become hard to maintain.

Here’s why you should consider Terragrunt:

  1. DRY Principle: Eliminate duplicate definitions by defining reusable Terraform configurations.
  2. Simplified Infrastructure: Keep your environment-specific configurations separate from your infrastructure definitions.
  3. Easy Multi-Environment Support: Deploy the same infrastructure across multiple environments with ease.
  4. Remote State Management: Automatically configure remote state and locking.

Applying Terraform Code with Terragrunt πŸ› οΈ

Let’s go through an example where we use Terragrunt to reduce duplicate Terraform code by deploying cloud resources across multiple environments.

Step 1: Organize Your Terraform Modules

First, you need to structure your Terraform code into reusable modules. For example, let’s say you want to create an S3 bucket and an RDS database for your application. Here’s how you can structure the Terraform code:

└── terraform-modules/
    β”œβ”€β”€ s3/
    β”‚   └── main.tf
    β”œβ”€β”€ rds/
    β”‚   └── main.tf
Enter fullscreen mode Exit fullscreen mode

Inside each module (s3/main.tf and rds/main.tf), you define the infrastructure resources, for example:

# s3/main.tf
resource "aws_s3_bucket" "this" {
  bucket = var.bucket_name
}
Enter fullscreen mode Exit fullscreen mode
# rds/main.tf
resource "aws_db_instance" "this" {
  identifier = var.db_name
  engine     = "mysql"
  instance_class = "db.t3.micro"
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Write Terragrunt Configuration

Now that you have your reusable Terraform modules, you can use Terragrunt to apply these modules across multiple environments like dev, staging, and production.

Create the following directory structure:

└── live/
    β”œβ”€β”€ dev/
    β”‚   └── terragrunt.hcl
    β”œβ”€β”€ staging/
    β”‚   └── terragrunt.hcl
    β”œβ”€β”€ prod/
    β”‚   └── terragrunt.hcl
Enter fullscreen mode Exit fullscreen mode

In each terragrunt.hcl file, you reference the Terraform module and define any environment-specific variables. For example, here’s the configuration for the dev environment:

# live/dev/terragrunt.hcl
terraform {
  source = "../../terraform-modules/s3"
}

inputs = {
  bucket_name = "my-app-dev-bucket"
}
Enter fullscreen mode Exit fullscreen mode

For the staging environment:

# live/staging/terragrunt.hcl
terraform {
  source = "../../terraform-modules/s3"
}

inputs = {
  bucket_name = "my-app-staging-bucket"
}
Enter fullscreen mode Exit fullscreen mode

As you can see, you reuse the same Terraform module and only change the inputs (like the bucket_name) for each environment. Terragrunt automatically ensures that the module is applied correctly for each environment.

Step 3: Manage Remote State

Terragrunt makes it easy to manage remote state for Terraform. You can define a common backend configuration in a root terragrunt.hcl file, which all environments inherit:

# live/terragrunt.hcl
remote_state {
  backend = "s3"
  config = {
    bucket         = "my-terraform-state-bucket"
    key            = "${path_relative_to_include()}/terraform.tfstate"
    region         = "us-east-1"
    dynamodb_table = "terraform-locks"
  }
}
Enter fullscreen mode Exit fullscreen mode

Now, all environments (dev, staging, prod) will use this same S3 bucket to store their Terraform state, making it easy to manage and share the state between different environments.

The Benefits of Using Terragrunt

By applying Terragrunt in your Terraform workflow, you unlock several advantages:

  • Reduced Duplication: Instead of copying and pasting similar Terraform code across environments, you create reusable modules and simply adjust inputs for each environment.

  • Easy Environment Management: Spin up new environments with just a few changes in the terragrunt.hcl files.

  • Centralized State Management: With Terragrunt, managing remote state is as simple as defining it once in the root configuration.

  • Clear Separation of Concerns: Separate your infrastructure logic (modules) from environment-specific configurations (Terragrunt configs).

Final Thoughts

By using Terragrunt with Terraform, you can significantly reduce the complexity and repetition in your infrastructure code. This approach scales well as your infrastructure grows, making it easier to manage different environments and resources.

If you’re working with multi-environment setups or struggling with redundant Terraform code, Terragrunt is an excellent tool to streamline your workflow.

Feel free to leave any questions in the comments or share your experiences using Terraform and Terragrunt. Happy coding! πŸŽ‰

Related Resources:

Top comments (0)