4. 成本分配与标签治理

在 Databricks 的 AIFinOps 实践中,账单本身只告诉我们“某个 SKU 在某段时间花了多少钱”,它并不会自动回答“这笔钱属于哪个业务、哪个项目、哪个团队、哪个作业、哪个模型”。成本分配与标签治理要解决的核心问题,就是建立一套稳定、可继承、可审计的标签体系,把云账单中的费用行,逐层归因到组织真正关心的对象上。没有标签治理,成本优化就只能停留在“总账单降了多少”的粗粒度层面;有了标签治理,才能回答“推荐模型推理成本为什么比上周高了 18%”“哪个团队的 Notebook 集群在空转”这类可行动的问题。

一、三层标签模型:业务、项目、成本中心

标签设计的第一步不是打开控制台,而是先定义归因维度。推荐采用三层结构,每层承担不同职责,避免把所有信息塞进一个键值对。

  • 业务标签(business_unit / domain):回答“这笔钱属于哪条业务线或产品域”,例如 business_unit=retail_banking、domain=risk_modeling。它通常变化频率低,是财务分摊和预算对比的主维度。
  • 项目标签(project / cost_center):回答“这笔钱属于哪个项目或成本中心”,例如 project=churn_prediction_v2、cost_center=CC-2041。项目有生命周期,适合做项目级预算和 ROI 核算。
  • 技术归因标签(team / job / model / env):回答“这笔钱由谁、用什么、在哪个环境产生”,例如 team=ml-platform、job_id=etl_daily_0421、model=llm-rag-prod、env=prod。它变化频率高,是作业级和模型级归因的关键。

三层之间是“继承 + 覆盖”的关系:业务标签和成本中心通常由工作空间或集群策略统一注入,项目标签由项目负责人在创建资源时指定,技术归因标签则由作业、模型服务或集群配置自动带上。这样既能保证财务口径统一,又能保留工程侧细粒度追踪能力。

从账单到团队 / 作业 / 模型的标签归因链路 云账单 / 用量明细 DBU 用量行 workspace / sku / 时间 云资源费用行 VM / 存储 / 网络 Serverless 费用 SQL / 模型服务 标签元数据 cluster / job / model 原始费用行本身不含业务语义 标签治理与归因引擎 标签规范校验 键名 / 枚举值 / 必填项 继承与覆盖规则 workspace → cluster → job 未打标费用识别 untagged / 默认桶 归因映射表 费用行 → 团队 / 作业 / 模型 归因结果与责任对象 团队维度 team=ml-platform → 本月 $12,480 作业维度 job_id=etl_daily_0421 → $3,210 模型维度 model=llm-rag-prod → $5,760 成本中心维度 cost_center=CC-2041 → $9,870 关键原则:标签在资源创建时注入,账单生成后只做映射与校验,不做事后猜测

二、标签规范:键名、枚举值与必填约束

标签治理失败最常见的原因不是“没打标签”,而是“标签打得五花八门”。同一个团队可能同时出现 team=ML、Team=ml、owner=ml-platform 三种写法,导致账单聚合时无法对齐。因此必须先把标签规范固化成可校验的契约。

建议在 Databricks 中通过集群策略(Cluster Policy)和作业配置强制注入以下必填标签:

# 集群策略中强制注入的标签示例(custom_tags)
business_unit: "retail_banking"      # 必填,枚举值
cost_center:   "CC-2041"             # 必填,格式 CC-四位数字
project:       "churn_prediction_v2" # 必填,项目代号
team:          "ml-platform"         # 必填,团队短名
env:           "prod"                # 必填,枚举:dev/staging/prod
owner:         "zhangsan@corp.com"   # 必填,资源负责人邮箱

对于作业级归因,还需要在作业定义中追加 job_id 和 model 标签。Databricks 的作业集群会自动继承作业标签,因此只要在作业创建时写入,后续每次运行产生的 DBU 费用行都会带上这些键值。模型服务(Model Serving)则通过端点配置中的 custom_tags 注入 model 和 model_version,从而把推理费用精确落到具体模型版本上。

标签键名统一使用小写加下划线,枚举值统一使用小写短横线或下划线,避免大小写和空格导致的聚合分裂。所有必填标签缺失时,资源创建应被策略拒绝,而不是事后补录。

三、从账单到归因:映射与校验的实际过程

账单生成后,费用行本身只携带云厂商和 Databricks 的原始字段。要实现精准归因,需要把账单与标签元数据做关联。实际做法通常分三步:

  1. 抽取标签元数据:通过 Databricks REST API 或系统表 system.billing.usage 获取每个 cluster_id、job_id、warehouse_id 对应的标签集合。系统表本身已经包含 custom_tags 字段,可以直接展开。
  2. 关联费用行:以 usage_date + workspace_id + cluster_id / job_id 为键,把 system.billing.usage 中的 usage_quantity(DBU)与 list_price 关联,得到每条费用行的金额和标签。
  3. 未打标费用识别:对 custom_tags 为空的费用行,归入 untagged 桶,并按 workspace 和 SKU 汇总,作为治理待办清单。

下面是一段可直接在 Databricks SQL 中运行的归因查询示例,用于按团队和项目汇总本月费用:

SELECT
  custom_tags['business_unit'] AS business_unit,
  custom_tags['project']       AS project,
  custom_tags['team']          AS team,
  custom_tags['cost_center']   AS cost_center,
  SUM(usage_quantity * list_price) AS estimated_cost_usd
FROM system.billing.usage
WHERE usage_date >= DATE_TRUNC('MONTH', CURRENT_DATE())
  AND custom_tags['env'] = 'prod'
GROUP BY 1, 2, 3, 4
ORDER BY estimated_cost_usd DESC;

查询结果中如果出现 business_unit = NULL 或 team = NULL 的行,说明存在未打标资源。此时不要直接把这些费用平均分摊,而应回到资源侧补齐标签,再重新生成归因结果。平均分摊会掩盖真实责任,导致后续优化动作无法落地。

四、标签治理的持续运营

标签不是一次性配置,而是需要持续运营的资产。建议建立三个例行动作:

  • 周度未打标巡检:每周检查 untagged 费用占比,目标控制在总费用的 3% 以内。超过阈值时,按 workspace 和资源类型定位缺失标签的集群或作业。
  • 标签变更审计:记录标签键值的变更历史,尤其是 project 和 cost_center 的变更,避免项目切换时历史费用被错误重分类。
  • 归因结果对账:每月将标签归因结果与财务实际账单做一次总额对账,确认归因覆盖率,并对差异部分给出解释。
不要用“资源名称”代替标签做归因。资源名称可以随意修改且不保证唯一,而标签是结构化、可校验、可继承的元数据。依赖名称解析会在资源重建或重命名后立即失效。

当标签体系稳定运行后,成本分配就从“月底财务追着问”变成“每天看板自动回答”。团队可以看到自己名下的作业和模型花了多少钱,项目负责人可以看到项目预算消耗进度,财务可以按成本中心直接出分摊报表。更重要的是,当某个模型推理成本异常上升时,可以沿着 model → job_id → team → cost_center 这条链路快速定位到具体端点、具体版本和具体负责人,让成本优化从“猜”变成“查”。