将多块databricks_catalog转为for_each循环后,如何避免资源误销毁?
问题描述
原有多块databricks_catalog资源代码:
resource "databricks_catalog" "sf_bronze_bc_westeurope_managed_catalog" { owner = "mip-admin-group" name = "sf_bronze" } resource "databricks_catalog" "sf_deltasharing_bc_westeurope_managed_catalog" { owner = "mip-admin-group" name = "sf_deltasharing" }
重构为for_each循环写法:
resource "databricks_catalog" "this" { for_each = var.catalog name = each.key owner = each.value.catalog_owner }
对应的variables.tf定义:
variable "catalog" { type = map(object({ catalog_grants = optional(map(list(string))) catalog_owner = optional(string) # Username/groupname/sp application_id of the catalog owner. catalog_storage_root = optional(string) # Location in cloud storage where data for managed tables will be stored catalog_isolation_mode = optional(string, "OPEN") # Whether the catalog is accessible from all workspaces or a specific set of workspaces. Can be ISOLATED or OPEN. catalog_comment = optional(string) # User-supplied free-form text catalog_properties = optional(map(string)) # Extensible Catalog Tags. schema_name = optional(list(string)) # List of Schema names relative to parent catalog. schema_grants = optional(map(list(string))) schema_owner = optional(string) # Username/groupname/sp application_id of the schema owner. schema_comment = optional(string) schema_properties = optional(map(string)) })) default = { sf_bronze = { catalog_owner = "mip-admin-group" } sf_deltasharing= { catalog_owner = "mip-admin-group" } } }
执行terraform plan时,Terraform会标记原有catalog为销毁,同时创建同名新资源。疑问点:
- 如何将原资源名称(
sf_bronze_bc_westeurope_managed_catalog、sf_deltasharing_bc_westeurope_managed_catalog)作为参数添加? - 是否是缺少原资源名称导致资源被标记为销毁?
- 资源名称是否作为Terraform状态中的基础设施标识符?
解答
核心原因:Terraform资源标识变更
Terraform状态中,资源的唯一标识是**资源类型.本地资源名称[for_each键](使用for_each时)或资源类型.本地资源名称**(单个资源):
- 原有资源的标识是
databricks_catalog.sf_bronze_bc_westeurope_managed_catalog和databricks_catalog.sf_deltasharing_bc_westeurope_managed_catalog - 重构后资源的标识是
databricks_catalog.this["sf_bronze"]和databricks_catalog.this["sf_deltasharing"]
两者是完全不同的资源地址,Terraform会判定原有资源已不再被代码定义,需要销毁;新的资源地址是全新的,需要创建。这和Databricks中catalog的名称无关,完全是Terraform状态标识不匹配导致的。
解决方法:迁移资源状态
要避免销毁重建,需要将原有状态中的资源地址迁移到新的for_each对应地址,步骤如下:
- 保留原有资源代码,不要替换为
for_each写法,执行以下状态迁移命令:terraform state mv "databricks_catalog.sf_bronze_bc_westeurope_managed_catalog" "databricks_catalog.this[\"sf_bronze\"]" terraform state mv "databricks_catalog.sf_deltasharing_bc_westeurope_managed_catalog" "databricks_catalog.this[\"sf_deltasharing\"]" - 将原有资源代码替换为
for_each的写法,再次执行terraform plan,此时Terraform会识别到状态中的资源地址已与新代码匹配,不会出现销毁重建操作。
关于资源名称的说明
Terraform中的本地资源名称(比如sf_bronze_bc_westeurope_managed_catalog)是Terraform内部用于标识状态资源的一部分,不属于Databricks catalog的属性,因此无法作为参数传递给databricks_catalog资源的字段。如果需要记录原本地名称信息,可以在变量的object结构中添加一个自定义字段(比如terraform_local_name),但该字段仅用于本地记录,不会同步到Databricks端。
内容的提问来源于stack exchange,提问作者Oliver Angelil
相关产品推荐
相关产品推荐

