Terraform 模块

LinuxBeginner
立即练习

介绍

想象一下,你是一名负责设计社区的建筑师。你不会从头开始,一砖一瓦地绘制每一栋房屋。相反,你会先设计一份「标准房屋」的蓝图,然后复制这份蓝图 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 块创建蓝图的实例。
  • 复用:如何用少量代码轻松创建多个基础设施副本。

你现在拥有的不是一堆杂乱的砖块,而是一组可复用的组件。这可以帮助你更快、更安全、更整洁地构建基础设施。