The Essential List of Terraform Modules and Their Purposes

By Eyal Katz March 31, 2022

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?

Terraform is Infrastructure as Code

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

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.

Related articles

top 10 ci/cd automation tools

Top 10 CI/CD Automation Tools

Software teams have focused on agility since the world embraced Mark Zuckerberg’s motto to “move fast and break things.” But many still lack the confidence or

3 Steps To Remain PCI Compliant with your AWS Configuration

3 Steps To Remain PCI Compliant with your AWS Configuration

Becoming and staying PCI compliant both take a lot of work. Developers are often already swamped with an endless list of tasks, and adding PCI compliance

Web Application Security: What to Consider for 2023

Web Application Security: What to Consider for 2023

Security is the biggest threat facing organizations that strive for faster software delivery. Organizations are witnessing increasing attacks due to application code gaps and security weaknesses.

Stop leaks at the source!