Modules Overview

Using Terraform modules can help promote code reuse, reduce duplication of effort, and improve maintainability of infrastructure code.

A Terraform module is a package of Terraform configuration files that creates resources. In fact, any folder containing Terraform configuration files is technically a module. The key point is Terraform projects can be comprised of two types of module folders:

Root module this is the folder where your Terraform configuration files that declare what you want to do are kept. So this is the project folder that is specific to each deployed resource and contains providers, variables.

Reusable module this is the folder containing the resource configuration code. You call the reusable module from the root module.

In the following example, there are three reusable modules defining three resources in a folder called modules. In a seperate folder called projects there is a project00 folder which is divided up by environment, prod & stage, then the root module resources are divided to maintain good state file isolation. The main.tf file in each root module folder is configured to import the Terraform configuration from the reusable module.

This means that the prod & atage resources are created using the same reusable modules code. The differences, such as resource names, resources sizes (smaller compute for stage), target cloud landing zones (prod/stage AWS accounts) are all declared in the root module per project/environment/resource.

+---modules
|   \---virtual-machines
|   |       main.tf
|   |       outputs.tf
|   |       readme.md
|   |       variables.tf
|   \---mysql-database
|   |       main.tf
|   |       outputs.tf
|   |       README.md
|   |       variables.tf
|   \---load-balancer
|   |       main.tf
|   |       outputs.tf
|   |       README.md
|   |       variables.tf
|
+---projects
|   \---project00
|       \---prod
|           \---databases
|                \---mysql
|                |        main.tf
|                |        providers.tf
|                |        variables.tf
|                |        outputs.tf
|           \---services
|                \---virtual-machines
|                |        main.tf
|                |        providers.tf
|                |        variables.tf
|                |        outputs.tf
|                \---load-balancer
|                |        main.tf
|                |        providers.tf
|                |        variables.tf
|                |        outputs.tf
|       \---stage
|           \---databases
|                \---mysql
|                |        main.tf
|                |        providers.tf
|                |        variables.tf
|                |        outputs.tf
|           \---services
|                \---virtual-machines
|                |        main.tf
|                |        providers.tf
|                |        variables.tf
|                |        outputs.tf
|                \---load-balancer
|                |        main.tf
|                |        providers.tf
|                |        variables.tf
|                |        outputs.tf

Modules can be used to create abstractions and promote code reuse across projects and teams, allowing for more efficient infrastructure management. A Terraform module typically includes input variables, output values, and one or more resource definitions that can be configured and customized when the module is called.

Modules can be created and published to the Terraform Registry, which is a centralized repository of modules contributed by the Terraform community or you can maintain a module library as a simple folder directory and map the folder path in your Terraform configuration code when you need to call the module. You can also host the module in a VCS such as GitHub or BitBucket and take advantage of version tags to pin a module version a run-time which can be useful if your module code changes with further development but you rely on the previous version for your deployment.

Key benefits

Don’t Repeat Yourself

  • Allows code to be DRY
  • Build reusable components; for example a module for a VM and one for SQL servers.
  • Split up large environments into smaller components
  • Easier testing
  • Smaller changes reduce the risk
  • Re-use the same code in DEV and PROD

Module use case

This diagram demonstrates how module code deploys multiple resources, with changes only required at the run time in the configuration code. The configuration code for each environment calls the same module code repeatedly, resulting in no code copying/pasting as the module code is referenced from a repository. Aside from environment variables, each resource is also the same, meaning testing is enhanced.

image

Authenticating to GitHub

The Terraform API needs access to the GitHub repository to be able to download the module. A recommened approach is to use SSH authentication instead of username/password. This avoids the need to hardcode credentials which is bad practice for any system you design and operate.

For example, each operator of the Terraform code would require their own public/private key pair. Their public key is added to the GitHub repository. The operator adds their private key to ssh-agent on their workistation which will support the Terraform API when it needs to authenticate to GitHub to pull the reusable module code.

Setup ssh-agent on a Windows 10/11 system:

  1. Open a new Terminal as Administrator

  2. Make sure you have OpenSSH installed along with the OpenSSH Client

sc query ssh-agent
  1. Set the OpenSSH Authentication Agent service startup type to “Manual”
sc config ssh-agent start= demand
  1. Start the OpenSSH Authentication Agent service:
net start ssh-agent
  1. Open a new Terminal as Administrator.

  2. Add your private key to the agent

ssh-add C:\path\to\your\private\key
Last modified July 21, 2024: update (e2ae86c)