4. 模块化设计:Terraform Module 的创建、输入输出变量、模块注册中心与版本管理
在跨云资源池编排场景中,直接编写扁平化的 .tf 文件会导致代码膨胀、复用性差、维护成本激增。Terraform Module 是解决这一问题的核心抽象单元,它将一组相关的资源封装为可复用的“乐高积木”。本章将深入 Module 的创建规范、变量契约、注册中心发布流程以及语义化版本控制策略。
4.1 Module 的标准结构与创建规范
Terraform Module 本质上是一个包含 .tf 或 .tf.json 文件的目录。一个生产级 Module 必须遵循以下文件结构约定:
| 文件/目录 | 必需性 | 作用说明 |
|---|---|---|
main.tf |
推荐 | 主资源定义逻辑,包含核心资源(如 AWS VPC、Azure AKS、GCP GKE)的声明。 |
variables.tf |
推荐 | 声明所有输入变量(Input Variables),定义类型、描述与默认值。 |
outputs.tf |
推荐 | 声明所有输出值(Output Values),供根模块或其他子模块消费。 |
versions.tf |
推荐 | 声明 Terraform 版本约束与 Provider 版本约束。 |
README.md |
强烈建议 | 模块用途、前置条件、使用示例与变更日志。 |
examples/ |
建议 | 包含可直接运行的完整示例目录,用于验证模块功能。 |
最佳实践: 始终在
versions.tf 中锁定 Terraform 最低版本(如 required_version = ">= 1.5"),避免因 CLI 版本差异导致状态文件不兼容。
4.2 输入输出变量:定义契约接口
变量是 Module 与外部交互的唯一通道。设计良好的变量接口应遵循“最小暴露原则”与“强类型约束”。
4.2.1 输入变量(Input Variables)
在 variables.tf 中,每个变量应包含 type、description 和可选的 default 与 validation 块。
# variables.tf
variable "cluster_name" {
description = "Kubernetes 集群名称,全局唯一"
type = string
}
variable "node_pool_config" {
description = "节点池配置映射"
type = object({
machine_type = string
min_count = number
max_count = number
disk_size_gb = optional(number, 100)
})
default = {
machine_type = "e2-medium"
min_count = 1
max_count = 3
}
}
variable "tags" {
description = "资源标签集合"
type = map(string)
default = {}
}
4.2.2 输出变量(Output Values)
输出变量用于向调用方暴露关键属性,如集群端点、资源组 ID 等。敏感信息应标记为 sensitive = true。
# outputs.tf
output "cluster_endpoint" {
description = "API Server 端点地址"
value = google_container_cluster.primary.endpoint
}
output "cluster_ca_certificate" {
description = "集群 CA 证书(Base64 编码)"
value = google_container_cluster.primary.master_auth[0].cluster_ca_certificate
sensitive = true
}
避坑指南: 避免在输出中暴露 IAM 密钥或 Service Account 令牌。若必须输出,务必设置
sensitive = true,并在 CI/CD 流水线中配置日志脱敏规则。
4.3 模块注册中心与版本管理
企业级跨云资源池需要集中式的模块注册中心来管理模块的发现、发布与版本演进。Terraform 官方提供 Terraform Registry,而私有化场景通常使用 Git 标签 + 文件系统路径 或 私有 Registry(如 Terraform Cloud、HashiCorp Vault 集成方案)。
4.3.1 版本约束语法
在根模块中引用子模块时,必须通过版本约束锁定模块版本,防止意外升级导致资源漂移。
| 约束符号 | 示例 | 含义 |
|---|---|---|
= |
version = "1.2.0" |
精确匹配版本 1.2.0 |
>= |
version = ">= 1.2.0" |
允许 1.2.0 及以上任何版本 |
~> |
version = "~> 1.2" |
允许 1.2.x 范围内的最新版本,禁止 1.3.0 |
!= |
version = "!= 1.2.5" |
排除特定版本 |
4.3.2 私有 Registry 发布流程
对于使用 Git 仓库作为模块源的团队,推荐采用“语义化版本标签 + 目录路径”的引用方式:
# 根模块引用示例
module "gke_cluster" {
source = "git::https://gitlab.internal.com/infra-modules/gke-cluster.git?ref=v1.3.1"
cluster_name = "prod-app-cluster"
node_pool_config = {
machine_type = "n1-standard-4"
min_count = 3
max_count = 10
}
tags = {
Environment = "production"
Team = "platform"
}
}
版本管理策略:
- MAJOR:不兼容的 API 变更(如重命名输入变量、删除输出值)。
- MINOR:向后兼容的功能新增(如增加可选变量、新增输出属性)。
- PATCH:向后兼容的缺陷修复(如修正 Provider 版本下限、修复资源参数错误)。
terraform validate 和 terraform fmt -check,确保模块语法正确且格式统一。
4.4 模块化架构全景图
下图展示了从模块创建、注册到跨云消费的完整生命周期,重点突出输入/输出变量在模块间及模块与根配置之间的数据流。
4.5 模块化设计检查清单
在将 Module 发布到注册中心前,请逐项核对以下清单,确保模块质量满足跨云资源池的复用要求:
- 变量完整性:所有输入变量均包含
type、description,敏感变量标记sensitive。 - 输出最小化:只暴露调用方真正需要的属性,避免输出内部临时资源 ID。
- 版本锁定:
versions.tf中指定 Terraform 与 Provider 的版本下限。 - 示例可运行:
examples/目录下的示例可通过terraform init && terraform plan验证。 - 语义化标签:Git 标签严格遵循
vMAJOR.MINOR.PATCH格式,并附带 CHANGELOG。 - 跨云兼容:若模块支持多云,需在 README 中明确标注支持的 Provider 版本与 Region 限制。
推荐工具: 使用
terraform-docs 自动从 variables.tf 和 outputs.tf 生成 README 文档,确保文档与代码始终同步。在 CI/CD 流水线中集成 pre-commit 钩子,自动检查 terraform validate 和 tflint。