重构Terraform代码后ECR仓库被误删重建问题求助
在TFE v1.13中有如下重复冗余但功能正常的代码:
resource "aws_ecr_repository" "repository-a" { name = "repo-a" #skipped } resource "aws_ecr_repository" "repository-b" { name = "repo-b" #skipped } resource "aws_ecr_repository" "repository-c" { name = "repo-c" #skipped }
重构为使用for_each批量管理的形式后:
locals { repo_table = [ { repo_id = "repo-id-a" repo_name = "repo-a" }, { repo_id = "repo-id-b" repo_name = "repo-b" }, { repo_id = "repo-id-c" repo_name = "repo-c" } ] } resource "aws_ecr_repository" "repositories" { for_each = {for repo in local.repo_table : repo.repo_id => repo } name = each.value.repo_name #skipped }
执行terraform apply时,每个仓库都触发两组错误:
Error: ECR Repository (repo-a) not empty, consider using force_delete: RepositoryNotEmptyException: The repository with name 'repo-a' in registry with id '123456789' cannot be deleted because it still contains images
Error: creating ECR Repository (repo-a): RepositoryAlreadyExistsException: The repository with name 'repo-a' already exists in the registry with id '123456789'
原因是Terraform把新旧资源判定为完全不同的实体,试图删除旧仓库再重建同名新仓库,但旧仓库有镜像无法删除,且同名仓库已存在导致创建失败。需要在重构代码的同时保留现有仓库和镜像。
核心是把旧资源的Terraform状态迁移到新的for_each管理的资源地址上,让Terraform认可新配置对应已有的旧资源,避免删除重建。具体步骤:
先执行
terraform plan确认差异
这一步会看到Terraform计划删除旧的aws_ecr_repository.repository-a等资源,创建新的aws_ecr_repository.repositories["repo-id-a"]等资源,记好这些资源地址的对应关系。逐个迁移资源状态
使用terraform state mv命令把旧资源的状态移到新资源地址:terraform state mv aws_ecr_repository.repository-a aws_ecr_repository.repositories["repo-id-a"] terraform state mv aws_ecr_repository.repository-b aws_ecr_repository.repositories["repo-id-b"] terraform state mv aws_ecr_repository.repository-c aws_ecr_repository.repositories["repo-id-c"]再次执行
terraform plan验证
正常情况下会显示No changes. Your infrastructure matches the configuration.,说明Terraform已经把新配置和现有基础设施对应上了,不会再做删除或创建操作。最后执行
terraform apply完成重构
此时不会有资源变更,只是更新配置,现有仓库和镜像完全保留。
额外注意:
- 要保证
for_each里的repo_id和迁移命令中的索引完全一致,比如repo-id-a必须对应新资源的键。 - 如果用的是TFE(Terraform Enterprise),要在对应的工作区执行这些命令,或者通过TFE的UI/API完成状态迁移。
内容的提问来源于stack exchange,提问作者AlexK

