Terraform for_each创建ECR仓库时无法绑定仓库策略问题
问题根因
引用失败由三个配置错误导致:
- 根模块调用ECR子模块时使用了
for_each,module.ecr是多个模块实例的集合对象,不是单个实例,无法直接通过module.ecr.name获取属性 - ECR子模块没有配置输出项,外部资源无法直接读取子模块内部创建的ECR仓库属性
- 仓库策略资源没有做循环匹配,单条策略资源无法绑定多个通过for_each创建的ECR仓库实例
修复步骤
第一步:为ECR子模块添加输出配置
在../../modules/ecr目录下新建outputs.tf文件,将子模块内创建的ECR仓库名称对外暴露。由于子模块内aws_ecr_repository资源使用count做循环,输出按索引返回对应仓库名即可:
output "ecr_repo_name" { type = list(string) description = "已创建的ECR仓库名称列表" value = aws_ecr_repository.this[*].name }
注:当前配置下每个ECR子模块实例只创建1个ECR仓库,所以输出是长度为1的列表。如果后续调整子模块支持单实例创建多个仓库,只需要对应调整策略资源的循环逻辑即可。
如果后续需要引用仓库ARN等其他属性,也可以按相同逻辑添加输出项,例如取值aws_ecr_repository.this[*].arn
第二步:调整根模块的仓库策略资源,和模块实例一一绑定
根模块内的aws_ecr_repository_policy不能写为单条资源,需要和ECR模块使用完全一致的for_each集合,确保每个ECR仓库实例对应一条独立的策略资源,正确引用子模块输出的仓库名:
# for_each集合和module "ecr"的for_each完全一致,保证实例键一一对应 resource "aws_ecr_repository_policy" "repo_policy" { for_each = { for repos in var.app_ecr_repo : join("-", [repos.name]) => repos } # 每个模块实例仅创建1个ECR仓库,取输出列表的第0个元素即为对应仓库名 repository = module.ecr[each.key].ecr_repo_name[0] policy = <<EOF { "Version": "2008-10-17", "Statement": [ { "Sid": "new policy", "Effect": "Allow", "Principal": "*", "Action": [ "ecr:GetDownloadUrlForLayer", "ecr:BatchGetImage", "ecr:BatchCheckLayerAvailability", "ecr:PutImage", "ecr:InitiateLayerUpload", "ecr:UploadLayerPart", "ecr:CompleteLayerUpload", "ecr:DescribeRepositories", "ecr:GetRepositoryPolicy", "ecr:ListImages", "ecr:DeleteRepository", "ecr:BatchDeleteImage", "ecr:SetRepositoryPolicy", "ecr:DeleteRepositoryPolicy" ] } ] } EOF }
可选优化方案(推荐)
当前子模块已经在内部管理ECR生命周期策略,更合理的实践是把aws_ecr_repository_policy也放到ECR子模块内部维护,不需要跨模块引用,资源逻辑更内聚,也不会出现引用错配问题:
- 给子模块新增可选变量,用来控制是否启用仓库策略、传入策略内容
- 子模块内直接使用
count和现有aws_ecr_repository资源对齐创建策略,repository参数直接引用同模块内的aws_ecr_repository.this[count.index].name即可,无需跨模块传值。
内容的提问来源于stack exchange,提问作者Veera
相关产品推荐
相关产品推荐

