Terraform跨多文件夹共享变量定义的最佳实践
Terraform 避免变量重复定义的最佳实践(无外部工具)
现有项目中,proj/website_1和proj/website_2需要重复定义application、db、cdn模块的变量,造成冗余。以下是仅用Terraform自身或调整结构的解决方案:
方案一:抽象上层组合模块(推荐最佳实践)
通过新增一个组合模块,将application、db、cdn模块的调用逻辑和变量定义统一封装,让website_1和website_2直接调用这个组合模块,彻底消除重复。
调整后的项目结构
. ├── modules/ │ ├── application/ │ │ ├── main.tf │ │ └── variables.tf │ ├── db/ │ │ ├── main.tf │ │ └── variables.tf │ ├── cdn/ │ │ ├── main.tf │ │ └── variables.tf │ └── website_stack/ # 新增:封装网站完整资源栈的组合模块 │ ├── main.tf # 在这里组合调用application、db、cdn模块 │ └── variables.tf # 统一定义所有子模块需要的变量,仅写一次 └── proj/ ├── website_1/ │ ├── main.tf # 仅调用website_stack模块,传递专属参数 │ ├── dev.tfvars │ └── prod.tfvars └── website_2/ ├── main.tf # 同样调用website_stack模块 ├── dev.tfvars └── prod.tfvars
具体实现
- 编写组合模块逻辑:在
modules/website_stack/main.tf中,按业务需求组合三个子模块,并将变量传递给它们:
module "application" { source = "../application" app_name = var.app_name app_description = var.app_description env_name = var.env_name # 传递其他application模块需要的变量 } module "db" { source = "../db" db_name = var.db_name env_name = var.env_name # 传递其他db模块需要的变量 } module "cdn" { source = "../cdn" cdn_domain = var.cdn_domain env_name = var.env_name # 传递其他cdn模块需要的变量 }
- 统一定义变量:在
modules/website_stack/variables.tf中,一次性定义所有子模块依赖的变量:
variable "app_name" { type = string description = "Application name" } variable "app_description" { type = string description = "Application description" } variable "env_name" { type = string description = "Environment name (dev/prod)" } variable "db_name" { type = string description = "Database name" } variable "cdn_domain" { type = string description = "CDN domain name" }
- 简化网站项目配置:以
proj/website_1/main.tf为例,只需调用组合模块并传递专属参数,无需重复定义变量:
module "website_stack" { source = "../../modules/website_stack" app_name = "website_1" app_description = "Website 1 生产环境资源栈" env_name = terraform.workspace db_name = "website_1_db" cdn_domain = "cdn.website1.com" }
website_2的配置逻辑完全一致,仅需修改参数值即可。
方案二:符号链接共享变量文件(适合简单场景)
如果不想新增组合模块,可通过符号链接让两个网站项目共享同一个变量定义文件,避免重复编写。
操作步骤
- 在
proj目录下创建shared_variables.tf,写入所有通用变量定义。 - 在
website_1和website_2目录下创建符号链接,指向这个共享文件:
# 针对Linux/macOS cd proj/website_1 && ln -s ../shared_variables.tf variables.tf cd ../website_2 && ln -s ../shared_variables.tf variables.tf # 针对Windows(需管理员权限) cd proj\website_1 && mklink variables.tf ..\shared_variables.tf cd ..\website_2 && mklink variables.tf ..\shared_variables.tf
- 若某个网站需要额外的专属变量,可在其目录下新建
extra_variables.tf补充,Terraform会自动合并同目录下的所有.tf文件。
注意:符号链接存在跨平台兼容性问题,Windows下需管理员权限,且版本控制系统(如Git)需特殊配置才能正确追踪符号链接。
方案三:工作区+根模块变量传递(适合高度一致的多网站场景)
如果website_1和website_2的资源结构几乎完全一致,仅参数不同,可考虑将两个项目合并为一个根模块,用Terraform工作区区分不同网站,变量统一定义在根模块的variables.tf中,通过.tfvars文件传递不同网站的参数。
调整后的结构示例
. ├── modules/ │ ├── application/ │ ├── db/ │ └── cdn/ └── proj/ ├── main.tf # 组合调用三个子模块 ├── variables.tf # 统一定义所有变量 ├── website_1_dev.tfvars ├── website_1_prod.tfvars ├── website_2_dev.tfvars └── website_2_prod.tfvars
使用方式
通过切换工作区并指定对应tfvars文件部署:
# 部署website_1生产环境 terraform workspace select website_1_prod terraform apply -var-file=website_1_prod.tfvars # 部署website_2开发环境 terraform workspace select website_2_dev terraform apply -var-file=website_2_dev.tfvars
总结
- 优先选择方案一:符合Terraform模块化设计理念,扩展性强,维护成本低,适合长期迭代的项目。
- 方案二:适合快速解决简单场景的冗余问题,但需注意跨平台和版本控制的兼容性。
- 方案三:适合资源结构高度一致的多网站场景,减少项目目录数量,但灵活性稍弱。
内容的提问来源于stack exchange,提问作者user3183717
相关产品推荐
相关产品推荐

