In this section, we will explore how to use modules in Terraform. Modules are a powerful way to organize and reuse code, making your Terraform configurations more manageable and scalable.

Key Concepts

  1. Module Basics: Understand what a module is and how it is structured.
  2. Calling a Module: Learn how to call a module from your Terraform configuration.
  3. Module Inputs and Outputs: Understand how to pass variables to a module and retrieve outputs.
  4. Module Versioning: Learn how to manage different versions of a module.
  5. Best Practices: Explore best practices for using modules effectively.

Module Basics

A module in Terraform is a container for multiple resources that are used together. A module consists of the following files:

  • main.tf: Contains the primary configuration for the module.
  • variables.tf: Defines the input variables for the module.
  • outputs.tf: Defines the outputs of the module.

Example Module Structure

my-module/
├── main.tf
├── variables.tf
└── outputs.tf

Calling a Module

To use a module, you need to call it from your root configuration. This is done using the module block.

Example

Let's assume we have a module that creates an AWS S3 bucket. The module is located in a directory called s3-bucket.

s3-bucket/main.tf

resource "aws_s3_bucket" "bucket" {
  bucket = var.bucket_name
  acl    = var.acl
}

output "bucket_arn" {
  value = aws_s3_bucket.bucket.arn
}

s3-bucket/variables.tf

variable "bucket_name" {
  description = "The name of the S3 bucket"
  type        = string
}

variable "acl" {
  description = "The ACL for the S3 bucket"
  type        = string
  default     = "private"
}

s3-bucket/outputs.tf

output "bucket_arn" {
  description = "The ARN of the S3 bucket"
  value       = aws_s3_bucket.bucket.arn
}

To call this module from your root configuration:

main.tf

provider "aws" {
  region = "us-west-2"
}

module "s3_bucket" {
  source      = "./s3-bucket"
  bucket_name = "my-unique-bucket-name"
  acl         = "private"
}

output "bucket_arn" {
  value = module.s3_bucket.bucket_arn
}

Module Inputs and Outputs

Inputs

Modules can accept input variables, which are defined in the variables.tf file. These variables can be passed when calling the module.

Outputs

Modules can also produce outputs, which are defined in the outputs.tf file. These outputs can be accessed using the module.<MODULE_NAME>.<OUTPUT_NAME> syntax.

Example

In the example above, the s3-bucket module accepts two input variables: bucket_name and acl. It produces one output: bucket_arn.

Module Versioning

When using modules from a remote source, such as the Terraform Registry, it's important to manage versions to ensure stability and predictability.

Example

To use a specific version of a module from the Terraform Registry:

module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "2.21.0"

  name = "my-vpc"
  cidr = "10.0.0.0/16"
  azs  = ["us-west-1a", "us-west-1b", "us-west-1c"]
}

Best Practices

  1. Use Descriptive Names: Name your modules and variables descriptively to make your configurations easier to understand.
  2. Version Control: Always specify a version when using remote modules to avoid unexpected changes.
  3. Documentation: Document your modules, including inputs, outputs, and usage examples.
  4. Reusability: Design modules to be reusable across different projects and environments.

Practical Exercise

Exercise

  1. Create a module that provisions an AWS EC2 instance.
  2. The module should accept the following inputs:
    • instance_type: The type of the EC2 instance.
    • ami_id: The ID of the AMI to use.
  3. The module should output the instance ID.

Solution

ec2-instance/main.tf

resource "aws_instance" "instance" {
  ami           = var.ami_id
  instance_type = var.instance_type
}

output "instance_id" {
  value = aws_instance.instance.id
}

ec2-instance/variables.tf

variable "instance_type" {
  description = "The type of the EC2 instance"
  type        = string
}

variable "ami_id" {
  description = "The ID of the AMI to use"
  type        = string
}

ec2-instance/outputs.tf

output "instance_id" {
  description = "The ID of the EC2 instance"
  value       = aws_instance.instance.id
}

main.tf

provider "aws" {
  region = "us-west-2"
}

module "ec2_instance" {
  source        = "./ec2-instance"
  instance_type = "t2.micro"
  ami_id        = "ami-0c55b159cbfafe1f0"
}

output "instance_id" {
  value = module.ec2_instance.instance_id
}

Conclusion

In this section, we learned how to use modules in Terraform to organize and reuse code. We covered the basics of module structure, how to call a module, manage inputs and outputs, and best practices for using modules effectively. By mastering modules, you can create more modular, maintainable, and scalable Terraform configurations.

© Copyright 2024. All rights reserved