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 验证)
Terraform Registry 模块引用流程 用户 Terraform 配置 module "vpc" { source = "..." } terraform init Terraform Registry registry.terraform.io 版本解析 版本约束匹配 ~> 5.0 → 5.2.4 模块下载 .terraform/modules/ 本地模块缓存 ~/.terraform.d/ terraform plan/apply 执行基础设施变更 关键点 • 版本约束在 init 时解析 • 锁定文件 .terraform.lock.hcl

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 接口。部署架构通常包含以下组件:

自托管 Terraform Registry 架构 Terraform CLI terraform init 负载均衡器 TLS 终止 + 路由 Registry API 模块发现 + 版本解析 对象存储 S3 / GCS / MinIO 认证服务 OIDC / LDAP / 部署建议 • 使用 Docker Compose 或 K8s 部署 • 数据库推荐 PostgreSQL

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 修复,不改变接口,如修复资源参数错误
兼容性检查清单:
  1. 新增变量必须设置 default 值,确保已有调用不报错
  2. 删除变量前至少废弃一个 MINOR 版本,并在 README 中标注 deprecated
  3. 输出值类型变更必须升级 MAJOR 版本
  4. 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 验证