Modules Overview
Categories:
5 minute read
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.
Info
This example shows reusable modules residing as local folders in the same location as the root modules. It’s also possible to host reusable module code in a VCS such as GitHib or a module registry such as HashiCorp. You configure the root module to in effect download the reusable module code when your runterraform init
.+---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.
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.
INFO
ssh-agent
is a background program that runs on your local machine and manages your SSH keys. It handles private key operations without exposing the sensitive key material to other processes. The primary function of the ssh-agent
is to store your private keys in memory, decrypt them, and use them to authenticate your SSH connections securely.Setup ssh-agent
on a Windows 10/11 system:
Open a new Terminal as Administrator
Make sure you have OpenSSH installed along with the
OpenSSH Client
sc query ssh-agent
- Set the OpenSSH Authentication Agent service startup type to “Manual”
sc config ssh-agent start= demand
- Start the OpenSSH Authentication Agent service:
net start ssh-agent
Open a new Terminal as Administrator.
Add your private key to the agent
ssh-add C:\path\to\your\private\key