如何通过Terragrunt实现模块化Terraform的父级状态文件与锁管理
Terragrunt 模块化架构下共享父级状态与锁的配置方案
项目结构
. ├── backend-config.yml ├── backend.tf ├── core-dns-csi-driver-addon │ ├── terragrunt.hcl ├── eks │ ├── terragrunt.hcl ├── karpenter │ ├── terragrunt.hcl ├── kube-proxy-vpc-cni-addon │ ├── terragrunt.hcl ├── local-swarm-nodegroup │ ├── terragrunt.hcl ├── loki │ ├── terragrunt.hcl ├── metrics-server │ ├── terragrunt.hcl ├── provider.tf ├── storageclass │ ├── terragrunt.hcl ├── terragrunt.hcl # 父级配置文件 ├── update_yaml.py └── vpc ├── terragrunt.hcl
需求
- 状态文件:在根目录使用单个共享状态文件
- 锁机制:通过父级配置的DynamoDB实现状态锁
- 模块化:保留各子模块(eks、vpc等)独立的
terragrunt.hcl结构
已尝试操作
- 根目录
terragrunt.hcl配置共享后端:
remote_state { backend = "s3" config = { bucket = "my-terraform-state" key = "terraform/parent-level-state.tfstate" region = "us-east-1" dynamodb_table = "eks-locks" encrypt = true } }
- 子模块
terragrunt.hcl引用父级配置:
include { path = find_in_parent_folders() }
问题
- 如何配置Terragrunt,在保留模块化结构的同时,强制使用父级的单个状态文件与锁机制?
- 如何在模块级别执行
apply和destroy操作,同时保持父级状态文件的完整性? - 有没有更优方案来管理带共享父级状态与锁的模块化Terraform配置?
解答
1. 强制使用父级共享状态与锁的配置
你的基础配置方向正确,只需补充以下规则确保子模块完全继承父级后端:
- 根目录
terragrunt.hcl:添加强制继承的配置,禁止子模块覆盖后端设置:
remote_state { backend = "s3" config = { bucket = "my-terraform-state" key = "terraform/parent-level-state.tfstate" region = "us-east-1" dynamodb_table = "eks-locks" encrypt = true } # 强制子模块使用此后端,不允许自定义覆盖 override = true } # 统一传递全局变量给所有子模块 terraform { extra_arguments "common_vars" { commands = get_terraform_commands_that_need_vars() arguments = [ "-var-file=${get_parent_terragrunt_dir()}/backend-config.yml" ] } }
- 子模块
terragrunt.hcl:绝对不能定义自己的remote_state块,仅保留继承和模块源配置:
include { path = find_in_parent_folders() } # 示例:指定当前模块的Terraform代码路径(根据实际情况调整) terraform { source = "./../modules/eks" }
这样所有子模块会强制使用父级的单状态文件和DynamoDB锁机制。
2. 模块级别执行操作并保持状态完整性
直接进入子模块目录执行Terragrunt命令即可,例如:
- 进入
eks目录:terragrunt apply - 进入
vpc目录:terragrunt destroy
需注意以下要点保证状态完整性:
- 禁止并行操作:所有模块共享同一状态文件和锁,并行执行会触发锁冲突,必须串行操作。
- 定期备份状态:执行
terragrunt state pull > backup.tfstate定期导出状态文件,防止误操作导致状态损坏。 - 依赖管理:如果模块间有依赖,需按依赖顺序执行命令(比如先apply vpc,再apply eks)。
3. 更优方案:共享锁+独立状态文件
单状态文件会导致状态耦合、并行受限等问题,更合理的方案是共享锁机制,但每个模块使用独立状态文件:
- 根目录
terragrunt.hcl:配置动态状态文件路径,共享锁表:
remote_state { backend = "s3" config = { bucket = "my-terraform-state" # 子模块自动替换为自身相对路径,生成唯一状态文件key key = "terraform/${path_relative_to_include()}/terraform.tfstate" region = "us-east-1" dynamodb_table = "eks-locks" encrypt = true } }
每个子模块的状态文件会存储为s3://my-terraform-state/terraform/eks/terraform.tfstate、s3://my-terraform-state/terraform/vpc/terraform.tfstate等独立路径,同时共享同一个DynamoDB锁表(锁会根据状态文件key自动区分,无冲突)。
这种方案的优势:
- 保留模块化独立性,状态文件按模块隔离,便于排查问题
- 共享锁机制,无需重复创建DynamoDB表
- 支持并行操作不同模块,提升效率
- 避免单状态文件过大,降低维护风险
如果你的业务场景确实需要单状态文件(比如模块强依赖、需统一管理所有资源),可以坚持原方案,但要严格遵守串行操作和状态备份规范。
内容的提问来源于stack exchange,提问作者Atish Humbre
相关产品推荐
相关产品推荐

