Estimated reading time: 11 minutes
Last updated on October 25th, 2024 at 02:55 pm
Table of Contents
Introduction to Terraform Modules
What are Terraform Modules?
Terraform modules are reusable and shareable code-based, which can be versioned and packaged to encapsulate the infrastructure.
Big Single ( main.tf ) = Multiple Small ( modules.tf )
You can break a big chunk of your infrastructure into smaller and resellable code units that you can use across your projects and different parts of your Terraform configuration files.
Why do you need a terraform module? To answer this question let’s check the benefits of using the Terraform Module
Benefits of Using Terraform Modules
- Code Reusability: Write the code once and use it multiple times with modules.
- Organization: Break down complex code into smaller but manageable modules.
- Consistency: Consistency across the projects. Deploy similar infrastructure in the same way.
In summary, using the Terraform modules helps to break the complex code into reusable code that deploys consistently across the environment.
So far we understand the Terraform modules and the benefits of using them. Let’s explore the importance of data sharing and Terraform use output from another module.
Importance of Sharing Data Between Modules
When you split the Terraform module into smaller code, sharing the data between the modules is crucial for the infrastructure. Sharing the data across the module enables you to utilize Terraform output from another module effectively.
For example, the network module outputs the subnet IDs, which later can be passed and utilized inside the compote module. Subnet IDs can be used to create the computer instances.
DevOps Efficiency Hacks in Your Inbox! 📩
Stop wasting time searching. Get weekly tips & tutorials to streamline your DevOps workflow.
Understanding Terraform Outputs
What is a Terraform Output?
Terraform output is exposed values that can be derived from the remote infrastructure or other modules. In simple terms, when you run the terraform plan
or terraform apply
, it checks the remote state and outputs the values from it.
Later you can use the value from Terraform output in another module. By default, Terraform doesn’t output all the values, you need to define the output
block to display the values you want.
Let’s check how to output certain values with Terraform modules.
How to Define Outputs in Terraform Modules
To define an output in the Terraform module, you can use the output
block:
output "subnet_id" {
value = aws_subnet.production_subnet.id
}
Best Practices for Managing Terraform Modules Outputs
1. Meaningful Naming
Rather than using random names, make the output easily understandable. Using descriptive names makes your Terraform configuration more readable and maintainable. Meaningful names clearly define what they represent without checking the module code.
Instead of using the name like id
, use the name like vpc_id
output "vpc_id" {
value = aws_vpc.production.id
description = "The ID of the Prod VPC"
}
2. Only Expose Required Values
Minimize the output and only output the required and non-sensitive values to maintain a secure and clear Terraform configuration.
Always review and adjust the output values to avoid accidental data leaks and security incidents.
# Avoid exposing internal resources unless necessary
# output "app_s3_bucket_arn" {
# value = aws_s3_bucket.app.arn
# }
output "s3_bucket_name" {
value = aws_s3_bucket.app.name
description = "The name of the S3 bucket used for application storage"
}
3. Module Documentation
Write the documentation within the output blocks to help users understand the meaning. Comprehensive documentation is important when multiple team members work with the same Terraform configuration.
output "database_endpoint" {
value = aws_db_instance.production.endpoint
description = "The endpoint of the primary database used for application connections"
}
Terraform Use Output from Another Module: Step-by-Step
Before you start, I assume you already have the Terraform installed on your system. If not you can download it from the official Terraform Website.
Let’s start with initializing the Terraform project by running the terraform init
. The process will set the necessary backend configuration and download the required providers
terraform init
Defining Outputs in the Source Module
Let’s define the output in your source code for the simple network module that outputs the subnet ID:
# modules/network/main.tf
resource "aws_vpc" "dev_vpc" {
cidr_block = "10.0.0.0/16"
}
resource "aws_subnet" "dev_subnet" {
vpc_id = aws_vpc.dev_vpc.id
cidr_block = "10.0.1.0/24"
}
output "subnet_id" {
value = aws_subnet.dev_subnet.id
}
The above code snippet shows the output subnet_id
for the network module.
Mistake to Avoid
- Undefined Resource: Make sure the resource you are referencing is defined.
- Incorrect Output: Use consistent and clear output names.
Terraform Use Output from Another Module
To use the output from another module, you need to take references. Terraform Use Output from another module is straightforward:
# modules/network/main.tf
module "network" {
source = "./modules/network"
}
# modules/compute/main.tf
module "compute" {
source = "./modules/compute"
subnet_id = module.network.subnet_id
}
To reference an output from another module, use the following syntax:
module.<MODULE_NAME>.<OUTPUT_NAME>.
Let’s check the real example by using the subnet_id
with compute module:
# modules/compute/main.tf
resource "aws_instance" "example" {
ami = "ami-0c55b129cbfafe1f0"
instance_type = "t2.micro"
subnet_id = var.subnet_id
}
variable "subnet_id" {
description = "The ID of the subnet to deploy instances into"
type = string
}
Level Up Your DevOps Skills! 📈
Get Weekly Tips, Tutorials & Master the Latest Trends – Subscribe Now!
Terraform Use Output from Another Module: Advanced Usage
1. Chain Multiple Module Outputs
You can chain output by passing one output from another module as input.
module "network" {
source = "./modules/network"
}
module "database" {
source = "./modules/database"
subnet_id = module.network.subnet_id
}
module "app" {
source = "./modules/app"
subnet_id = module.network.subnet_id
db_id = module.database.db_id
}
2. Conditional Logic with Module Outputs
You can manage different environments such as staging
, production
with parameterized modules
variable "environment" {
description = "The deployment environment (staging, production)"
type = string
}
output "environment" {
value = var.environment
}
Terraform Use Output from Another Module: Real-World Example
1. Networking Infrastructure
Setting up the networking infrastructure is an essential step for running resources inside them and for that, you need to share VPC and subnet IDs across the modules. The Terraform Use Output from Another Module helps to achieve it
Let’s define the network module with VPC and Subnet.
# modules/network/main.tf
resource "aws_vpc" "vpc" {
cidr_block = "10.0.0.0/16"
}
resource "aws_subnet" "public" {
vpc_id = aws_vpc.vpc.id
cidr_block = "10.0.1.0/24"
}
resource "aws_subnet" "private" {
vpc_id = aws_vpc.vpc.id
cidr_block = "10.0.2.0/24"
}
output "vpc_id" {
value = aws_vpc.vpc.id
description = "The ID of the VPC"
}
output "public_subnet_id" {
value = aws_subnet.public.id
description = "The ID of the public subnet"
}
output "private_subnet_id" {
value = aws_subnet.private.id
description = "The ID of the private subnet"
}
Now use the VPC and subnet IDs from the network modules for compute instance
# main.tf
module "network" {
source = "./modules/network"
}
module "compute" {
source = "./modules/compute"
vpc_id = module.network.vpc_id
subnet_id = module.network.public_subnet_id
}
# modules/compute/main.tf
variable "vpc_id" {
description = "The ID of the VPC to deploy instances into"
type = string
}
variable "subnet_id" {
description = "The ID of the subnet to deploy instances into"
type = string
}
resource "aws_instance" "example" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
subnet_id = var.subnet_id
}
2. Multi-Region Deployment with Terraform
Deploying the infrastructure across multiple regions with AWS can be a complicated setup but Terraform Use Output from Another Module helps to manage and define resources efficiently.
Let’s define the network module as an essential step
# modules/network/main.tf
variable "region" {
description = "The AWS region to deploy the VPC"
type = string
}
provider "aws" {
region = var.region
}
resource "aws_vpc" "vpc" {
cidr_block = "10.0.0.0/16"
}
output "vpc_id" {
value = aws_vpc.vpc.id
description = "The ID of the VPC"
}
Now define the different regions and pass the VPC IDs
# main.tf
module "network_us_east_1" {
source = "./modules/network"
region = "us-east-1"
}
module "network_us_west_2" {
source = "./modules/network"
region = "us-west-2"
}
module "compute_us_east_1" {
source = "./modules/compute"
vpc_id = module.network_us_east_1.vpc_id
}
module "compute_us_west_2" {
source = "./modules/compute"
vpc_id = module.network_us_west_2.vpc_id
}
3. Microservices Architecture
Microservice architecture deployment can be complex, the deployment is to be carried out in a specific subnet for service isolation and enhanced security. Terraform Use Output from Another Module helps to coordinate the microservices deployment.
Let’s create the first network and different subnets for services
# modules/network/main.tf
resource "aws_vpc" "vpc" {
cidr_block = "10.0.0.0/16"
}
resource "aws_subnet" "service_backend" {
vpc_id = aws_vpc.vpc.id
cidr_block = "10.0.1.0/24"
}
resource "aws_subnet" "service_frontend" {
vpc_id = aws_vpc.vpc.id
cidr_block = "10.0.2.0/24"
}
output "vpc_id" {
value = aws_vpc.vpc.id
description = "The ID of the VPC"
}
output "service_backend_subnet_id" {
value = aws_subnet.service_backend.id
description = "The ID of the subnet for Service Backend"
}
output "service_frontend_subnet_id" {
value = aws_subnet.service_frontend.id
description = "The ID of the subnet for Service Frontend"
}
Now within the service module, you can use the Terraform output
# main.tf
module "network" {
source = "./modules/network"
}
module "service_backend" {
source = "./modules/service_a"
subnet_id = module.network.service_backend_subnet_id
}
module "service_frontend" {
source = "./modules/service_b"
subnet_id = module.network.service_frontend_subnet_id
}
# modules/service_a/main.tf
variable "subnet_id" {
description = "The ID of the subnet to deploy Service A into"
type = string
}
resource "aws_instance" "service_backend_instance" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
subnet_id = var.subnet_id
}
# modules/service_b/main.tf
variable "subnet_id" {
description = "The ID of the subnet to deploy Service B into"
type = string
}
resource "aws_instance" "service_frontend_instance" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
subnet_id = var.subnet_id
}
You can effectively manage the complex Terraform configuration such as modular architecture, multi-region deployment, and microservice infrastructure.
Conclusion
Key Points
- Terraform modules enhance reusability and code organization
- Output blocks are crucial for data sharing between modules
- Properly define and reference outputs in configuration.
Tips for Effective Module Output Management
- Use descriptive and meaningful names.
- Only expose necessary values. Excessive output can slow down Terraform runs.
- Documents your outputs.
Terraform Use Output from Another Module: FAQs
Can I use outputs from multiple modules simultaneously?
Yes, you can use outputs from multiple modules by referencing each module’s output block.
How do I debug issues with module outputs?
Use terraform plan
to see how Terraform understands your configuration. Check the definitions and references of your output
What are the limitations of using module outputs in Terraform?
Only supported data types and expressions can be used with the Terraform output. Ensure outputs are simple and well-defined.