将Terraform模块对象作为输入变量传递是否常用?有何风险?
关于Terraform模块间传递上下文对象的疑问
需求与实现
我计划创建一个模块作为顶层上下文(存储一系列共享常量),避免每个模块都重复实例化该上下文模块,于是让入口模块创建该模块对象,再将其作为输入变量传递给其他模块。以下是验证可行的代码结构与实现:
目录结构
├── main.tf ├── modules │ ├── mod1 │ │ └── mod1.tf │ ├── mod2 │ │ └── mod2.tf
代码实现
main.tf
module mod1 { source = "./modules/mod1" var1 = "hello" var2 = "world" } module mod2 { source = "./modules/mod2" var1 = module.mod1 } output "mod1" { value = module.mod1 } output "mod2" { value = module.mod2 }
modules/mod1/mod1.tf
variable "var1" { type = string } variable "var2" { type = string } output "out1" { value = "In module1; got var1 = ${var.var1}" } output "out2" { value = "In module1; got var2 = ${var.var2}" }
modules/mod2/mod2.tf
variable "var1" { type = any } output "out1" { value = "var1 is ${var.var1.out1}, var2 is ${var.var1.out2}" }
执行结果
执行命令:
$ terraform init && terraform plan
得到输出:
Changes to Outputs: + mod1 = { + out1 = "In module1; got var1 = hello" + out2 = "In module1; got var2 = world" } + mod2 = { + out1 = "var1 is In module1; got var1 = hello, var2 is In module1; got var2 = world" }
问题
请问这种做法是否属于常规操作?若不是,该方式存在哪些风险,比如Terraform未来版本是否会不再支持该特性?
解答
这种将整个模块输出对象作为变量传递给其他模块的方式,是Terraform官方支持的常规用法,但存在几个需要注意的点:
1. 类型安全性缺失
你在mod2中使用type = any接收模块对象,会丢失Terraform的类型检查能力。如果mod1的输出结构发生变化(比如字段重命名、类型修改),mod2只会在执行阶段报错,无法在plan阶段提前发现问题。建议定义更精确的对象类型,比如:
variable "var1" { type = object({ out1 = string out2 = string }) }
这样能在配置编写或plan阶段就检测到不匹配的结构,提升代码健壮性。
2. 模块耦合度升高
mod2直接依赖mod1的输出字段结构,一旦mod1调整输出,mod2必须同步修改,否则会出现引用错误。这种强耦合会降低模块的独立性,不利于后续维护和复用。
3. 版本兼容性风险
Terraform从0.12版本开始就支持模块输出作为复杂对象传递,这个特性属于核心功能,未来版本几乎不会移除。但升级Terraform时需要注意官方的兼容性说明,比如某些输出类型的序列化逻辑可能有细微调整,但这类情况极少发生。
4. 更优替代方案
如果只是传递共享常量,推荐以下更轻量的方式:
- 根模块局部值:在根模块用
locals定义共享常量,直接传递给各个模块,避免额外的模块实例化:locals { shared_var1 = "hello" shared_var2 = "world" } module mod2 { source = "./modules/mod2" var1 = local.shared_var1 var2 = local.shared_var2 } - 专用常量模块:创建仅输出常量的模块,其他模块直接引用其输出,无需传递整个模块对象:
# 常量模块 outputs.tf output "shared_var1" { value = "hello" } output "shared_var2" { value = "world" } # 其他模块引用 module mod2 { source = "./modules/mod2" var1 = module.constants.shared_var1 var2 = module.constants.shared_var2 }
内容的提问来源于stack exchange,提问作者codeforester
相关产品推荐
相关产品推荐

