You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Terraform plan误删重建Azure SQL数据库问题排查

问题根因

从plan输出可以直接定位核心问题:你把配置里Azure SQL相关资源从旧版azurerm_sql_*系列资源类型,替换成了新版azurerm_mssql_*系列,Terraform将两类资源判定为完全独立、无关联的资源,因此生成了删除旧资源、创建新资源的执行计划。

Terraform判断两个资源是否为同一个实体,从来不是看Azure侧的资源ID、资源名称,而是看「资源类型+资源在模块内的地址」。你当前状态文件里存的都是旧类型的资源记录:

  • SQL Server:azurerm_sql_server.tenant_sql
  • 数据库:azurerm_sql_database.tenant_sqldb
  • 虚拟网络规则:azurerm_sql_virtual_network_rule.*
  • AAD管理员:azurerm_sql_active_directory_administrator.tenant_sql_aad_admin

但你现在配置里写的全是azurerm_mssql_前缀的新类型资源,Terraform在状态里找不到对应地址的记录,就会判定这些是需要新建的资源;反过来,状态里留存的旧azurerm_sql_*资源在当前配置里已经找不到对应定义,自然会被标记为待删除。

你之前加的lifecycle.prevent_destroy规则没生效也很正常:这个规则是加在新的azurerm_mssql_*资源块上的,只能约束新的mssql资源的删除行为,根本管不到状态里已经存在的旧azurerm_sql_*资源,拦不住删除操作完全符合预期。

通用排查机制

遇到非预期的重建/删除计划,按以下顺序定位即可:

  • 先执行terraform state list导出当前状态文件里所有留存的资源地址,和本地配置里定义的资源地址逐行比对。只要配置里不存在对应地址的资源定义,Terraform就一定会生成删除计划,和资源本身的参数有没有变没有关系。
  • 如果是同地址同类型的资源被标记为重建,执行terraform plan -out=tfplan && terraform show tfplan查看该资源的所有属性变更项,被标记为# forces replacement的属性,就是触发强制重建的直接依据。
  • 不要只看资源名称、云上资源ID这类业务属性,Terraform的调度逻辑完全基于状态文件和配置的资源地址匹配,和云侧实际资源属性无关。
修复步骤(零数据库删除风险)
  1. 当下绝对不要执行terraform apply,先备份状态文件:执行terraform state pull > tfstate.backup把当前状态存到本地安全位置,所有状态操作失误都可以用这个备份回滚。
  2. 不需要回滚配置,用terraform state mv命令把状态里的旧资源记录迁移到新的mssql资源地址下,让Terraform识别到这是同一个资源,不需要删了重建。按你贴的资源清单,依次执行以下命令:
# 迁移SQL Server主资源
terraform state mv 'module.tenant_infrastructure.azurerm_sql_server.tenant_sql' 'module.tenant_infrastructure.azurerm_mssql_server.tenant_sql'

# 迁移数据库资源
terraform state mv 'module.tenant_infrastructure.azurerm_sql_database.tenant_sqldb' 'module.tenant_infrastructure.azurerm_mssql_database.tenant_sqldb'

# 迁移管理子网虚拟网络规则
terraform state mv 'module.tenant_infrastructure.azurerm_sql_virtual_network_rule.tenant_sql_subnet_rule_management_access' 'module.tenant_infrastructure.azurerm_mssql_virtual_network_rule.tenant_sql_subnet_rule_management_access'

# 迁移业务子网虚拟网络规则
terraform state mv 'module.tenant_infrastructure.azurerm_sql_virtual_network_rule.tenant_sql_subnet_rule_tenant_access' 'module.tenant_infrastructure.azurerm_mssql_virtual_network_rule.tenant_sql_subnet_rule_tenant_access'
  1. 处理AAD管理员配置:你现在把AAD管理员配置内嵌到了azurerm_mssql_server的azuread_administrator块里,不再是独立资源,所以需要把状态里旧的独立AAD管理员资源记录移除,执行以下命令即可——这个操作只会修改本地状态文件,不会删除云上的实际AAD管理员配置:
terraform state rm 'module.tenant_infrastructure.azurerm_sql_active_directory_administrator.tenant_sql_aad_admin'
  1. 所有状态操作完成后,重新执行terraform plan,此时不会再出现SQL相关资源的删除、重建计划,最多只会有少量属性的原地更新(新旧资源的Schema差异导致),确认所有变更项都符合预期、没有核心资源删除操作后,再执行apply即可。
  2. 长期防护:在Terraform流水线里加plan结果校验规则,只要plan输出里出现数据库、存储等核心资源的will be destroyed标记,直接阻断流水线,必须人工二次审核确认后才能继续执行。

内容的提问来源于stack exchange,提问作者iasksillyquestions

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.31 20:15:44