Rapid and constantly-evolving software development cycles have increased the need for reliable and fast infrastructure changes. Thus manually carrying out infrastructure changes has become an unscalable process – which is what Infrastructure as Code (IaC) tools are here to solve. They enable teams to codify their infrastructure configurations and integrate them directly into their CI/CD pipelines.
IaC has allowed developers to create version-controlled infrastructure configurations that are easily scalable and manageable. The codification enables them to easily standardize their infrastructure configurations, facilitating seamless rollbacks while increasing the overall observability of the infrastructure.
Terraform is one of the leading platform-agnostic open-source Infrastructure as Code tools. It lets developers create infrastructure configurations for major cloud platforms like AWS, Azure, GCP, and IBM to specific tools and services like Cloudflare, Elastic stack, and GitLab.
In this post, we will look at Terraform modules and how they can help teams improve their infrastructure configurations.
What are Terraform modules, and why use them?
In many instances, you have to define the same configuration multiple times when creating infrastructure configurations or providing them across environments. Repeating the same code block is inefficient and can easily lead to mistakes.
Terraform Modules address this issue by providing predefined resource structures. Think of modules as a collection of grouped resources, including variables and outputs. Users can simply call the module when they need to create a set of resources within a module other than defining them individually in the configuration. Using modules is the primary way to package and reuse resource configurations.
Modules in Terraform are a collection of .tf files stored in a separate directory within the overall configuration. All resources within a module are in the scope of that module. So the module must be explicitly declared if the user requires information about the resources created by a module. This is done by declaring an output on the module that exposes the relevant information, allowing that output to be referred outside the module.
4 Types of Terraform Modules
Terraform lets you utilize prebuilt modules available through the Terraform registry or create custom modules to suit their needs. There are thousands of free modules in the Terraform registry that cater to different providers and use cases. But there are three primary types of modules in Terraform that you are likely to encounter:
- Root Module
- Child Module
- Published Modules
1. Root Module
As the name implies, this module is the root of any configuration. Every Terraform configuration consists of the root module as the main directory that works with the .tf files. You can call any number of child modules or published modules from the root module.
Calling a Module from the Root Module
# Call the server module
module "server-module" {
source = "modules/server-module"
instance_name = "test-web-server"
instance_type = "t3a.small"
subnet_id = "sub-00001"
vpc_security_group_ids = ["sg-00001"]
}
The above code block calls a “server-module,” which is stored locally and passes the required configuration options to create the ec2 instance.
2. Child Module
Any module that can be called by another module (usually the Root module) is considered a child module. A child module can be any module that originates from different locations, including;
- Local modules defined in the local Terraform configuration.
- The Terraform registry which stores publicly available modules that can be used by any user in their configurations.
- Git repository consisting of the module. You can use tags or branch names to select a specific version of a module when calling a module from a git repository.
- Generic mercurial repository.
- HTTP URL pointing to a zip archive with the module.
- Cloud Storage like Amazon S3 or Google Cloud Storage buckets
3. Sample Child Module (Local Module)
Below is the configuration for the local module “server-module” referred to in the earlier example of the Root module. At a minimum, it consists of three files: the variables, output, and the config (main.tf).
Local Module Structure
As you can see, the root directory of the configuration is the “tf-module-example” folder which is the root of the configuration. Therefore, the “main.tf” file in the directory can be considered the Root Module. The configurations defined within the modules folder “server-module” and “storage-module” are the child modules of this configuration.
Local Module Code Sample
This module will create an ec2 instance in an AWS environment. The variable file defines the variables you can define to change the configuration when calling the module. In the meantime, the output file defines what output will be provided when the resource is created. This output can be queried outside of the module.
main.tf
# Creating a AWS EC2 Instance
resource "aws_instance" "server-instance" {
# Define number of instance
instance_count = var.number_of_instances
# Instance Configuration
ami = var.ami
instance_type = var.instance_type
subnet_id = var.subnet_id
vpc_security_group_ids = var.security_group
# Instance Tagsid
tags = {
Name = "${var.instance_name}"
}
}
variables.tf
# Server Module Variables
variable "number_of_instances" {
description = "Number of Instances to Create"
type = number
default = 1
}
variable "instance_name" {
description = "Instance Name"
}
variable "ami" {
description = "AMI ID"
default = "ami-xxxx"
}
variable "instance_type" {
description = "Instance Type"
}
variable "subnet_id" {
description = "Subnet ID"
}
variable "security_group" {
description = "Security Group"
type = list(any)
}
output.tf
# Server Module Output
output "server_id" {
description = "Server ID"
value = aws_instance.server-instance.id
}
4. Published Modules
Published Modules are modules pushed to a private or public repository. Terraform registry is the primary public repository. It hosts freely-accessible modules that can be used by anyone within their configurations. Terraform will automatically download the necessary modules from the registry when the appropriate source and version are defined in the module block.
You will need to create custom modules at an organizational level and only share them within the organization. Services like Terraform Cloud and Terraform Enterprise provide businesses with private module registries that they can use to share modules internally within the organization.
Contributors are free to create modules and publish them in any registry. Terraform welcomes modules from its community to its public Terraform registry that addresses various use cases. You can simply go to the Terraform registry and upload your module if the requirements for publishing a module are met. Then these modules will be accessible to the wider Terraform community, and users may call these public modules from their configurations. Thus, these modules can be categorized as child modules even though they are considered a different category of modules.
Calling a Published Module (AWS Lambda)
module "lambda_function" {
# Point to the Registry
source = "terraform-aws-modules/lambda/aws"
version = "2.35.1"
# Module Options
function_name = "test-lambda-function"
description = "Published Module Example"
handler = "index.lambda_handler"
runtime = "python3.9"
source_path = "../src/lambda-function"
tags = {
Name = "test-lambda-function"
Env = "Production"
}
}
The above configuration will utilize the official AWS lambda module hosted in the Terraform Registry.
Module at Will
Terraform modules provide an effective way to package and create reusable resource configurations. However, it does not mean that all configurations should be modularized. Modules should only be used when there is a need to create repeatable configurations that will be implemented in multiple locations of a Terraform configuration.
Furthermore, anyone can create published modules, so you can create custom modules to facilitate any configuration requirement in your environments. Yet, you should also consider infrastructure security when using IaC tools. This is where an IaC security tool like Spectral can streamline the incorporation of best security practices into your infrastructure configuration files and instances.