Terragrunt vs Terraform
In this article, I detail the benefits of using Terragrunt. At the end, I list the reasons why sometimes Terragrunt may not be the right choice for your project.
Terragrunt is a wrapper on top of Terraform that fixes some of Terraform's deficiencies. When you use Terragrunt, you are running Terraform behind the scenes.
In this article, I detail the benefits of using Terragrunt. At the end, I list the reasons why sometimes Terragrunt may not be the right choice for your project.
Intended Audience: Technical team members with some familiarity with Terraform and AWS.
Why use Terragrunt?
The two main benefits of Terragrunt are:
- DRY clean code
- Ease of use
Preamble
Directly from HashiCorp's Terraform best practices, you should avoid a monolithic configuration and eschew a large Terraform state file . In summary, if you put all your cloud resources like EC2, S3, RDS, etc. into Terraform files under one big directory, modifying a S3 bucket will slowly scan and potentially modify other AWS resources in that directory.
Seasoned Terraform users will group the TF configuration files into its own directory, such as VPC, IAM, EC2 or Frontend-UI, Backend-Service, Databases. In practice, this can lead to many duplicate configuration and variables.
DRY clean code
A fundamental tenet of clean code is Don't Repeat Yourself (DRY). If you duplicate code in more than one place, you must change the code in multiple places when doing fixes and enhancements. When you don't change the code in all the duplicated places, bugs occur.
- DRY Input Variables
Terragrunt
You can put all your variables in one file and reuse it via theinputs
block.
Example config
env.hcl
Terraform
You are forced to duplicate your input variables in multiple tfvars files.
Example config
vpc/terraform.tfvars
s3/terraform.tfvars
iam/terraform.tfvars - DRY Output Variables
Terragrunt
Output values are automatically generated from the Terraform module output variables.
Terraform
There are multiple outputs.tf files.
Example config
vpc/outputs.tf
s3/outputs.tf
iam/outputs.tf - DRY remote state backend
Terragrunt
Theremote_state
block dynamically generates the Terragrunt remote state configuration in the parent terragrunt.hcl file.
Example config
terragrunt.hcl
Terraform
The Terraform remote state configuration is defined via thebackend
block. Even worse, Terraform does not allow the use of variables in the backend block so you have to explicitly hard code everything. You must create multiple backend configuration files with nearly identical configuration.
Example config
vpc/providers.tf
s3/providers.tf
iam/providers.tf - DRY CLI arguments
Terragrunt
You can define required Terraform CLI arguments via theextra_arguments
block in one central terragrunt.hcl.
Example config
terragrunt.hcl
Terraform
If you want to always run theterraform
command line with certain required arguments, you would have to hack a custom script.
Ease of use
Terragrunt helps using Terraform more convenient for the operators.
- run-all
Terragrunt
This is the killer feature of Terragrunt.
The primary issue with multiple Terraform state stacks is running it in the right order. For example, you need to apply the VPC stack before the EC2 stack.
You can explicitly define the correct order to apply the stacks viadependencies
. Then executingterragrunt run-all apply
will execute the resource creation in the correct order.
Example config
envcommon/app_ec2.hcl
Terraform
To apply the Terraform stacks in the proper order, you would have to code and maintain your own script.
Example script
terraform.run-all.sh - Before/After/Error hooks
Terragrunt
You may want to run an external program like Slack before and after running Terragrunt. This is accomplished via thebefore_hook
,after_hook
, anderror_hook
.
Exanple config
terragrunt.hcl
Terraform
To accomplish the above hooks in Terraform, it would be a custom wrapper script. - Auto-create remote state resource
Terragrunt
If the remote state backend store (S3 and DynamoDB in AWS) does not exist, Terragrunt will automatically create it for you with the correct security settings.
Example config
terragrunt.hcl
Terraform
Before you can start using Terraform, you either have to create the remote state backing store manually or create the store via Terraform using local state then migrate.
Example config
terraform_infra/main.tf - Auto-retry
Terragrunt
Cloud providers can be finicky or slow. You can configure Terragrunt to automatically retry after a failure with theretry_max_attempts
setting.
Example config
terragrunt.hcl
Terraform
Terraform has no built-in auto-retry setting. - Auto-init
Terragrunt
It's a small annoyance, but in Terraform you must manually executeterraform init
once on a new stack before you canterraform plan/apply
. Terragrunt is smart enough to recognize that an init is needed during the plan/apply phase and will automatically execute it for you.
Why not to use Terragrunt
Yet another tool
DevOps already has a lot of tools to learn. If your team is already overwhelmed, it may not be the right time to introduce yet another tool.
Terraform cloud
Terragrunt does not work well with Terraform Cloud. Terraform Cloud competes with Terragrunt, offering many of the same clean code and ease of use features.
Large Terraform codebase
Refactoring a large Terraform codebase into Terragrunt is a pain, involving many tedious terraform import
. It's more prudent to introduce Terragrunt on a new project codebase instead.
Final thoughts on Terragrunt vs Terraform
I enjoy using Terragrunt on my projects and I wholeheartedly recommend it. Terragrunt offers so many additional benefits on top of the already wonderful Terraform.
If you enjoyed this article, come back next week for my article on "How to layout your Terragrunt project."
A preview can be found at GitHub
https://github.com/deptagency/engineering-blog-terraform-terragrunt/tree/main/soapbox/terragrunt