- Definition: A Terraform module is a container for multiple resources that are used together. Modules help organize, reuse, and manage your Terraform code efficiently.
-
Structure:
-
Root Module: The directory where
terraform init
is run. - Child Module: Any module called by another module (e.g., a reusable VPC or EC2 setup).
-
Root Module: The directory where
Example:
A reusable VPC module might create subnets, route tables, and an Internet Gateway.
Why Use Modules?
- Reusability: Share modules across multiple projects.
- Maintainability: Separate infrastructure into logical, manageable pieces.
- Consistency: Apply standardized configurations across environments (e.g., dev, staging, production).
- Simplified Management: Focus on high-level architecture by abstracting complex configurations.
Creating a Terraform Module
Example: VPC Module
Module Directory Structure:
modules/
└── vpc/
├── main.tf
├── variables.tf
├── outputs.tf
main.tf
(VPC resources):
`
resource "aws_vpc" "example" {
cidr_block = var.cidr_block
}
resource "aws_subnet" "public" {
count = var.public_subnet_count
cidr_block = element(var.public_subnet_cidrs, count.index)
availability_zone = element(var.availability_zones, count.index)
vpc_id = aws_vpc.example.id
}
`
variables.tf
(Input Variables):
variable "cidr_block" {}
variable "public_subnet_cidrs" {
type = list(string)
}
variable "public_subnet_count" {}
variable "availability_zones" {}
outputs.tf
(Outputs):
`
output "vpc_id" {
value = aws_vpc.example.id
}
output "public_subnets" {
value = aws_subnet.public[*].id
}
`
-
Using the Module:
In your root module:
module "vpc" { source = "./modules/vpc" cidr_block = "10.0.0.0/16" public_subnet_cidrs = ["10.0.1.0/24", "10.0.2.0/24"] public_subnet_count = 2 availability_zones = ["us-east-1a", "us-east-1b"] }
Terraform Best Practices
-
Organize Code into Modules:
- Group related resources into modules (e.g., network, database, compute).
-
Use Remote Backends:
- Store Terraform state in remote backends like S3 with state locking via DynamoDB to avoid conflicts.
-
Use Version Control:
- Pin versions for the Terraform provider and modules:
terraform { required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } } }
- Pin versions for the Terraform provider and modules:
-
Implement Input Validation:
- Use
validation
blocks in variables:variable "environment" { type = string validation { condition = var.environment in ["dev", "staging", "prod"] error_message = "Invalid environment. Choose dev, staging, or prod." } }
- Use
-
Minimize Hardcoding:
- Use variables and outputs to increase flexibility and portability.
-
Keep State Secure:
- Encrypt your state file when using remote backends.
-
Write Meaningful Outputs:
- Provide critical resource IDs or URLs to simplify downstream usage.
-
Use Terraform Workspaces:
- Manage multiple environments (e.g., dev, staging, prod):
terraform workspace new staging terraform workspace select staging
-
Adopt a CI/CD Pipeline:
- Automate plan and apply actions while enforcing code reviews and approvals.
Happy Learning !!!
Top comments (0)