Terragrunt多环境多区域最佳DRY实践及架构优化咨询
现有文件夹与文件结构
├── live │ └── environments │ └── alpha │ ├── control-plane │ ├── env.hcl │ ├── global │ └── regional │ ├── eu-central-1 │ │ ├── networking │ │ │ └── terragrunt.hcl │ │ └── region.hcl │ └── us-west-2 │ ├── networking │ │ └── terragrunt.hcl │ └── region.hcl ├── provider.tf ├── terraform.tfstate └── terragrunt.hcl
关键文件定义
region.hcl
locals { region = reverse(split("/", get_terragrunt_dir()))[0] }
env.hcl
locals { environment = reverse(split("/", get_terragrunt_dir()))[0] }
架构说明
这套架构可实现不同区域内模块的复制与隔离,这在旧版Terraform中较难实现,但在tofu 1.8中已可行。
待解决问题与目标
- 能否避免手动复制
<region>/<modules/terragrunt.hcl>文件? - 能不能实现文件与文件夹的模板化?
- 即将发布的tofu 1.9的动态提供商如何助力现有架构,实现通过占位符环境与基础区域文件夹、传递区域变量来迭代?
- 该架构和Terragrunt官方《Keep your Architecture DRY》指南中推荐的
_env文件夹方案差异有多大?
核心需求
需要部署多个设计相似的应用,每个应用对应一个国家,每个国家要部署在2个不同区域,每个区域需要5-8个区域模块。如果有8个国家,会产生8×2×8=128个hcl文件,急需DRY(Don't Repeat Yourself)实践或工具/模板化方案减少重复工作。
问题解答
1. 避免手动复制<region>/<modules/terragrunt.hcl>文件
完全可以,借助Terragrunt的继承与引用机制实现:
- 在
regional目录下创建_common.hcl通用配置文件,定义所有区域模块共享的Terragrunt规则,比如模块源、依赖关系、通用变量等。 - 各区域模块目录下的
terragrunt.hcl仅需通过include块引用通用配置,补充少量区域特有配置即可,示例:include "common" { path = find_in_parent_folders("_common.hcl") } # 仅添加区域专属配置(如有需要) inputs = { region = local.region } - 还可结合
get_terragrunt_dir()自动推导模块名称,动态匹配对应Terraform模块源,进一步减少重复。
2. 文件与文件夹的模板化实现
有两种可行方式:
- Terragrunt生成器:利用Terragrunt的
generate块,运行时自动生成terragrunt.hcl文件;也可结合Go Template、Jinja2等外部模板工具,批量生成基础文件夹结构和配置文件。 - 自定义脚本:编写Shell/Python脚本,根据预设的区域列表、模块列表,读取含占位符(如
{{REGION}}、{{MODULE}})的模板文件,批量替换并创建对应文件夹和配置。 - 另外,Terragrunt的
terraform { source = ... }支持动态路径,配合local变量可让同一配置适配不同模块,无需复制文件。
3. tofu 1.9动态提供商的助力
tofu 1.9的动态提供商特性可从以下方面优化现有架构:
- 占位符环境与区域迭代:在根配置中定义所有需部署的环境、区域列表,动态提供商可根据列表自动创建对应区域的提供商实例,无需为每个区域单独编写提供商配置。
- 变量传递自动化:动态提供商可直接引用路径推导的
local.region变量,自动将区域参数传递给提供商,无需在每个区域配置中重复定义。 - 批量部署简化:配合Terragrunt的
terragrunt run-all批量执行命令,可一次性迭代所有占位符区域,自动完成不同区域的模块部署,无需逐个区域操作。
4. 与Terragrunt官方_env方案的差异
官方_env方案核心是环境级配置继承,典型结构为:
├── live │ ├── _env │ │ ├── common.hcl │ │ ├── alpha.hcl │ │ └── beta.hcl │ ├── alpha │ │ └── ... │ └── beta │ └── ...
两者差异主要在:
- 配置层级:你的架构是
environments -> alpha -> regional -> <region>的嵌套层级,配置自上而下继承;_env方案将环境配置集中在_env目录,各环境目录通过include引用,偏向扁平式管理。 - 区域处理:你的架构为每个区域创建独立目录和
region.hcl;_env方案通常将区域作为输入变量,配合模块多区域支持,无需单独创建区域目录。 - 扩展性:你的架构新增区域需创建对应目录;
_env方案可通过变量列表动态生成区域配置,更适合大规模多区域部署。 - 隔离性:你的架构区域物理隔离,直观清晰;
_env方案通过变量隔离,配置更紧凑。
两者核心均遵循DRY原则,可结合优点优化:比如在现有架构中引入_env式的集中配置,同时保留区域目录的隔离性。
内容的提问来源于stack exchange,提问作者diegoaguilar
相关产品推荐
相关产品推荐

