Terraform创建ECR仓库报错:RepositoryAlreadyExistsException问题排查
问题:Terraform重复创建ECR仓库报错
场景概述
尝试通过Terraform部署两个基于Docker镜像的AWS Lambda函数,对应两个独立ECR仓库,文件夹结构如下:
- main.tf - variables.tf - lambda_functions/ - main.tf - ... - ecr_repository/ - main.tf - ...
ECR仓库模块代码(ecr_repository/main.tf)
resource "aws_ecr_repository" "converter_repo" { name = "cs-lambda-converter-repo-${var.environment}" force_delete = true } resource "aws_ecr_repository" "uploader_repo" { name = "cs-lambda-uploader-repo-${var.environment}" force_delete = true } output "converter_repo_url" { value = aws_ecr_repository.converter_repo.repository_url } output "uploader_repo_url" { value = aws_ecr_repository.uploader_repo.repository_url } output "converter_repo_name" { value = aws_ecr_repository.converter_repo.name } output "uploader_repo_name" { value = aws_ecr_repository.uploader_repo.name }
Lambda函数模块代码(lambda_functions/main.tf)
module "ecr_repository" { source = "../ecr_repository" environment = var.environment } locals { uploader_image_tag = "latest" converter_image_tag = "latest" } data "aws_ecr_image" "uploader_lambda_image" { depends_on = [ null_resource.ecr_uploader_image ] repository_name = module.ecr_repository.uploader_repo_name image_tag = local.uploader_image_tag } data "aws_ecr_image" "converter_lambda_image" { depends_on = [ null_resource.ecr_converter_image ] repository_name = module.ecr_repository.converter_repo_name image_tag = local.converter_image_tag } resource "null_resource" "ecr_uploader_image" { triggers = { python_file = md5(file("${var.lambda_uploader_path}/lambda_function.py")) docker_file = md5(file("${var.lambda_uploader_path}/Dockerfile")) } provisioner "local-exec" { command = <<EOF rm ~/.docker/config.json 2> /dev/null aws ecr get-login-password --region ${var.region} | docker login --username AWS --password-stdin ${data.aws_caller_identity.current.account_id}.dkr.ecr.${var.region}.amazonaws.com docker buildx build --platform linux/amd64 -t ${module.ecr_repository.uploader_repo_url}:${local.uploader_image_tag} . docker push ${module.ecr_repository.uploader_repo_url}:${local.uploader_image_tag} EOF interpreter = ["bash", "-c"] working_dir = var.lambda_uploader_path } } resource "null_resource" "ecr_converter_image" { triggers = { python_file = md5(file("${var.lambda_converter_path}/lambda_function.py")) docker_file = md5(file("${var.lambda_converter_path}/Dockerfile")) } provisioner "local-exec" { command = <<EOF rm ~/.docker/config.json 2> /dev/null aws ecr get-login-password --region ${var.region} | docker login --username AWS --password-stdin ${data.aws_caller_identity.current.account_id}.dkr.ecr.${var.region}.amazonaws.com docker buildx build --platform linux/amd64 -t ${module.ecr_repository.converter_repo_url}:${local.converter_image_tag} . docker push ${module.ecr_repository.converter_repo_url}:${local.converter_image_tag} EOF interpreter = ["bash", "-c"] working_dir = var.lambda_converter_path } } resource "aws_lambda_function" "pdf-uploader" { depends_on = [ null_resource.ecr_uploader_image ] function_name = "capsphere-ocr-uploader-${var.environment}" role = aws_iam_role.lambda-role.arn timeout = 300 memory_size = 512 image_uri = "${module.ecr_repository.uploader_repo_url}:${local.uploader_image_tag}" package_type = "Image" } resource "aws_lambda_function" "pdf-converter" { depends_on = [ null_resource.ecr_converter_image ] function_name = "capsphere-ocr-converter-${var.environment}" role = aws_iam_role.lambda-role.arn timeout = 300 memory_size = 512 image_uri = "${module.ecr_repository.converter_repo_url}:${local.converter_image_tag}" package_type = "Image" } output "uploader_lambda_name" { value = aws_lambda_function.pdf-uploader.function_name } output "converter_lambda_name" { value = aws_lambda_function.pdf-converter.function_name }
执行报错
Error: creating ECR Repository (cs-lambda-converter-repo-dev): RepositoryAlreadyExistsException: The repository with name 'cs-lambda-converter-repo-dev' already exists in the registry with id 'XXXXX' with module.lambda_functions.module.ecr_repository.aws_ecr_repository.converter_repo, on modules\ecr_repository\main.tf line 1, in resource "aws_ecr_repository" "converter_repo": 1: resource "aws_ecr_repository" "converter_repo" { Error: creating ECR Repository (cs-lambda-uploader-repo-dev): RepositoryAlreadyExistsException: The repository with name 'cs-lambda-uploader-repo-dev' already exists in the registry with id 'XXXXX' with module.ecr_repository.aws_ecr_repository.uploader_repo, on modules\ecr_repository\main.tf line 6, in resource "aws_ecr_repository" "uploader_repo": 6: resource "aws_ecr_repository" "uploader_repo" {
排查思路
- 检查模块重复调用:从报错信息可见,ECR仓库被两个不同模块实例创建——
module.lambda_functions.module.ecr_repository和module.ecr_repository,说明根目录main.tf大概率也直接调用了ecr_repository模块,和lambda_functions模块内部的调用形成重复创建。 - 核对Terraform状态:执行
terraform state list,查看状态中是否存在两个同名ECR仓库资源实例,确认重复定义的来源。 - 检查根模块代码:查看根目录
main.tf,是否存在独立调用ecr_repository模块的代码,比如:
若存在则会和module "ecr_repository" { source = "./ecr_repository" environment = var.environment }lambda_functions模块内的调用冲突。
解决方法
方法1:移除重复的模块调用
推荐将ECR模块的调用放在根模块,通过变量传递输出值给lambda_functions模块,避免嵌套调用重复创建:
- 调整根目录
main.tf:module "ecr_repository" { source = "./ecr_repository" environment = var.environment } module "lambda_functions" { source = "./lambda_functions" environment = var.environment region = var.region lambda_uploader_path = var.lambda_uploader_path lambda_converter_path = var.lambda_converter_path # 传递ECR仓库的输出值 uploader_repo_url = module.ecr_repository.uploader_repo_url uploader_repo_name = module.ecr_repository.uploader_repo_name converter_repo_url = module.ecr_repository.converter_repo_url converter_repo_name = module.ecr_repository.converter_repo_name } - 修改
lambda_functions/main.tf,移除内部的ecr_repository模块调用,改用变量接收:variable "uploader_repo_url" {} variable "uploader_repo_name" {} variable "converter_repo_url" {} variable "converter_repo_name" {} # 移除原来的module "ecr_repository"块 # 后续代码直接使用var.uploader_repo_url等变量替代原module调用
方法2:导入现有资源到Terraform状态
如果ECR仓库已存在且需要保留,执行terraform import将现有仓库导入状态,避免重复创建:
# 根据实际保留的模块路径选择,比如保留根模块调用则用module.ecr_repository terraform import module.ecr_repository.aws_ecr_repository.converter_repo cs-lambda-converter-repo-dev terraform import module.ecr_repository.aws_ecr_repository.uploader_repo cs-lambda-uploader-repo-dev
方法3:清理重复的状态条目
如果状态中存在重复资源实例,执行terraform state rm删除多余条目:
# 删除lambda模块内的重复ECR资源 terraform state rm module.lambda_functions.module.ecr_repository.aws_ecr_repository.converter_repo terraform state rm module.lambda_functions.module.ecr_repository.aws_ecr_repository.uploader_repo
内容的提问来源于stack exchange,提问作者clattenburg cake
相关产品推荐
相关产品推荐

