Terraform/OpenTofu:tfvars变量传递至根模块与子模块的最佳实践
Terraform根模块与子模块的变量传递最佳实践
核心原则很明确:子模块负责定义严格的变量类型、校验规则和默认值,根模块仅做最基础的变量声明,无需重复复杂定义
1. 子模块:作为变量约束的权威来源
子模块是可复用单元,必须明确变量的完整结构、类型和校验逻辑,确保任何调用它的代码都符合要求。比如在子模块的variables.tf中定义:
variable "example" { type = list(object({ name = string size = object({ height = number length = number }) })) nullable = false description = "示例复杂对象列表" validation { # 注意:原代码的校验逻辑有误,需遍历列表中每个元素做检查 condition = alltrue([for item in var.example : item.size.height > 5]) error_message = "每个对象的height必须大于5。" } }
这样不管哪个项目调用这个子模块,都会自动执行校验,保证输入数据的合法性。
2. 根模块:仅做基础声明,传递变量即可
根模块只需要接收外部(.tfvars或环境变量)传入的值,无需重复子模块的复杂结构和校验。比如根模块的variables.tf:
variable "example" { type = list(object()) nullable = false description = "传递给子模块的示例复杂对象列表" }
然后在根模块中调用子模块时直接传递变量:
module "example_module" { source = "./path/to/your/submodule" example = var.example }
3. 为什么不重复定义?
- 减少冗余维护:子模块的定义是唯一权威,重复定义会导致修改时要同步改两处,增加出错概率。
- 保障复用性:子模块自带完整约束,在其他项目复用时,调用方只需传入符合要求的数据,无需重新编写校验和类型定义。
- 提前暴露错误:子模块的校验会在Terraform计划阶段就检查数据合法性,避免模糊定义导致问题晚发现。
关于.tfvars和环境变量的传递
- .tfvars中直接按复杂结构编写即可,和你原来的写法一致:
example = [ { name = "example1" size = { height = 10 length = 20 } }, { name = "example2" size = { height = 30 length = 40 } } ]
- 用环境变量传递时,需将复杂结构转为JSON字符串:
export TF_VAR_example='[{"name":"example1","size":{"height":10,"length":20}},{"name":"example2","size":{"height":30,"length":40}}]'
内容的提问来源于stack exchange,提问作者Appleoddity
相关产品推荐
相关产品推荐

