Digger 与 Terragrunt _envcommon 共享配置模式:从目录结构到项目生成的源码级解读
DevOps云原生后端【免费下载链接】diggerDigger is an open source IaC orchestration tool. Digger allows you to run IaC in your existing CI pipeline ⚡️项目地址https://gitcode.com/gh_mirrors/di/digger点击查看免费下载_envcommon目录是 Terragrunt 保持架构 DRYKeep Your Terragrunt Architecture DRY实践中的关键一环它集中存放各组件component跨环境共享的通用配置再通过include块把每个文件合并进各环境的 live 配置中。本文以 digger 仓库内置的 terragrunt-infrastructure-live-example 测试示例为完整实例结合 digger 的 terragrunt 配置解析源码libs/digger_config/terragrunt/tac带你理解_envcommon的运作机制并看清 digger 如何识别_envcommon文件、将其自动纳入项目依赖与自动规划autoplan的触发条件。读完你将掌握一套可直接复制、可验证的多环境 Terragrunt 布局方案以及从 Terragrunt 配置到 digger 项目清单的完整数据流。一、_envcommon是什么一处定义、处处合并原文档对_envcommon目录的定位非常清晰This directory holds common configurations for each component that is shared across the environments. Each file will be included and merged into the live configuration for the service component in each environment.翻译成工程语言就是三点按组件组织而非按环境组织_envcommon下每个文件对应一个组件如mysql.hcl、webserver-cluster.hcl而不是每个环境一个文件。跨环境共享同一组件在不同环境qa / stage / prod中复用的参数集中定义在这里避免在每份环境配置里重复粘贴。通过 include 合并进 live 配置各环境目录下的terragrunt.hcl通过include块引用_envcommon中对应的组件文件Terragrunt 在解析时自动完成配置合并。在 digger 仓库中这份示例位于 libs/digger_config/terragrunt/tac/test_examples/terragrunt-infrastructure-live-example/_envcommon/目录下包含mysql.hcl与webserver-cluster.hcl两个组件配置外加本 README。它同时是 digger 的 terragrunt→digger.yml 转换器tac 包的测试样例因此既能作为 Terragrunt 用法示范也能验证 digger 的解析行为。二、整体目录结构account → region → environment → resource要理解_envcommon的定位先看整个示例仓库的层级。示例 README 给出了经典四层组织方式account └ _global └ region └ _global └ environment └ resource对应到本仓库的实际目录account账号层non-prod/与prod/每层都有 account.hcl定义account_name、aws_account_id、aws_profile。region区域层如us-east-1/其 region.hcl 定义aws_region。environment环境层qa/、stage/、prod/其 env.hcl 定义environment qa。resource资源层mysql/、webserver-cluster/每层一份 terragrunt.hcl。而_envcommon与account.hcl、region.hcl、env.hcl平级地处于 跨环境共享 的位置——它是组件层面的公共区配合根目录 terragrunt.hcl 的账号/区域/环境变量聚合共同实现Terraform 代码零重复。三、_envcommon组件文件剖析以 mysql.hcl 为例_envcommon/mysql.hcl是理解共享配置的样板文件由三个部分构成。1.terraform块锁定模块来源与版本terraform { source ${local.base_source_url}?refv0.4.0 }source指向 Terraform 模块仓库中的//mysql子路径?refv0.4.0锁定模块版本。注释明确指出任何环境若需部署不同版本的模块应在本环境重新定义该块并给出不同的 ref 来覆盖部署版本——这正是下文第 4 节要讲的覆盖机制在版本管理上的应用。2.locals读取父级变量并构造复用常量locals { # Automatically load environment-level variables environment_vars read_terragrunt_config(find_in_parent_folders(env.hcl)) # Extract out common variables for reuse env local.environment_vars.locals.environment # Expose the base source URL so different versions of the module can be deployed in different environments. base_source_url git::gitgithub.com:gruntwork-io/terragrunt-infrastructure-modules-example.git//mysql }find_in_parent_folders(env.hcl)从当前目录向上查找最近的env.hclread_terragrunt_config读取并解析它从而拿到当前环境名qa/stage/prodenv提取环境名用于构造带环境前缀的资源名如mysql_qabase_source_url是模块的基础 URL配合上面terraform.source中的?ref一起使用。这里之所以用local.引用而非直接写死是为了让子配置即各环境的terragrunt.hcl在expose true时可以读取并拼接自己的版本号。3.inputs跨环境通用的模块参数inputs { name mysql_${local.env} instance_class db.t2.micro allocated_storage 20 storage_type standard master_username admin # TODO: To avoid storing your DB password in the code, set it as the environment variable TF_VAR_master_password }inputs是传给底层 Terraform 模块的变量。这里的参数是所有环境共用的基线实例规格db.t2.micro、存储 20GB、类型standard、用户名admin。密码刻意留空注释提示通过TF_VAR_master_password环境变量注入避免把数据库口令写进代码。webserver-cluster.hcl采用同样的三段式结构inputs中定义 ASG 的min_size、max_size、server_port、elb_port等公共参数base_source_url指向//asg-elb-service子路径。四、环境侧如何接收共享配置include 块_envcommon的文件并不会被自动加载必须由各环境的terragrunt.hcl显式引用。以 qa 环境的 mysql 为例non-prod/us-east-1/qa/mysql/terragrunt.hcl 中有两个 include# Include the root terragrunt.hcl configuration. The root configuration contains settings that are common across all # components and environments, such as how to configure remote state. include root { path find_in_parent_folders() } # Include the envcommon configuration for the component. The envcommon configuration contains settings that are common # for the component across all environments. include envcommon { path ${dirname(find_in_parent_folders())}/_envcommon/mysql.hcl expose true }include root通过find_in_parent_folders()找到根目录 terragrunt.hcl继承其中的远程状态、AWS provider 生成、账号/区域/环境变量聚合等全局设置include envcommon用dirname(find_in_parent_folders())定位仓库根再拼接/_envcommon/mysql.hcl把组件共享配置合并进来expose true把被包含文件中的locals暴露给本配置使用这样本环境可以用include.envcommon.locals.base_source_url引用_envcommon里定义的模块地址。同样地该文件的terraform块覆盖了模块版本terraform { source ${include.envcommon.locals.base_source_url}?refv0.4.0 }注释说明此处仅为 QA 环境覆盖terraform块的 source 属性以演示如何在不同环境部署不同版本的模块。_envcommon定义的是默认 URL 骨架环境侧只需拼接自己的?ref即可切换版本。值得注意的是 qa 与 stage 的 mysql 配置略有差异qa 版本带expose true因为要读取base_source_urlstage 版本 stage/mysql/terragrunt.hcl 与 prod 版本都只做普通 include不覆盖任何参数或仅覆盖 inputs。三种写法并存正好演示了 include 的灵活度。五、覆盖机制环境个性需求如何覆盖公共基线共享配置的价值在于默认统一、按需覆盖。prod 环境的 mysql 是覆盖示例的最佳说明prod/us-east-1/prod/mysql/terragrunt.hcl# For production, we want to specify bigger instance classes and storage, so we specify override parameters here. These # inputs get merged with the common inputs from the root and the envcommon terragrunt.hcl inputs { instance_class db.t2.medium allocated_storage 100 }注释点明合并语义本环境的inputs会与 root 配置和 envcommon 配置中的公共 inputs 合并。于是 prod 的 MySQL 在继承name mysql_prod、storage_type standard等公共参数的同时把实例规格提升为db.t2.medium、存储提升为 100GB。这种同键覆盖、异键保留的合并行为正是 Terragrunt include 机制的核心价值既保证跨环境一致又允许关键环境差异化。同时root 配置 terragrunt.hcl 里还有一个对 digger 至关重要的扩展点——extra_digger_dependencieslocals { extra_digger_dependencies [ find_in_parent_folders(account.hcl), find_in_parent_folders(region.hcl), find_in_parent_folders(env.hcl), ] ... }这个自定义 local 会被 digger 解析器读取把account.hcl、region.hcl、env.hcl显式声明为项目依赖确保这些层级变量文件变更时也能触发对应项目的 plan/apply详见第七节。六、根配置的全局职责远程状态与 provider 生成虽然_envcommon是组件公共区但账号/区域/环境三级的更全局公共逻辑放在根 terragrunt.hcl通过include root被所有组件继承主要包括1. 自动加载三级变量用read_terragrunt_config(find_in_parent_folders(account.hcl))等方式读取账号、区域、环境变量提取出account_name、account_id、aws_region。2. 生成 AWS provider 块generate provider { path provider.tf if_exists overwrite_terragrunt contents EOF provider aws { region ${local.aws_region} # Only these AWS Account IDs may be operated on by this template allowed_account_ids [${local.account_id}] } EOF }generate块让 Terragrunt 在运行时生成provider.tfallowed_account_ids从账号层变量取值防止误操作其他账号。3. 配置 S3 远程状态remote_state { backend s3 config { encrypt true bucket ${get_env(TG_BUCKET_PREFIX, )}terragrunt-example-terraform-state-${local.account_name}-${local.aws_region} key ${path_relative_to_include()}/terraform.tfstate region local.aws_region dynamodb_table terraform-locks } generate { path backend.tf if_exists overwrite_terragrunt } }后端配置同样被generate写成backend.tf。get_env(TG_BUCKET_PREFIX, )支持通过环境变量给 bucket 名加前缀因为 S3 bucket 名全局唯一示例 README 也提示需要自行改 bucket 或设置TG_BUCKET_PREFIX。4. 全局 inputs 聚合把账号、区域、环境三级的 locals 用merge()合并成全局inputs向下传递给所有子模块——多账号场景下无需在每个模块里重复传terraform_remote_state所需的数据源参数。七、源码视角digger 如何把 terragrunt 配置变成项目清单_envcommon共享配置对 digger 的意义在于digger 需要知道每个项目依赖哪些文件当这些文件变更时自动触发对应项目的 plan。digger 的 terragrunt 解析器位于 libs/digger_config/terragrunt/tac基于 terragrunt-atlantis-config 思想实现见 tac/readme.md核心函数在 generate.go 的getDependencies中。1. include 链被解析为依赖从源码看getDependencies会先调用parseModuleparse_hcl.go判断模块是否为 parent、并抽取 include 列表随后每个 include 的路径都会被追加进依赖集合if len(includes) 0 { for _, includeDep : range includes { getDependenciesCache.set(includeDep.Path, getDependenciesOutput{nil, err}) dependencies append(dependencies, includeDep.Path) } }也就是说qa/mysql 的terragrunt.hcl中include root与include envcommon指向的两份文件根terragrunt.hcl与_envcommon/mysql.hcl都会被识别为依赖。这就是_envcommon文件被纳入 digger 项目触发条件的技术原理。2. locals 中的扩展依赖getDependencies还解析locals读取ExtraDiggerDependencies字段即extra_digger_dependenciesif locals.ExtraDiggerDependencies ! nil { dependencies sliceUnion(dependencies, locals.ExtraDiggerDependencies) }这解释了第六节中extra_digger_dependencies的用途account.hcl、region.hcl、env.hcl的变更也会触发依赖它们的项目。3. 依赖去重、路径规范与缓存getDependencies对相对路径做绝对化makePathAbsolute、统一为 Unix 分隔符filepath.ToSlash、过滤空串并用singleflight.Group 内存缓存GetDependenciesCache避免重复解析默认不开启级联依赖cascadeDependencies由调用方通过 flag 控制。解析完成后createBaseProject把依赖集写入项目的Autoplan.WhenModified即文件变更即触发自动规划的白名单。多个 terragrunt 文件通过errgroup 信号量并发解析Parse中sem : semaphore.NewWeighted(10)兼顾效率与资源上限。4. golden 文件验证生成结果解析结果的标准答案固化在 tac/golden/infrastructureLive.yaml 中。可以看到为non-prod/us-east-1/qa/mysql生成的when_modified列表为projects: - autoplan: enabled: false when_modified: - *.hcl - *.tf* - ../../../../terragrunt.hcl - ../../../../_envcommon/mysql.hcl - ../../../account.hcl - ../../region.hcl - ../env.hcl dir: non-prod/us-east-1/qa/mysql这张 golden 文件精确印证了上述机制*.hcl、*.tf*是本目录自身变更的匹配规则../../../../_envcommon/mysql.hcl正是include envcommon指向的共享配置——_envcommon文件一旦修改qa、stage、prod 三个环境的 mysql 项目都会触发../../../../terragrunt.hcl对应include rootaccount.hcl、region.hcl、env.hcl对应extra_digger_dependencies。类似地webserver-cluster项目的when_modified中对应的是../../../../_envcommon/webserver-cluster.hcl。这份 golden 文件既是转换器的测试基准也是理解 digger 与_envcommon联动关系的最直接证据。八、环境变量与版本选择三个必须知道的细节模块版本由环境自行决定_envcommon中source带?refv0.4.0只是默认值任何环境都可以在自身terragrunt.hcl中重写terraform.source配合expose true读取base_source_url选择不同版本——多环境灰度模块升级无需改动公共文件。数据库密码走环境变量master_username是公共参数但密码必须通过TF_VAR_master_password注入避免口令入库。这也是 digger/CI 场景下推荐的做法。S3 bucket 全局唯一根配置中的 bucket 名必须全局唯一示例 README 明确提示该名字已被占用需要自行修改或通过TG_BUCKET_PREFIX环境变量加前缀。九、快速上手部署与验证路径结合示例 README 的操作指引最小验证路径如下前置条件Terraform 0.13.0、Terragrunt v0.32.0修改根terragrunt.hcl中的 S3 bucket 或设置TG_BUCKET_PREFIX配置 AWS 凭证在prod/account.hcl与non-prod/account.hcl中填入真实的 AWS 账号 ID。部署单个模块cd non-prod/us-east-1/qa/mysql export TF_VAR_master_password(your-password) terragrunt plan terragrunt apply部署区域内全部模块cd non-prod/us-east-1 export TF_VAR_master_password(your-password) terragrunt plan-all terragrunt apply-all验证效果部署后可通过输出的url访问 ASG 服务或用endpoint、db_name连接 MySQL 实例。示例 README 提供了完整的输出样例。若要在 digger 中落地可参考上述 golden 文件的生成逻辑digger 会自动为每个terragrunt.hcl生成一个项目并把_envcommon等依赖文件写入when_modified实现改公共配置、全环境联动的自动化效果。十、小结_envcommon是 Terragrunt DRY 架构中承上启下的组件公共区向上通过find_in_parent_folders读取账号/区域/环境变量向下通过 include 被各环境 live 配置合并侧向通过expose暴露 locals 供环境侧拼接模块版本。它把每个组件跨环境不变的参数收敛到单一来源配合根配置的 provider 生成、远程状态与全局 inputs 聚合让多账号、多区域、多环境的基础设施代码做到真正的一次定义、处处复用。而对 digger 而言_envcommon并非旁路文件——解析器tac 包通过 include 链与extra_digger_dependencies两套机制识别出这些共享配置并将其写入项目的when_modified最终固化在 infrastructureLive.yaml 这类 golden 文件中。理解这条从 HCL 到项目清单的数据流你就能精准控制什么文件变更触发哪些环境的重建这也是把 Terragrunt 仓库接入 digger 自动化的关键一步。赞分享DevOps云原生后端【免费下载链接】diggerDigger is an open source IaC orchestration tool. Digger allows you to run IaC in your existing CI pipeline ⚡️项目地址https://gitcode.com/gh_mirrors/di/digger点击查看免费下载相关推荐Nuxt目录结构终极指南srcDir配置与共享目录最佳实践Nuxt目录结构终极指南srcDir配置与共享目录最佳实践 你是否曾经被Nuxt项目中混乱的目录结构困扰过文件散落在各处不知道应该放在哪里才能获得最佳的开前端后端Web框架SSRFLIP.js结合GSAP打造专业级Web动画的完整指南FLIP.js结合GSAP打造专业级Web动画的完整指南 FLIP.js是一款轻量级的Web动画辅助库通过FLIPFirst, Last, Invert,BitCPM-CANN-1B-gguf社区实践指南用户案例分享与常见问题解决方案 BitCPM CANN 1B gguf社区实践指南用户案例分享与常见问题解决方案 BitCPM CANN 1B gguf 是首个基于华为昇腾 NPU 原上一篇Angel DataBlock 数据块存储详解从接口设计到内存/磁盘三级存储实现下一篇OGX 快速上手指南用 Ollama 五分钟搭建标准化 GenAI API 服务创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考