Terraform中模块固定关联对应资源状态文件的实现方案
明确答复
原生Terraform做不到你说的效果。Terraform的状态存储粒度是根模块工作区级别的,单个根模块执行apply时,不管加载了多少层嵌套子模块、子模块对应哪类资源,所有新创建资源的状态都会写入当前根模块绑定的状态文件,不会因为子模块是S3模块就自动把S3资源的状态分流到S3专属状态文件里。不管你是直接调用S3模块,还是在上层编排模块里嵌套调用S3模块,只要是在同一个根模块下跑,状态就会混在同一个文件里。
适配方案(完全不改动你既定的按对象类型拆状态的架构)
你不需要调整现有的状态拆分规则,只要把状态拆分的边界放在根模块层,不要把跨不同状态的资源调用封装在同一个根模块的执行链路里就行,具体落地规则:
- 每一类对象对应一个独立的根模块工作区,单独绑定自己的专属状态文件。比如S3专属工作区里只调用S3底层模块,所有S3资源的变更都在这个工作区执行,状态固定写入S3专属状态文件;Snowflake Storage Integration专属工作区里只调用对应的底层模块,所有集成对象的变更都在这个工作区执行,状态固定写入它自己的专属状态文件。
- 原来的跨资源依赖编排逻辑,不要做成「单个上层模块嵌套调用两个底层模块、一次apply同时创建两类资源」的形式,改成工作区层面的调度:需要创建绑定S3的存储集成时,先在S3工作区执行apply创建桶,通过输出值或者数据源拿到S3桶的名称、关联IAM角色ARN等必要属性,再切到Storage Integration工作区,把拿到的S3属性作为入参传入模块创建集成对象即可。
- 如果需要一键执行全链路编排,写个简单的Shell/Python脚本按顺序调用不同工作区的
terraform apply命令就行,不需要改动现有底层模块、上层模块的封装逻辑。
给个参考目录结构:
infrastructure/ ├── workspaces/ │ ├── s3/ # S3专属工作区 │ │ ├── main.tf # 配置backend绑定S3专属状态,仅调用S3底层模块 │ │ └── outputs.tf # 输出桶名、访问角色等属性供其他工作区调用 │ └── snowflake_storage_int/ # 存储集成专属工作区 │ ├── main.tf # 配置backend绑定自身专属状态,仅调用存储集成底层模块 │ └── variables.tf # 定义入参接收S3相关属性 └── modules/ ├── s3/ # 现有S3底层模块,无需改动 ├── snowflake_storage_int/ # 现有存储集成底层模块,无需改动 └── orchestration/ # 现有上层编排模块可保留,仅作为逻辑参考,不要在单个根模块里直接调用它跨两类资源的创建逻辑
注意避坑:不要尝试在同一个根模块里用
terraform_remote_state加载其他状态再嵌套调用多类资源的模块,这种方式下新创建的资源还是会写入当前根模块绑定的状态,根本达不到分流的效果。
内容的提问来源于stack exchange,提问作者NickW
相关产品推荐
相关产品推荐

