Introduction to Terraform Modules: The Power of Reusable Code

Efficiency and maintainability are crucial in infrastructure as code (IaC). Terraform, an open-source tool by HashiCorp, has emerged as a leader in this domain, enabling developers to define and provision infrastructure using a high-level configuration language. At the heart of Terraform’s power lies its ability to create reusable modules, allowing you to encapsulate and share your infrastructure components across projects. This guide explores mastering Terraform modules, focusing on building reusable infrastructure components that streamline operations and reduce redundancy.

Building Your First Terraform Module: An AWS SQS Example

To demonstrate the power of Terraform modules, we’ll walk through creating a simple yet practical module that provisions an AWS Simple Queue Service (SQS) queue. This example will cover the fundamental aspects of Terraform modules, from initializing the module structure to defining inputs, data sources, and outputs.

2.1 Initializing the Module Structure

The first step in creating a Terraform module is to set up a directory structure. A typical module structure includes the following files:

  • main.tf: Contains the core resources of the module.
  • variables.tf: Defines the input variables for the module.
  • outputs.tf: Specifies the outputs that the module will return.
  • datasources.tf: (Optional) Used to define any data sources the module may need.

For our SQS example, create a new directory called terraform-aws-sqs-module and make the main.tf, variables.tf, and outputs.tf files within it.

2.2 Defining Input Variables (variables.tf)

Input variables allow your module to be flexible and reusable across different environments. In the variables.tf file, define the variables that your module will accept. For our SQS queue, we might define variables like queue_name, delay_seconds, and visibility_timeout.

variable “queue_name” {

  description = “The name of the SQS queue”

  type        = string

}

variable “delay_seconds” {

  description = “The delay in seconds for the queue”

  type        = number

  default     = 0

}

variable “visibility_timeout” {

  description = “The visibility timeout for the queue”

  type        = number

  default     = 30

}

2.3 Crafting Data Sources (datasources.tf)

Data sources allow you to query existing infrastructure resources. For our SQS module, we may not need a data source, but if we were integrating with existing infrastructure, this file would come into play. For example, if you wanted to reference an existing VPC or IAM role, you’d define that in datasources.tf.

2.4 Constructing the SQS Queue (main.tf)

In the main.tf file, you’ll define the AWS SQS resource using the earlier variables. Here’s how you might set up the SQS queue:

resource “aws_sqs_queue” “this” {

  name                      = var.queue_name

  delay_seconds             = var.delay_seconds

  visibility_timeout_seconds = var.visibility_timeout

}

2.5 Declaring Module Outputs (outputs.tf)

Outputs allow other Terraform configurations to access the values produced by your module. In outputs.tf, you might return the SQS queue’s URL or ARN:

output “queue_url” {

  description = “The URL of the created SQS queue”

  value       = aws_sqs_queue.this.id

}

output “queue_arn” {

  description = “The ARN of the created SQS queue”

  value       = aws_sqs_queue.this.arn

}

Utilizing Terraform Modules: Internal and External Referencing

Once you’ve built a module, you must understand how to reference it within your project and from external sources.

3.1 Internal Referencing: Within Your Project

You can easily reference a module internally by specifying its relative path. For example, if your module is located in a modules/sqs directory within your project, you’d reference it like this:

module “sqs_queue” {

  source = “./modules/sqs”

  queue_name = “my-queue”

  delay_seconds = 10

  visibility_timeout = 45

}

3.2 External Referencing: From GitHub Repositories

You can store your modules in a version-controlled repository like GitHub to make them available to others. You can reference such modules using the source attribute, pointing to the repository URL:

module “sqs_queue” {

  source  = “git::https://github.com/yourusername/terraform-aws-sqs-module.git”

  version = “v1.0.0”

  queue_name = “my-queue”

}

Versioning Your Public Terraform Modules for Stability

Versioning is crucial when sharing modules publicly to ensure stability and predictability. By tagging your Git repository with versions (e.g., v1.0.0), users of your module can lock their configuration to a specific version, avoiding breaking changes.

In your GitHub repository, tag a commit with a version number:

git tag v1.0.0

git push origin v1.0.0

Users can specify the version when they reference your module, ensuring their infrastructure remains consistent even as it evolves.

Conclusion: Mastering Terraform Modules for Streamlined Infrastructure

Terraform modules are a powerful way to encapsulate and share infrastructure code, making managing complex environments and promoting code reuse easier. By mastering the creation and usage of Terraform modules, you can build more maintainable, scalable, and reliable infrastructure. Whether you’re building internal modules for your team or sharing them with the broader community, understanding the best practices for module development and versioning will empower you to streamline your operations and deliver consistent results.

References

Best practices for using the Terraform AWS Provider

Understanding Terraform modules