亚马逊AWS官方博客
Terraform 最佳实践之变量传递
![]() |
在本文中,我们将探讨在企业中使用 Terraform 时,如何在面对不同组织部门的情况下进行全局规划。由于环境中的组件通常是动态变化的,需要在动态过程中实现变量传递。接下来,我们将讲解实现这一目标的具体方法。
组织架构和需求实现
- 基础设施层:通常由基础架构部门(如 SRE/DevOps 工程师)负责初始化账号,给到不同的部门交付基础架构的设计,例如 Amazon VPC 和基础权限,这些构成了公司的核心安全基础。
- 应用层:各个业务部门通常有自己的应用层面的需求,这一层主要部署业务需求相关的应用级资源,例如 Amazon EKS 和 Amazon RDS。
模块使用
如果需要实现上述的需求,就需要调用特定的模块,学会协调和使用模块。通常,我们会用到公有模块和私有模块。
- 公有模块:由 Terraform 官方提供的开发的模块 https://github.com/terraform-aws-modules,通常涵盖了常用的所有基础服务,可以用于快速构建基础环境。例如:Amazon VPC、Amazon IAM、Amazon EC2,等等。
- 私有模块:根据企业的特殊需求自定义开发的模块。例如,为实现 VPC Peering 而创建的模块,并根据场景需求不断迭代完善。
目录结构
在 Terraform 中,各部门创建资源时通常使用特定的目录结构。为了便于区分,可以将这些目录称为“Playbook”,与 Modules 目录结构加以区分。
核心问题
所以接下来引出的问题是,在各部门创建 Playbook 资源的过程中,可能存在公司或部门约定的全局变量。然而,由于每次调用通常是以独立目录的方式进行,如何在这种情况下实现全局变量的共享和使用?
另外,假设 SRE 部门已编写了一些用于资源创建的 Playbook,例如 VPC 的创建。作为业务部门,如果想单独编写 RDS 创建的 Playbook,应如何基于 SRE 部门的 Playbook,获取目标 VPC 下不同子网的部署信息?
为了更好地说明问题,我们先基于上面的假设看一下全局设计图。
![]() |
解决方案
管理全局变量
在 Terraform 调用过程中,是以目录为基础单元进行调用的。在默认机制中,存在一定限制,但我们可以通过将全局变量作为 output 来定义,然后在不同部门的 Playbook 中直接调用该模块。具体见下图。
![]() |
通过这种方式,在每个 Playbook 里面调用 global_variables 模块,从而通过做到变量的引用,这样实际就建立起一种约定机制。
跨 Playbook 调用
不同 Playbook 之间的调用层次非常偏上层。如果我们在一个单独的 Playbook 里面,直接使用 resource 和 module,都可以直接使用其属性值;但是在不同 Playbook 之间调用,需要用到 tfstate 进行引用,而存在于 tfstat 里面的值,实际上随着 Playbook 的执行而变化。实际上,这种引用关系仍然是通过 playbook 里面定义的 output 实现的,如果没有定义对应的 output,调用的 Playbook 也不会读取到。但是如果我们基础架构发生变化,关于资源的 ARN 会发生变化,这种引用关系实际上是一种动态的引用逻辑。
![]() |
例如:
其中:
Playbook 调用 Public Modules 或者 Private Modules
我们建议使用指定的模块版本,指向模块的 Git 仓库。具体使用方法:
我们当前引用的是一个公开的 Terraform 实现的 Amazon VPC 模块:
指定版本后,可以确保部署的一致性和可重复性,避免意外升级带来的破坏性,提供可靠的 CI/CD 流程。而使用 Private Modules 原理也是一致的。
结论
通过采用以上最佳实践,企业可以更高效地管理 Terraform 变量,实现团队间的协作与基础设施的一致性。这些方法同样适用于 Terraform Cloud 或 GitOps 流程,有助于构建可扩展且易维护的基础设施管理体系。