Best Practices for Terraform Modules: Clean, Reusable Infrastructure Code
Terraform modules to organize infrastructure code into reusable, self-contained units with clear inputs and outputs. Follow best practices like keeping modules small, using version control, and documenting inputs and outputs for easy maintenance and sharing.Syntax
A Terraform module is a folder with Terraform configuration files. It has variables.tf for inputs, outputs.tf for outputs, and main configuration files like main.tf. You call a module using the module block with a source and input variables.
- module block: Defines where to get the module and what inputs to pass.
- variables.tf: Declares inputs the module expects.
- outputs.tf: Declares outputs the module provides.
module "example_module" { source = "./modules/example" instance_count = 3 instance_type = "t2.micro" } // variables.tf inside module variable "instance_count" { type = number } variable "instance_type" { type = string } // outputs.tf inside module output "instance_ids" { value = aws_instance.example.*.id }
Example
This example shows a simple module that creates AWS EC2 instances. The root configuration calls the module with inputs. The module defines variables for instance count and type, creates instances, and outputs their IDs.
// Root configuration module "web_servers" { source = "./modules/ec2_instances" instance_count = 2 instance_type = "t3.micro" } // modules/ec2_instances/variables.tf variable "instance_count" { type = number } variable "instance_type" { type = string } // modules/ec2_instances/main.tf resource "aws_instance" "example" { count = var.instance_count ami = "ami-0c55b159cbfafe1f0" // Example AMI instance_type = var.instance_type } // modules/ec2_instances/outputs.tf output "instance_ids" { value = aws_instance.example.*.id }
Common Pitfalls
Common mistakes include making modules too large or complex, not documenting inputs and outputs, and hardcoding values inside modules. Avoid using relative paths that break when sharing modules. Also, do not mix resource creation and environment-specific settings in one module.
Always use version control and semantic versioning when publishing modules for reuse.
// Wrong: Hardcoding values inside module variable "instance_type" { default = "t2.micro" // Avoid hardcoding defaults that limit reuse } // Right: Require input without default or provide flexible defaults variable "instance_type" { type = string default = "t3.micro" }
Quick Reference
- Keep modules small and focused on one task.
- Use clear, descriptive variable names and document them.
- Define outputs for important values to share with root configurations.
- Use version control and semantic versioning for modules.
- Test modules independently before using them in projects.