This topic introduces Terraform modules.
What are Terraform modules?
Terraform modules are one of the key and basic unit in the Infrastructure as code (IaC) ecosystem of Terraform for organizing and reusing Terraform code. As the cloud infrastructure scales out, it becomes a great challenge to maintain and manage all infrastructure configurations in a single Terraform file. To facilitate reading and management, Terraform modules allow you to encapsulate infrastructure configurations into a reusable component that can be shared with other users. Modulization is the foundation for building maintainable, scalable, and standardized infrastructure code. It is suitable for cloud infrastructure management scenarios, especially for large-scale, multi-environment, and team collaboration.
A Terraform module is a collection of resources that can be regarded as the functions of the infrastructure code. Terraform modules provide an abstraction mechanism by defining input variables, output values, and resource configurations. This mechanism allows you to reuse complex infrastructure components in a simplified approach. It not only increases the code reuse rate and reduces the maintenance cost, but also promotes the implementation of standard and best practices within your organization.
Why Terraform modules?
When you use Terraform to manage Alibaba Cloud infrastructures, you may need to repeatedly deploy similar resources. For example, you may need to create multiple Elastic Compute Service (ECS) instances in a custom network and each ECS instance contains the following attributes:
Instance type (instance_type)
Disk specification (system_disk_category and data_disks)
Elastic IP Address (EIP)
Image ID
...
If you do not use Terraform modules, you may need to repeatedly write the same code:
resource "alicloud_instance" "web_server" {
instance_type = "ecs.g6.large"
system_disk_category = "cloud_essd"
security_groups = ["sg-12sfew2"]
instance_name = "web-server"
vswitch_id = "vsw-12345"
image_id = "ubuntu_18_04_64_20G_alibase_20190624.vhd"
}
resource "alicloud_eip_address" "web_server" {
bandwidth = "5"
internet_charge_type = "PayByBandwidth"
}
resource "alicloud_eip_association" "web_server" {
instance_id = alicloud_instance.web_server.id
allocation_id = alicloud_eip_address.web_server.id
}This method raises the following issues:
Duplicate code increases the maintenance difficulty.
Multiple modifications are required in cases of configuration updates.
User errors may be made.
Poor code readability.
However, a Terraform module is a collection of configuration files in the same directory. Terraform modules provide the following benefits:
Classify reusable code into the same category.
Manage code as a module.
Improve the code maintainability and reusability.
Terraform module types
Terraform provides two module types:
1. Root module
The root module is the main entrance for module configurations. It calls and organizes other modules.
# Root Module (main.tf)
# Note that if you want to publish the module or allow the module to be called by other modules,
#we recommend that you do not define the provider block in the current code block, but define the provider block when you call the module.
# In addition, use providers to pass the metadata.
provider "alicloud" {
region = "cn-hangzhou"
}
module "vpc" {
source = "./modules/vpc"
}
module "ecs" {
source = "./modules/ecs"
depends_on = [module.vpc]
}2. Child modules
Child modules are called by the root module or other modules. Child modules are designed for specific features and can be repeatedly reused.
# Child Module (modules/vpc/main.tf)
resource "alicloud_vpc" "vpc" {
vpc_name = var.vpc_name
cidr_block = var.vpc_cidr
}
# Call the module in the root module
module "vpc" {
source = "./modules/vpc"
vpc_name = "my-vpc"
vpc_cidr = "172.16.0.0/16"
}Example: Create a module
This example demonstrate how to create module for Alibaba Cloud resources. The module contains the network and server modules.
4.1 Directory structure
In this example, the following directory structure is used:
.
├── main.tf
├── modules
├── network
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
└── server
├── main.tf
├── variables.tf
└── outputs.tf4.2 Sample network module
# modules/network/main.tf
resource "alicloud_vpc" "vpc" {
vpc_name = var.vpc_name
cidr_block = var.vpc_cidr
}
resource "alicloud_vswitch" "vsw" {
vswitch_name = var.vswitch_name
vpc_id = alicloud_vpc.vpc.id
cidr_block = var.vswitch_cidr
zone_id = var.zone_id
}
resource "alicloud_security_group" "default" {
security_group_name = var.security_group_name
vpc_id = alicloud_vpc.vpc.id
}# modules/network/variables.tf
variable "vpc_name" {
type = string
description = "Name of the VPC"
default = "terraform-vpc"
}
variable "vpc_cidr" {
type = string
description = "CIDR block for the VPC"
default = "172.16.0.0/16"
}
variable "vswitch_name" {
type = string
description = "Name of the VSwitch"
default = "terraform-vswitch"
}
variable "vswitch_cidr" {
type = string
description = "CIDR block for the VSwitch"
default = "172.16.0.0/24"
}
variable "zone_id" {
type = string
description = "Zone ID for the VSwitch"
default = "cn-hangzhou-i" # Replace the value with the region ID that you use.
}
variable "security_group_name" {
type = string
description = "Name of the security group"
default = "terraform-security-group"
}# modules/network/outputs.tf
output "security_group_id" {
value = alicloud_security_group.default.id
description = "The ID of the security group"
}
output "vswitch_id" {
value = alicloud_vswitch.vsw.id
description = "The ID of the vswitch"
}
output "vpc_id" {
value = alicloud_vpc.vpc.id
description = "The ID of the VPC"
} 4.3 Sample server module
# modules/server/main.tf
resource "alicloud_instance" "web" {
instance_name = var.instance_name
instance_type = var.instance_type
security_groups = [var.security_group_id]
vswitch_id = var.vswitch_id
system_disk_category = var.disk_category
image_id = var.image_id
}
resource "alicloud_eip_address" "web" {
bandwidth = var.eip_bandwidth
internet_charge_type = var.internet_charge_type
}
resource "alicloud_eip_association" "web" {
instance_id = alicloud_instance.web.id
allocation_id = alicloud_eip_address.web.id
}# modules/server/variables.tf
variable "instance_name" {
type = string
description = "Name of the ECS instance"
default = "terraform-ecs"
}
variable "instance_type" {
type = string
description = "Type of the ECS instance"
default = "ecs.n1.small" # Select an instance type based on your actual business requirements.
}
variable "security_group_id" {
type = string
description = "ID of the security group"
}
variable "vswitch_id" {
type = string
description = "ID of the vswitch"
}
variable "disk_category" {
type = string
description = "Category of the system disk"
default = "cloud_efficiency"
}
variable "eip_bandwidth" {
type = number
description = "Bandwidth for the EIP in Mbps"
default = 5
}
variable "internet_charge_type" {
type = string
description = "Internet charge type for EIP"
default = "PayByTraffic"
}
variable "image_id" {
type = string
description = "ID of the ECS image"
default = "ubuntu_18_04_64_20G_alibase_20190624.vhd" # By default, Ubuntu 18.04 is used.
} # modules/server/outputs.tf
output "server_id" {
description = "The ID of the ECS instance"
value = alicloud_instance.web.id
}
output "server_ip" {
description = "The public IP address of the server"
value = alicloud_eip_address.web.ip_address
}4.4 Call the modules
Call the preceding modules in the root module, which is in the root directory main.tf.
provider "alicloud" {
region = "cn-hangzhou"
}
module "network" {
source = "./modules/network"
vpc_name = "my-vpc"
vpc_cidr = "10.0.0.0/16"
vswitch_name = "my-vsw"
vswitch_cidr = "10.0.1.0/24"
zone_id = "cn-hangzhou-i"
security_group_name = "my-sg"
}
module "web_server" {
source = "./modules/server"
instance_name = "web-server"
instance_type = "ecs.g6.large"
security_group_id = module.network.security_group_id
vswitch_id = module.network.vswitch_id
disk_category = "cloud_essd"
eip_bandwidth = "5"
internet_charge_type = "PayByBandwidth"
}As shown in the preceding example, Terraform modules facilitate the management of Alibaba Cloud infrastructure code and improve the code reusability and maintainability.