介绍
想象一下,你是一名负责设计社区的建筑师。你不会从头开始,一砖一瓦地绘制每一栋房屋。相反,你会先设计一份「标准房屋」的蓝图,然后复制这份蓝图 50 次。
在 Terraform 中,这些可复用的蓝图称为 模块。
模块是 Terraform 从小型示例扩展到实际基础设施代码库的主要方式。团队可以将常见模式封装一次,然后重复使用多次。
你不需要一遍又一遍地重复相同的配置,而是将配置写在模块中,然后重复使用。模块非常重要,因为实际的基础设施代码库会快速增长,需要像应用程序代码一样具备清晰的结构。
在本实验中,你将创建一个用于生成服务器配置文件的简单模块,然后使用该模块创建两台不同的服务器。
创建模块目录
首先,需要准备一个存放蓝图的位置。Terraform 模块实际上就是包含 Terraform 文件的普通目录。
这里有一个重要细节:从文件格式的角度看,模块并不是一种特殊的新语言特性。它只是将 Terraform 配置打包起来,并通过可复用的接口提供出来。
按照惯例,我们通常创建一个名为 modules 的目录,以便统一管理模块。在这个目录中,再为具体的「webserver」模块创建一个目录。
设置目录结构:
cd ~/project
mkdir -p modules/webserver
检查结果:
ls -R
你应该能看到一个包含 webserver 目录的 modules 目录。这个 webserver 目录将作为一个自包含的小型项目。
定义模块
现在需要编写蓝图本身。
模块的工作方式与根项目类似:使用 main.tf 定义资源,使用 variables.tf 接收输入。
本实验使用一个名为 local_file 的简单资源。它只会在磁盘上创建一个文本文件。这个资源非常适合用于学习模块,因为执行速度快,也不需要复杂的云环境配置。
首先使用 nano 创建模块的 main.tf:
nano modules/webserver/main.tf
添加以下内容。这段配置会告诉 Terraform 创建一个文件,并在文件中写入指定文本。
resource "local_file" "server_config" {
content = "Server Name: ${var.server_name}\nEnvironment: ${var.env}"
filename = "${path.root}/${var.server_name}-config.txt"
}
在 nano 中保存并退出(按 Ctrl+O、Enter、Ctrl+X)。
等等,var.server_name 是什么?我们还没有定义它!模块需要声明它接受哪些输入,这与编程语言中的函数类似。
这种类似函数的模型是一个很好的理解方式。模块向调用方公开输入和输出,同时隐藏内部资源的具体细节。
创建模块的 variables.tf:
nano modules/webserver/variables.tf
添加以下输入定义:
variable "server_name" {
description = "The name of the server"
type = string
}
variable "env" {
description = "The environment (e.g., dev, prod)"
type = string
default = "dev"
}
在 nano 中保存并退出。
现在,蓝图(模块)已经完成。它知道如何创建文件,也知道要完成任务需要哪些信息(名称和环境)。
调用模块
现在假设你是一名站点管理员。你想要构建一台服务器,但不想处理具体细节,只想「聘请」模块来完成这项工作。
具体做法是在根目录的 main.tf 中创建一个 module 块。这里的根目录 main.tf 位于 ~/project。
创建根目录中的 main.tf:
cd ~/project
nano main.tf
添加以下内容,用于「调用」模块:
module "my_first_server" {
source = "./modules/webserver"
server_name = "web-01"
env = "production"
}
记得在 nano 中保存并退出。
下面解释这段配置:
module "my_first_server":这是该模块实例的名称。source:这是关键配置,用于告诉 Terraform 从哪里找到蓝图目录(./modules/webserver)。server_name和env:这是传递给模块的输入。
模块调用可以让根配置以更高层次描述目标。你不需要重新输入每个底层资源,只需指定「使用这些输入实例化这个可复用模式」。
重要提示:每次添加新模块时,都必须告诉 Terraform 准备该模块。运行 init 来安装模块:
terraform init
现在应用这份配置:
terraform apply -auto-approve
检查结果。你应该能看到模块创建的新文件:
cat web-01-config.txt
成功!模块接收了输入(web-01 和 production),并代替我们完成了工作。
复用模块
精彩的地方就在这里。现在要创建第二台服务器。你不需要复制所有资源代码,只需再次使用这份蓝图。
再次使用 nano 打开根目录中的 main.tf:
nano main.tf
使用方向键移动到文件末尾,然后追加以下代码块:
module "my_second_server" {
source = "./modules/webserver"
server_name = "web-02"
## We are not setting 'env' here, so it will use the default value "dev"
}
在 nano 中保存并退出。
看看这样是不是很简洁?我们只需说明「我想要另一台名为 web-02 的服务器」。不需要了解 local_file 在内部是如何工作的,只需使用模块提供的接口即可。
应用更改:
terraform init
terraform apply -auto-approve
确认现在有两个独立的服务器文件:
ls -l *-config.txt
检查第二个文件,确认它使用了默认的「dev」环境:
cat web-02-config.txt
你已经掌握了可复用基础设施的基本原理!
总结
恭喜你!你已经朝着编写专业 Terraform 代码迈出了一大步。
在本实验中,你学习了:
- 模块:如何将代码组织到可复用的目录中(也就是你的「蓝图」)。
- 输入:如何使用变量让模块更加灵活。
- 调用模块:如何使用
module块创建蓝图的实例。 - 复用:如何用少量代码轻松创建多个基础设施副本。
你现在拥有的不是一堆杂乱的砖块,而是一组可复用的组件。这可以帮助你更快、更安全、更整洁地构建基础设施。



