3. Terraform Registry 与私有模块仓库
模块是 Terraform 实现基础设施即代码复用的核心单元。Terraform Registry 作为官方模块分发中心,提供了海量经过验证的公共模块;而私有模块仓库则解决了企业内部敏感配置、合规策略和定制化模块的托管需求。本章将系统讲解公有仓库的使用方法、私有仓库的搭建方案以及模块发布的标准化流程。
3.1 公有仓库:Terraform Registry 使用
Terraform Registry(registry.terraform.io)是 HashiCorp 官方维护的公共模块市场,支持直接通过 source 参数引用。其核心优势在于版本语义化、自动依赖解析和文档渲染。
| 特性 | 说明 |
|---|---|
| 版本管理 | 严格遵循 SemVer 2.0,支持 ~> 和 >= 约束 |
| 自动文档 | 根据 variables.tf 和 outputs.tf 自动生成输入输出说明 |
| 依赖图 | Registry 会解析模块间的依赖关系并展示版本兼容性 |
| 验证徽章 | 通过 CI 测试的模块会获得“Verified”标识 |
推荐实践:优先使用 Verified 模块(如
terraform-aws-modules/vpc/aws),它们经过社区和 HashiCorp 双重审查,稳定性更高。
公有模块引用语法:
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 5.0"
name = "my-vpc"
cidr = "10.0.0.0/16"
azs = ["us-east-1a", "us-east-1b"]
private_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
public_subnets = ["10.0.101.0/24", "10.0.102.0/24"]
enable_nat_gateway = true
enable_vpn_gateway = false
tags = {
Environment = "production"
ManagedBy = "terraform"
}
}
版本约束最佳实践:
- 生产环境:使用
~> 5.0.0锁定补丁版本,避免意外引入破坏性变更 - 开发环境:使用
>= 5.0.0, < 6.0.0允许自动获取小版本更新 - 测试环境:使用
>= 5.0.0始终使用最新版本(需配合 CI 验证)
3.2 私有仓库搭建方案
企业环境中,敏感配置、合规策略和定制化模块不适合公开在公有 Registry 中。私有模块仓库提供与公有 Registry 一致的版本管理和引用体验,同时支持访问控制和审计。
| 方案 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| Git 仓库直接引用 | 小型团队、快速原型 | 零额外基础设施,直接使用 Git 标签做版本 | 无 Registry UI,版本发现困难 |
| Terraform Enterprise | 大型企业、合规要求高 | 内置 Registry、RBAC、审计日志 | 商业授权成本高 |
| HashiCorp 开源 Registry | 中型团队、自托管 | 功能与公有 Registry 一致,开源免费 | 需要维护服务器和存储 |
| 对象存储 + 元数据文件 | 云原生、S3/GCS 生态 | 存储成本低,与 CI/CD 集成方便 | 需要自行实现版本发现逻辑 |
安全提示:私有模块仓库必须启用传输加密(TLS)和身份认证。避免在模块源码中硬编码密钥或密码,使用 Terraform Vault Provider 或环境变量注入敏感信息。
3.2.1 Git 仓库直接引用
最轻量的私有模块方案,无需额外服务。通过 source 参数直接指向 Git 仓库地址,使用 Git 标签作为版本标识。
# 通过 HTTPS 引用私有 Git 仓库
module "internal_vpc" {
source = "git::https://gitlab.internal.com/infra/terraform-modules/vpc.git?ref=v1.2.0"
}
# 通过 SSH 引用(推荐用于 CI/CD)
module "internal_vpc" {
source = "git::ssh://git@gitlab.internal.com:22/infra/terraform-modules/vpc.git?ref=v1.2.0"
}
# 使用本地路径(开发调试阶段)
module "internal_vpc" {
source = "../../modules/vpc"
}
版本管理约定:
- 使用语义化 Git 标签:
v1.0.0、v1.1.0、v2.0.0 - 在
?ref=参数中指定标签或提交哈希 - 生产环境禁止使用
?ref=main或?ref=develop等分支引用
3.2.2 自托管 Terraform Registry
HashiCorp 提供了开源的 terraform-registry 实现,支持与公有 Registry 相同的 API 接口。部署架构通常包含以下组件:
3.3 模块发布流程
无论使用公有还是私有仓库,模块发布都应遵循标准化流程,确保版本可追溯、变更可审计、使用者可平滑升级。
3.3.1 模块目录结构规范
一个标准的 Terraform 模块应包含以下文件:
terraform-aws-vpc/
├── README.md # 模块说明、使用示例、注意事项
├── main.tf # 核心资源定义
├── variables.tf # 输入变量声明
├── outputs.tf # 输出值声明
├── versions.tf # Terraform 和 Provider 版本约束
├── locals.tf # 本地变量(可选)
├── examples/
│ ├── complete/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── outputs.tf
│ └── minimal/
│ ├── main.tf
│ └── variables.tf
├── tests/
│ ├── test_basic.go # Terratest 集成测试
│ └── fixtures/
└── .terraform.lock.hcl # 依赖锁定文件
关键文件说明:
versions.tf:必须声明required_version和required_providers,避免使用者因版本不兼容而失败README.md:包含模块用途、输入输出说明、至少一个完整示例examples/:提供可直接运行的示例配置,用于 CI 测试和用户参考
3.3.2 版本发布工作流
推荐使用 Git 标签 + CI/CD 流水线实现自动化发布:
| 步骤 | 操作 | 自动化检查 |
|---|---|---|
| 1 | 开发者提交 PR 到 main 分支 |
terraform fmt / validate / lint |
| 2 | CI 运行单元测试和集成测试 | Terratest / kitchen-terraform |
| 3 | PR 合并后,维护者创建 Git 标签 | 标签格式:v1.2.0 |
| 4 | CI 检测到新标签,触发发布流水线 | 生成 CHANGELOG、更新 Registry 元数据 |
| 5 | 模块包上传至 Registry(公有或私有) | 签名验证、版本冲突检查 |
| 6 | 通知下游使用者版本更新 | Slack / 邮件 / Runbook 联动 |
3.3.3 版本语义化与兼容性保证
模块版本必须严格遵循 SemVer 2.0 规范:
- MAJOR 版本(1.x.x → 2.0.0):破坏性变更,如删除变量、修改资源类型、改变输出类型
- MINOR 版本(1.1.0 → 1.2.0):新增功能,向后兼容,如增加可选变量、新增输出
- PATCH 版本(1.1.0 → 1.1.1):Bug 修复,不改变接口,如修复资源参数错误
兼容性检查清单:
- 新增变量必须设置
default值,确保已有调用不报错 - 删除变量前至少废弃一个 MINOR 版本,并在 README 中标注
deprecated - 输出值类型变更必须升级 MAJOR 版本
- Provider 版本升级(如 AWS Provider 4.x → 5.x)建议同步升级 MAJOR 版本
3.3.4 私有仓库模块引用配置
使用私有 Registry 时,需要在 Terraform 配置中指定 source 为私有仓库地址:
# 引用自托管 Registry 中的模块
module "internal_vpc" {
source = "registry.internal.company.com/infra/vpc/aws"
version = "~> 2.0"
name = "production-vpc"
cidr = "10.0.0.0/16"
}
# 引用 Git 仓库(不使用 Registry)
module "internal_vpc" {
source = "git::https://gitlab.internal.com/terraform-modules/vpc.git?ref=v2.1.0"
}
私有 Registry 认证配置:
# ~/.terraformrc 或 $TF_CLI_CONFIG_FILE
provider_installation {
network_mirror {
url = "https://terraform-mirror.internal.company.com/"
include = ["registry.internal.company.com/*"]
}
}
# 私有 Registry 认证令牌
credentials "registry.internal.company.com" {
= "your-registry-"
}
安全最佳实践:不要在
.terraformrc 中硬编码令牌。使用环境变量 TERRAFORM_REGISTRY_ 或 CI/CD 系统的密钥管理服务注入令牌。对于 Git 仓库引用,优先使用 SSH 密钥而非 HTTPS 密码认证。
3.3.5 模块发布清单
每次发布前,使用以下清单确保模块质量:
| 检查项 | 标准 | 自动化 |
|---|---|---|
| 代码格式化 | terraform fmt -check 通过 |
CI 前置检查 |
| 语法验证 | terraform validate 通过 |
CI 前置检查 |
| 版本约束 | versions.tf 包含 required_version |
CI 检查 |
| 文档完整性 | README 包含输入输出说明和示例 | 人工审查 |
| 集成测试 | 至少一个完整示例通过 terraform apply |
CI 集成测试 |
| CHANGELOG | 记录本次变更内容 | 人工审查 |
| 标签签名 | Git 标签使用 GPG 签名 | CI 验证 |