文章讨论了 Terraform/OpenTofu 模块在基础设施规模化中的作用:从本地模块、Git 托管模块到私有 Registry 模块,随着团队和系统复杂度提升,模块能帮助复用配置、统一安全与合规策略、减少漂移并便于版本管理。文章还结合 Infisical 介绍了如何用 Terraform 的 ephemeral resources 以不落盘的方式获取密钥,避免 secrets 进入 state 文件,同时保持模块接口简洁可复用。
发布于 2025 年 4 月 16 日星期三

使用 Terraform 或 OpenTofu 的基础设施团队,随着部署规模的增长,必然会遇到扩展性挑战。最初简单直接的资源定义,会演变为跨环境、应用和团队重复出现的复杂配置。最初的解决方案通常是为每个新服务或环境复制并修改 Terraform 代码,而随着新服务和应用不断加入,这种做法会逐渐累积技术债务。
Terraform modules 通过将基础设施模式转化为可版本控制、可复用的组件,来应对这一挑战。工程团队不再复制配置块,而是可以在 modules 中封装通用模式,并通过不同的输入变量重复使用。这种方法将基础设施开发从手工复制转变为系统化的组件复用。
当团队需要修改负载均衡器配置或更新安全策略时,他们只需修改一次相关 module。使用该 module 的服务随后便可以通过受控的版本更新采用这些改进。
模块化基础设施的影响不仅限于代码组织。有效使用 modules 的团队会发现,他们的开发模式会从被动复制转向主动设计。安全策略、合规要求和基础设施优化会变成标准化组件,而不是孤立的配置。这种标准化降低了配置漂移,同时有助于在规模化时保持基础设施的一致性。
从本地 modules 到外部 modules 的路径,通常反映了组织基础设施成熟度和规模的演进。团队在早期开发阶段往往从本地 modules 开始,把可复用配置放在基础设施仓库的 modules 目录中。当一两名工程师快速迭代基础设施时,这种方式非常合理;变更是即时的,测试也很直接,而且版本控制会自然地与主配置一起进行。
本地 modules 位于基础设施仓库的结构之内,通常在一个 modules 目录中,每个 module 都维护自己的资源、变量和输出文件。对这些 modules 的更改会和根配置一起记录在同一个提交历史中,因此很容易将 module 更新与基础设施变更对应起来:
module "app_networking" {
source = "./modules/app_networking"
vpc_cidr = "10.0.0.0/16"
environment = "production"
}
随着组织的 Infrastructure as Code(IaC)实践日趋成熟,通常会把 modules 迁移到专门的 Git 仓库中。当团队需要在多个项目之间共享基础设施模式,或者需要通过适当的版本管理来控制变更时,就会发生这种转变。托管在 Git 上的 modules 支持通过 commit 或 tag 固定特定版本,从而能够精确控制每个配置使用的 module 版本:
module "web_platform" {
source = "git::https://example.com/infrastructure.git//modules/web-platform?ref=v1.2.0"
}
对于包含多个相关 modules 的大型仓库,可以采用子目录级别的组织方式。module source 中的双斜杠语法允许引用这些子目录,同时保持相关 modules 一起进行版本管理:
locals {
infra_repo = "git::https://example.com/infrastructure.git//modules"
version = "?ref=v1.2.0"
}
module "networking" {
source = "${local.infra_repo}/networking${local.version}"
}
当基础设施的复杂度和规模达到某个阈值时,组织通常会投资于像 Terrateam 这样的 TACOS(Terraform/OpenTofu Automation and Collaboration Software)平台,它提供多种自动化功能,以及一个私有 module registry 的托管实例。
由 registry 托管的 modules 引入了一种更结构化的版本管理和分发方式:
module "web_platform" {
source = "private-registry.example.com/infrastructure/web-platform"
version = "~> 1.2.0"
}
在整个开发过程中,工程师不可避免地会面临一个决定:是构建自定义 modules,还是利用来自公共社区 registry 的现有 modules,例如 Terraform 或 OpenTofu。这些 registry 提供了数千个由社区维护的常见基础设施模式模块,从 VPC 配置到数据库部署。那么,你是否应该重新发明轮子?
从安全角度来看,内部创建的 modules 通常是更安全的选择,尤其是对于关键基础设施。外部 modules 需要仔细审查其实现细节:一个看似无害的计算模块,可能在配置中硬编码了恶意的 AMI 镜像。除了关键安全问题之外,外部来源的 modules 不可避免地会带有一定程度的“大而全”配置;它们必须被设计为支持尽可能多的 use case。引入一个外部 module 可能会提供所需的基础设施,但代价是陈旧或未使用的配置,以及额外的技术债务。
版本管理在内部 modules 和外部 modules 之间也有显著差异。对于内部 modules,团队掌控整个更新周期。外部 modules 可能会引入破坏性变更,或带来与现有基础设施冲突的依赖更新。有些团队通过 fork 并在内部维护外部 modules 来解决这个问题,但这也会带来额外的维护负担。
从本地 modules 过渡到外部 modules,也意味着必须实现认证和授权逻辑。托管在 Git 上的 modules 通常依赖 SSH keys 或 access tokens,因此需要进行凭证和 secret 管理。私有 registry 会增加另一层认证,通常会与组织的 SSO 集成,同时还要求 CI/CD 系统使用服务凭证。
对于大多数企业来说,modules 的使用会随着基础设施成熟而经历以下阶段:
随着团队扩展 Terraform 部署,管理 secrets 和凭证会迅速成为一个痛点。直接在 Terraform 代码中硬编码凭证,从安全角度看显然有问题,但即使使用环境变量或 .tfvars 文件,随着基础设施变得越来越复杂,也会带来运维挑战。基础设施团队最终会面临一个棘手的问题:我们的可复用 modules 如何安全地访问它们所需的凭证?
Infisical 通过与 Terraform 集成来应对这一挑战,提供与模块化基础设施无缝协作的安全 secrets 管理。使用 Terraform v1.10+ 时,你可以使用 ephemeral resources,确保 secrets 永远不会持久化到 state 文件中:
terraform {
required_providers {
infisical = {
source = "infisical/infisical"
version = ">= 0.4.0"
}
}
required_version = ">= 1.10.0"
}
module "database" {
source = "./modules/database"
name = "customer-db"
engine = "postgres"
instance_type = "db.t3.medium"
# 从 Infisical 引用 ephemeral secrets
credentials = {
username = local.db_credentials.username
password = local.db_credentials.password
}
}
## 以 ephemeral 方式获取 secret(永不持久化到 state 中)
ephemeral "infisical_secret" "db_creds" {
name = "DB_CREDENTIALS"
env_slug = var.environment
workspace_id = var.infisical_workspace_id
folder_path = "/database"
}
## 将 JSON secret 解码为可用值
locals {
db_credentials = jsondecode(ephemeral.infisical_secret.db_creds.value)
}
这种方法同时解决了几个问题:
另请阅读:如何使用 Terraform 从 Infisical 获取 secrets,使用传统 data sources 和 ephemeral resources 两种方式
这种模式在数据库 modules 中尤其有效,因为你通常既要处理预配期间的管理员凭证,也要处理服务连接所需的应用凭证。与其通过变量和输出管理两套凭证,不如都通过 Infisical 来处理,从而降低 module 接口的复杂性。
到了一定阶段,本地 modules 将不再足够。随着基础设施规模扩大,团队需要一种方式来管理 module 版本、安全地发布更新,并在不同环境之间保持一致性。这正是结构化 module 管理和自动化发挥作用的地方。下一篇文章将介绍如何组织 Terraform modules、处理版本管理,以及避免基础设施代码在扩展过程中常见的陷阱。
CTO,Terrateam
- 原文链接: infisical.com/blog/terra...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!
作者暂未设置收款二维码