Mastering Infrastructure as Code requires more than just Terraform. Learn how to use Terragrunt to simplify multi-cloud management and automate your DevOps workflows.
Managing infrastructure across AWS, GCP, and Azure using raw Terraform usually leads to one thing: a massive, unmaintainable mess. I’ve spent years cleaning up "copy-paste" modules where a single change in a network security group required updating twenty different directories. If you're tired of repeating yourself, it’s time to talk about Terragrunt.
Terraform is excellent for provisioning, but it isn’t built to handle the complexity of multi-cloud environments at scale. When you manage multiple environments—dev, staging, production—across different cloud providers, you quickly hit the "DRY" (Don't Repeat Yourself) wall.
Standard Terraform forces you to duplicate backend configurations, provider blocks, and variable definitions. That’s where Terragrunt comes in. It’s a thin wrapper that provides extra tools for keeping your configurations dry, managing remote state, and orchestrating multiple modules.
First, ensure you have the required tools installed. I’m currently using:
To start, move your backend configuration out of your main.tf and into a root terragrunt.hcl file. This is the magic of Terragrunt. You define the backend once, and every child module inherits it.
HCL# Root terragrunt.hcl remote_state { backend = "s3" generate = { path = "backend.tf" if_exists = "overwrite_terragrunt" } config = { bucket = "my-terraform-state-bucket" key = "${path_relative_to_include()}/terraform.tfstate" region = "us-east-1" encrypt = true dynamodb_table = "terraform-lock-table" } }
By using ${path_relative_to_include()}, Terragrunt automatically creates a unique state file path for every directory, preventing state collisions across your multi-cloud setup.
When you're dealing with Infrastructure as Code across providers, the biggest headache is variable propagation. You need to pass outputs from an AWS VPC to a GCP VPN gateway.
Terragrunt allows you to define dependencies between modules using the dependency block. This ensures that the infrastructure is applied in the correct order, and you can pull outputs directly from one module into another.
HCL# modules/gcp-vpn/terragrunt.hcl dependency "aws-vpc" { config_path = "../aws-vpc" } inputs = { remote_vpc_cidr = dependency.aws-vpc.outputs.vpc_cidr }
This approach makes DevOps automation feel like actual software engineering. You aren't just writing static files; you're building a dependency graph that the CLI resolves for you at runtime.
I’ve seen too many teams use git branches to manage staging vs. production. Don't do that. It leads to configuration drift that's impossible to debug.
Instead, use a folder structure that mirrors your architecture:
TEXTinfrastructure/ ├── terragrunt.hcl (root) ├── prod/ │ ├── aws/ │ │ └── vpc/terragrunt.hcl │ └── gcp/ │ └── k8s/terragrunt.hcl └── dev/ └── aws/ └── vpc/terragrunt.hcl
By keeping your code this way, you can run terragrunt apply-all from the prod/ directory to deploy your entire stack, or navigate to a specific folder to make a targeted change. It’s clean, predictable, and—most importantly—auditable.
source = "git::git@github.com:org/repo.git//modules/vpc?ref=v1.2.0"). This prevents a change in one environment from accidentally breaking another.--terragrunt-include-dir flag to target specific changes.terragrunt plan in your CI/CD pipeline, you’re flying blind. Make sure your pipeline fails if the plan isn't clean.Multi-cloud management is inherently messy, but using Terraform combined with Terragrunt provides the abstraction layer necessary to keep your sanity. It forces you to think about your infrastructure as a coherent system rather than a collection of disparate shell scripts.
Stop repeating your configurations. Start treating your infrastructure as code that’s actually maintainable. Your future self—and your team—will thank you during the next midnight production incident.
Master Infrastructure as Code drift detection with Terraform and Driftctl. Learn how to automate remediation and keep your cloud environment synchronized.
Read moreMaster Kubernetes Cluster API for automated node upgrades. Learn how to leverage MachineHealthCheck for reliable, hands-off node lifecycle management today.