Introduction to Terraform Modules

Part 1: Smart Infrastructure Management


In the dynamic world of cloud infrastructure management, efficiency and consistency are paramount. Terraform, an open-source infrastructure as code software tool, has emerged as a game-changer, empowering developers and system administrators to automate the provisioning of infrastructure. At the heart of Terraform’s power and flexibility are Terraform Modules – the building blocks that make managing large-scale, complex systems more manageable and repeatable.

Terraform Modules enable users to encapsulate and reuse code, fostering a more organized and modular approach to infrastructure deployment. These modules, akin to functions in traditional programming languages, allow for the packaging of a collection of resources and configurations. The benefit? A significant reduction in code duplication, easier maintenance, and the ability to share and reuse codebases across different projects and teams.

As we delve deeper into the world of Terraform Modules, we’ll explore their structure, how to use them effectively, and best practices to optimize their potential. Whether you’re a seasoned Terraform veteran or just starting out, understanding modules is key to mastering efficient infrastructure as code.

What are Terraform Modules?

At their core, Terraform Modules are containers for multiple resources that are used together. A module can include resources such as virtual machines, network settings, and more. The beauty of a module lies in its reusability – it’s a way to package configurations so you can reuse them in different parts of your infrastructure or even in different projects.

A typical Terraform Module comprises several files:

  • This file contains the main set of configuration code for the module.
  • Here, you define variables that your module will use.
  • This file defines outputs that your module may return.
  • Although not mandatory, it’s a best practice to include a README file to document the purpose and usage of your module.

Module Sources

Modules can be sourced from a variety of locations. You can use local paths, or you can source them from version control systems like Git, or even from the Terraform Registry – a public repository of modules created by the Terraform community.

Anatomy of a Terraform Module

A Terraform Module for Azure might include the following components:

  • Input Variables: Define parameters that can be customized each time the module is used. For example, the size of a virtual machine or the name of a resource group in Azure.
  • Resources: The Azure resources that will be created or managed. This could be anything from an Azure Blob Storage to a complete Virtual Network setup.
  • Output Values: These are the outputs that the module will return, such as the public IP of a deployed Azure VM or the endpoint of a storage account.

Example: Azure Virtual Network Module

Let’s illustrate with a simple example of a Terraform Module that creates a Virtual Network in Azure:

module "azure_vnet" {
  source = "./modules/vnet"

  vnet_name = "myVnet"
  address_space = [""]
  subnet_prefixes = [""]
  subnet_names = ["Subnet1"]

  resource_group_name = var.resource_group_name
  location = var.location

In this example, the module azure_vnet is defined to create a Virtual Network in Azure. The module takes in variables like vnet_name, address_space, subnet_prefixes, resource_group_name, and location to create a customized network. This allows for easy replication of network configurations across different environments or projects.

Utilizing Terraform Modules for Azure

The use of Terraform Modules is pivotal in scaling and managing Azure resources efficiently. Here, we will discuss how to implement these modules in your Terraform configuration, emphasizing the ease of use and flexibility they offer.

Step-by-Step Usage

  1. Module Source Identification: Determine whether to use a local module (created and stored within your project) or a remote module (stored in a Terraform Registry or a version control system).
  2. Module Integration: Incorporate the module into your main Terraform configuration file. For instance, to use an Azure Virtual Machine module, you would specify the module source and pass the required input variables.
module "azure_vm" {
  source = "Azure/vm/azurerm"
  version = "2.0.0"

  vm_name = "myAzureVM"
  resource_group_name =
  location = azurerm_resource_group.rg.location
  // ... other necessary variables
  1. Initialization: Run terraform init to initialize the configuration. This step downloads and installs the specified modules.
  2. Execution: Apply your configuration with terraform apply. Terraform will then provision the Azure resources as defined in your modules.

The file in the root directory is the starting point of your Terraform configuration. It defines the provider, initializes modules, and sets up any required resources that aren’t covered by modules. Here’s an enriched example:


# Configure the Azure Provider
provider "azurerm" {
  features {}
  version = "=2.46.0"

# Initialize Resource Group Module
module "resource_group" {
  source = "./modules/resource_group"
  location = "East US"
  rg_name = "myResourceGroup"

# Initialize Networking Module
module "networking" {
  source = "./modules/networking"

  resource_group_name =
  vnet_name = "myVNet"
  address_space = [""]
  subnet_names = ["subnet1"]
  subnet_prefixes = [""]

# Initialize Compute Module
module "compute" {
  source = "./modules/compute"

  resource_group_name =
  vm_name = "myVM"
  location = module.resource_group.location
  // Additional configurations

# Initialize Storage Module
module "storage" {
  source = "./modules/storage"

  resource_group_name =
  storage_account_name = "mystorageaccount"
  location = module.resource_group.location
  // Additional configurations

The resource_group module creates a resource group in Azure. It’s a fundamental module as other modules like networking, compute, and storage will reference the resource group created here.

# modules/resource_group/

resource "azurerm_resource_group" "rg" {
  name     = var.rg_name
  location = var.location

# modules/resource_group/

variable "rg_name" {
  description = "Name of the resource group"
  type        = string

variable "location" {
  description = "Azure region to deploy the resources"
  type        = string

# modules/resource_group/

output "name" {
  value =

Best Practices in Terraform: Directory Structure with Azure CAF

Organizing for Clarity and Scalability

A well-organized directory structure is crucial for managing Terraform configurations, especially when dealing with complex environments like those managed with the Azure CAF provider. This structure not only enhances readability but also eases maintenance and collaboration.

Suggested Directory Structure

Here’s an example of a recommended directory structure when using Terraform with the Azure CAF provider:

└── modules/
    ├── networking/
    │   ├──
    │   ├──
    │   └──
    ├── compute/
    │   ├──
    │   ├──
    │   └──
    └── storage/
  • Root Directory: Contains the main Terraform configuration files (,, and It’s where you define the Azure provider and specify the version, backend configuration, and variables that apply to all modules.
  • Modules Directory: This is a subdirectory within your Terraform project. It contains different modules for specific Azure resources, like networking, compute, and storage.
    • Each module (e.g., networking, compute, storage) has its own set of Terraform files:
      • Contains the resource definitions and data sources for that module.
      • Defines the variables used in the module.
      • Specifies the output values that the module will return.

Example: Networking Module

Let’s take a closer look at the networking module as an example. This module could be responsible for setting up the network infrastructure in Azure, including virtual networks, subnets, and network security groups.

  • Defines Azure network resources like virtual networks (VNet), subnets, and network security groups.
  • Includes definitions for variables such as the address space for the VNet, subnet details, etc.
  • Outputs important information like the VNet ID or subnet IDs.

Leveraging the Azure CAF Provider

The Azure CAF provider offers an extensive set of modules specifically designed to implement the Cloud Adoption Framework best practices. By organizing these modules within the suggested directory structure, you can create a scalable and maintainable Terraform configuration that aligns with Azure’s best practices.


Bringing It All Together

Our exploration of Terraform Modules reveals how they serve as a cornerstone in managing Azure cloud infrastructure efficiently and effectively. From creating reusable components to organizing complex configurations, Terraform Modules offer a path to streamlined infrastructure as code.

Key Takeaways

  • Modularity and Reusability: Terraform Modules allow for the encapsulation of complex infrastructure setups, making them reusable across various projects and environments.
  • Organized Structure: A well-planned directory structure, as exemplified with the Azure CAF provider, enhances readability, maintainability, and collaboration.
  • Scalable Configurations: Modules enable scalable and manageable configurations, crucial for large-scale Azure deployments.
  • Reduced Complexity: By abstracting the infrastructure components into modules, we significantly reduce the complexity of our Terraform configurations.

Final Thoughts

As the cloud landscape continues to evolve, so does the need for tools and practices that can keep up with the pace of change. Terraform Modules stand out as a vital asset in this regard, especially when paired with Azure. They provide not just a means to manage infrastructure but a way to do so that is efficient, scalable, and sustainable.

Whether you’re managing a small project or an enterprise-level infrastructure, the principles of Terraform Modules remain the same. Embrace these practices, and you’ll find yourself navigating the complexities of cloud infrastructure with greater ease and confidence.


Spread the word. Share this post!

Leave Comment