In this article, we will explore Terragrunt, a popular tool that promotes DRY (Don’t Repeat Yourself) practices and helps you use Terraform more effectively. DRY practices aim to reduce repetitive patterns and ensure that every piece of knowledge in your system has a single, unambiguous representation. We will also see how to use Terragrunt to set up resources on Google Cloud (GCP).
By walking through a practical example, you will learn how to streamline your Terraform configurations, improve code maintainability, and efficiently manage your cloud infrastructure in Google Cloud.
Terragrunt: Make the most of Terraform
Note: Before we start, make sure you have a basic understanding of Terraform.
Terraform is an Infrastructure as Code (IAC) tool that provisions and manages infrastructure (resources) in any cloud or data centre. It’s a powerful tool for IAC, but it can encounter many challenges as projects grow. For example, Terraform configurations can become repetitive and duplicated, especially when handling multiple environments and components. Which can lead to maintenance difficulties.
Additionally, Terraform modules can depend on each other, complicating management and increasing the risk of errors due to manual oversight.
Managing a remote state can also become complex and challenging in large projects, especially when working with multiple environments and different teams. Similarly, provisioning and managing resources across multiple environments and reusing the same components can be tedious and difficult.
Terragrunt offers solutions to all of these challenges.
Terragrunt’s Core Benefits
Eliminate Repetition with Terragrunt
Abstractions or the “Don’t Repeat Yourself” (DRY) principle is a well-known software engineering pattern that aims to reduce duplicated code. This helps avoid managing extra configurations and simplifies system changes.
Terragrunt allows you to share configurations across multiple Terraform modules or environments by defining, for example, the backend configurations, provider configurations, and variables at the root level. This way, all child modules can inherit these settings, eliminating repetition and promoting reusability.
Effortless State Management with Terragrunt
Terragrunt stores state files remotely, automatically creating and enabling locking resources (bucket) automatically to manage states. This helps avoid manual errors, state overwrites, and shares states across teams. As a result, you ensure that you are using the correct state configuration without any manual configuration of your modules.
Simplify Dependencies Between Modules
Usually, terraform modules depend on each other. For example, a database or computer instance may depend on the network, requiring you to manage the order in which modules are deployed. Terragrunt allows you to manage dependencies between modules explicitly, ensuring resources are provisioned in the correct order. Additionally, the outputs of modules can be passed to others, streamlining the process.
Terragrunt: Manage Multiple Environments with Ease
Managing multiple environments with Terraform requires additional configuration and management through workspaces and variables. This can be tedious and error-prone. Terragrunt simplifies this process by allowing you to define separate configuration files for each environment, reducing code duplication and minimising errors.
Streamline Your Terraform Workflow
In large projects with many teams, modules, and resources, Terraform can make it challenging to manage the workflow (init, plan, apply, etc.) across different environments, teams, and modules. Terragrunt simplifies this by automatically running Terraform commands in the correct order across modules, eliminating the need for manual execution and keeping files organised.
Practical Terragrunt Use Cases: Deploying on Google Cloud
This example is not intended for production use; it demonstrates key features of Terragrunt. It helps keep your terraform code DRY, remote state configuration DRY, and Terragrunt architecture DRY.
This project deploys (a GCE, a MySQL database, an Instance Template, and a VPC) in three environments (dev, stage, and prod)
This project utilises public Terraform modules for GCP and is inspired by the official Terragrunt documentation.
Source code
This project organises and manages different environments and modules, using Terragrunt to simplify the configuration and promote DRY principles.
The configuration is designed to be modular and reusable, with a central configuration inherited across different environments or modules.
This setup allows for centralising configurations, making it easier to manage and maintain common settings across multiple environments and modules. Any variables, remote state configurations, or other settings defined in the parent `terra grunt.hcl` will be applied to the module.
Keep Your Terraform Dry
This architecture manages different environments (development, stageand production) and various components (db, gce, template, vpc).
- terragrunt.hcl at the root level is used for setting global configurations applicable across all environments and modules.
- common-vars.hcl contains common variable definitions shared among different modules and environments.
- env-vars.hcl contains environment-specific variable definitions.
You have different components (e.g., db, gce, template, vpc) in each environment. Each component directory contains its own terra grunt.hcl and module-vars.hcl files.
Notes:
This Terragrunt Project does the following:
- Loads Configuration Variables
- Module Variables: Loads module-specific variables from module-vars.hcl.
- Common Variables: Loads common infrastructure variables from common-vars.hcl.
- Environment Variables: Loads environment-specific variables from env-vars.hcl.
- Remote State
- Creates Remote State for each component.
- Every component state will be managed in a different state file.
- Google Cloud Storage (GCS) is the backend for storing Terraform state files.
- Inputs
- Merges the variables from the common, environment, and module-specific configurations. (Pay attention to the order, the last value is the module value)
- Terraform Source
- Specifies the source and version of the Terraform module to be used, which may vary across environments.
- Components
Each component (such as DB (database)) or GCE (Google Compute Engine) makes use of Terragrunt’s features, including inheriting parent configurations, managing dependencies, and dynamically passing inputs.
Terragrunt configuration file does the following:
- Includes Parent Configuration: Inherits configurations from a parent terragrunt.hcl file, enabling consistent settings across environments and avoiding duplication.
- Manages Dependencies: Defines a dependency to VPC (Virtual Private Cloud).
- Passes Inputs: Uses the outputs from dependencies as inputs to other modules, allowing dynamic infrastructure management.
By following this setup, you can manage your Terraform infrastructure dynamically and efficiently across different environments and modules, keeping it modular and maintainable.
For more details about the project, please refer to the README file.
Usage:
Basic command:
Most Terragrunt commands use the Terraform command.
- Terragrunt will automatically call Terragrunt init during other commands (e.g. terragrunt plan).
- You can deploy the project (Hello World), by component or at once.
Use the Power of Terragrunt for Cleaner Infrastructure Code
In this article, we have explored an example of using Terragrunt to deploy resources on Google Cloud (GCP) in different environments, showing the practical benefits of avoiding code duplication in Terraform adopting DRY practices.
By integrating Terragrunt into your workflow, you can streamline your infrastructure management, making your codebase cleaner, more organised, and easier to maintain over the long term.
Ready to use Terragrunt for Cleaner Infrastructure Code?
Contact our experts today! Let’s chart a roadmap for seamless Terragrunt adoption for Google Cloud.