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

将多块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对应地址,步骤如下:

  1. 保留原有资源代码,不要替换为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\"]"
    
  2. 将原有资源代码替换为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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 18:35:57