每个模块的变量声明是完全独立的,因此 Terraform 中没有内置功能可以共享它们。
如果您使用支持符号链接的文件系统,您可以将同一个 .tf 文件符号链接到多个目录中以获得类似的效果。但是,除非变量声明集特别大或特别复杂,否则我建议只复制它们:从长远来看,保持每个配置自包含通常比避免少量复制简单的样板代码更有帮助。
如果您使用的是 Terraform v0.12,您可能希望将所有这些常用设置组合成一个对象值,以便减少样板:
locals {
context = {
app = "example"
env = var.environment
}
}
module "ec2" {
source = "../service1"
context = local.context
}
module "workspaces" {
source = "../service2"
context = local.context
}
像下面这样的变量声明(在您的每个子模块中)将使 context 对象的形状更加明确,因此如果传递了不适当的值,Terraform 可以检测并报告有关它的错误:
variable "context" {
type = object({
app = string
env = string
})
}
当分解成多个模块时,像上面那样传递一组标准的上下文通常就足够了,但是如果您的系统特别复杂(模块代表了许多不同的子系统),从长远来看,思考可能会有所帮助确切地了解每个模块需要什么并明确传递这些单独的东西,而不是到处传递相同的对象。
例如,如果您想从其调用者decouple ec2 模块,也许您会将其设计为没有“应用程序”或“环境”的概念——这些概念属于调用者模块,但不是 EC2 概念——而是以更以 EC2 为中心的方式表达相同的东西,例如通过标签:
locals {
# Common tags for all AWS objects
aws_tags = {
Name = "example ${var.environment}"
Environment = var.environment
}
}
module "ec2" {
source = "../service1"
# (other EC2-oriented settings)
tags = local.aws_tags
}
通过这种方式,EC2 模块只关心 EC2 的概念,根模块从它自己的“应用程序”和“环境”的思想转化为 EC2 的标签思想。这可能允许稍后在不同的上下文中使用相同的 EC2 模块,例如,不同的标记方案是合适的。
在Module Composition 上的 Terraform 文档部分中提供了有关此方法的更多信息。