[TOOLS] 16 分鐘閱讀OraCore 編輯部

Databricks 端點讓你少猜

我拆 Databricks 自訂模型服務端點的權限、Registry、流量與部署模板,整理成可直接照抄的實作清單。

分享 LinkedIn
Databricks 端點讓你少猜

這篇把 Databricks 自訂模型服務端點的權限、Registry、流量與部署模板整理成可直接照抄的版本。

我用 Databricks 模型服務一陣子了,越用越覺得它不是不行,是很會把人搞到懷疑自己。端點建起來看起來很順,結果一更新就冒出 PERMISSION_DENIED;明明模型有掛上去,卻因為建立者身份、Unity Catalog 權限、還有那個會依模型所在位置變來變去的表單,整個流程卡得像老電腦。我本來以為這只是 UI 難用,後來才發現根本不是。它是在逼你把「誰建立、誰擁有、誰能更新」這三件事先講清楚,不然就等著踩雷。

這次我拆的是 Databricks 官方文件 Create custom model serving endpoints,搭配 Model Serving 總覽權限說明,還有 Databricks Python SDK。文件本身有寫,但真正會害你出事的,通常不是功能,而是那些看起來像細節、其實是地雷的地方。官方沒給觀看數或星數,我就不亂掰了。

先別急著建端點,先搞清楚誰在背鍋

訂閱 AI 趨勢週報

每週精選模型發布、工具應用與深度分析,直送信箱。不定期,不騷擾。

不會寄垃圾信,隨時可取消。

當你建立端點時,Databricks 會把呼叫者身分記成端點建立者。這個身分通常是 service principal,之後會代表端點去存取 Unity Catalog 資源,而且建立後不能改。

白話就是:你以為你是在建一個端點,Databricks 其實是在記錄「這個端點以後算誰的」。這個人不是備註欄位,不是裝飾,是之後更新、查權限、碰 UC 資源時會被拿來驗證的身分。你如果用某個工程師的個人帳號去建,三天後他離開團隊,端點就會開始用最難看的方式提醒你:當初不該偷懶。

Databricks 端點讓你少猜

我之前就遇過一個很煩的案例。團隊趕著上線,直接用值班同仁的帳號把端點建起來,當下都正常。結果那位同仁調組後,某次更新直接炸掉,錯誤就是 PERMISSION_DENIED。那時候大家還以為是模型版本壞掉,查半天才發現是建立者身分已經不在 workspace 裡了。這種問題最討厭的地方不是難修,是它看起來像隨機故障。

實操寫法很簡單:建立端點時,優先用 service principal,不要拿人類帳號硬上。然後把這個 service principal 當成長期資產管理,確保它還留在 workspace、還有需要的權限、還能碰得到 Unity Catalog。要是你已經用錯身分建了,別幻想可以局部補救,官方的做法就是刪掉重建,讓正確的身分重新成為建立者。

  • 建立端點的人,最好固定是 service principal。
  • 這個身分要保留 workspace membership。
  • 更新前先假設建立者權限會被重新檢查。

表單不是在問好玩,它是在分流你的模型來源

點進 Entity 欄位後,選取要服務的實體表單。依照模型註冊位置,選擇 My models - Unity Catalog 或 My models - Model Registry。表單會依你的選擇動態更新。

這段很容易被忽略,因為 UI 看起來像只是多問你一個選項,但它其實是在先問:你的模型到底放哪裡。放在 Unity Catalog,還是放在 Workspace Model Registry,後面整套路徑、權限、版本解析都不一樣。你如果心裡沒先定義清楚,後面就會一直在那邊猜,猜到最後只是在跟錯誤訊息對話。

我現在會把這件事當成第一個決策點,不是最後一步。原因很簡單,因為 Databricks 並不是用同一套邏輯處理兩種 Registry。Unity Catalog 要的是完整的 catalog.schema.model_name,workspace registry 則走另一條路。你如果把這兩個世界混在一起,端點看似建立成功,實際上只是把未來的自己推去撞牆。

實操寫法:先決定模型歸屬,再去填端點。模型在 Unity Catalog,就老老實實用完整名稱;模型在 Workspace Model Registry,就在 UI 選對來源,不要硬把兩邊的命名習慣混用。這不是格式潔癖,這是避免你之後在權限與版本上來回試錯。

  • Unity Catalog 模型:用完整路徑 catalog.schema.model_name
  • Workspace Model Registry:先選對來源,再填版本。
  • 建立前先確認你要的是哪一版模型,不要靠印象。

權限不是一次檢查完就沒事,它會在兩個時間點咬你

我覺得 Databricks 最值得記住的地方,就是它把權限分成兩種時機在檢查。第一種是建立或更新端點時,第二種是實際有流量打進來時。很多人只看前者,然後在 production 被後者補刀,還一頭霧水。

Databricks 端點讓你少猜

如果你服務的是 Unity Catalog 模型,建立者至少要有 USE CATALOGUSE SCHEMAEXECUTE 這幾個權限。模型如果還依賴其他函式,連上游函式的 EXECUTE 也要一併有。少一個,建立或更新就可能直接失敗。這裡不是「最好有」,是「沒給就別想過」。

我以前最常看到的錯誤,就是大家只去補模型本身的權限,忘了 schema。結果 endpoint 建不過,還以為是 UI 壞掉。其實不是,Databricks 只是照規則檢查而已。只是這規則很不客氣,錯了就直接拒絕,不會幫你猜。

實操寫法:先做一份建立者權限清單,包含 catalog、schema、model、上游函式。你可以把它當成部署前檢查表,先確認再動手。然後記得,端點建立成功不代表萬事大吉,query-time 的權限還是可能在實際請求時失敗,所以要把「能建立」跟「能穩定服務」分開看。

  • 先檢查建立者是不是 workspace 成員。
  • 再檢查 UC 權限鏈。
  • 建立成功後,還要另外測實際查詢。

流量分配跟併發,才是你真正要算的帳

Databricks 提供 traffic split 和 compute sizing,這其實就是在叫你別再憑感覺配資源。你可以把流量切到不同 served entity,也可以依照模型吞吐量去選擇併發規模。官方甚至直接丟了一個很實在的估算方式:併發數大概抓 QPS x model run time

這句我很買單,因為它把很多人愛講的「先開小一點看看」直接打回去。你如果知道 QPS,知道單次推論時間,就可以開始算了,不用靠運氣。像一個請求 200 毫秒、每秒 20 個請求的模型,跟一個每次要 3 秒的模型,資源需求根本不是同一個量級。你不先算,最後就是 latency 跟成本一起爆。

實際上我看過不少團隊把 endpoint 開得很小,測試時都沒事,正式流量一進來就開始抖。問題不是模型不行,是你根本沒用真實負載去配。Databricks 有 Small、Medium、Large 這些範圍,API 和 SDK 也能設自訂併發;如果你要用自訂值,記得要是 4 的倍數,這種小規則不先記起來,就很容易卡在奇怪的地方。

實操寫法:先用觀察到的 QPS 和平均推論時間算出大概需要的併發,再選最小但不會卡住的配置。如果你要同時跑多個版本,就明確切 traffic split,不要把版本混成一團。要做自動化,就用 REST API 或 SDK,不要每次都靠 UI 手動改,久了只會漂移。

  • Small:適合 0 到 4 個請求。
  • Medium:適合 8 到 16 個請求。
  • Large:適合 16 到 64 個請求。

Scale to zero 很省錢,但 production 會記恨你

官方對這件事講得很直接:scale to zero 不建議拿來做 production endpoint,因為冷啟動時不保證容量,流量回來時你會先吃到延遲。這不是理論問題,是使用者真的會感受到的問題。

我不反對 scale to zero,我自己也會拿來做 demo、測試環境,或那種偶爾才會被打到的端點。但如果這條端點是產品流程的一部分,我就不想賭。因為第一個請求慢,不只是慢而已,它會讓整個體驗看起來很不穩。你省下來的錢,常常是拿使用者耐心去換的。

實操寫法:低風險、低頻率的 workload 可以留著 scale to zero;正式上線、重視回應時間的路徑就關掉。你如果很在意首請求延遲,別省那點錢。這不是道德選擇,是成本跟體驗的取捨。

同一件事有四種入口,方便,但也很容易抄錯

Databricks 讓你可以用 Serving UI、REST API、MLflow Deployments SDK,或 Databricks Workspace Client SDK 來建立端點。這種彈性我承認很方便,但也很容易讓人把不同情境的範例混著抄,最後配置語法對不上。

我自己的做法是,正式自動化只選一條路走到底。UI 適合第一次摸、快速驗證;REST API 比較像基礎設施操作,配置明確;SDK 則適合 Python 腳本化部署。每條路都能做同一件事,但你最好只挑一條當主線,不然之後排查差異會很痛苦。

實操寫法:如果你要做 production,先決定團隊標準是 API 還是 SDK,然後把範例固化。不要今天 UI 建、明天 API 改、後天又手動補設定。那種做法短期看起來快,長期就是 config drift 的溫床。

  • UI:適合人工檢查與快速試錯。
  • REST API:適合明確可追蹤的部署設定。
  • MLflow Deployments SDK / Workspace Client SDK:適合 Python 自動化。

GPU 不是勾一下就好,版本不對一樣白搭

如果你要走 GPU serving,Databricks 不是只給你一個勾選框而已,它還會看你套件版本合不合。官方列得很清楚:PyTorch 1.13.0 到 2.0.1、TensorFlow 2.5.0 到 2.13.0、MLflow 2.4.0 以上。版本不在範圍內,別幻想只是小問題。

這點我很有感,因為很多模型在本機或訓練環境跑得好好的,一搬到服務端就開始出現相依性問題。GPU endpoint 需要對應的 workload type,像 GPU_SMALL 這種設定也不是裝飾。你如果只看到 GPU 兩個字就衝,很容易在上線前才發現 runtime 不合。

實操寫法:先盤點模型使用的套件版本,再決定要不要上 GPU。版本在支援範圍邊緣的,先升級或固定版本,別邊跑邊賭。接著再把 workload type、workload size 一起設好,最後用真實請求把整條路測過一次,不要只驗 artifact 能不能載入。

我也順手把常用參考放這裡:MLflow DeploymentsDatabricks Workspace Client SDKModel Serving 總覽權限說明。這些連結我自己也會留著,因為單看一頁常常會漏掉上下文。

可抄的模板

# Databricks 自訂模型服務端點檢查表

## 建立前先確認
- 先決定模型是在 Unity Catalog,還是在 Workspace Model Registry。
- 端點建立者請固定用 service principal。
- 確認這個身分還在 workspace,且有 workspace-access entitlement。
- 如果是 Unity Catalog 模型,請先確認:
  - catalog 上有 USE CATALOG
  - schema 上有 USE SCHEMA
  - model 上有 EXECUTE
  - 若有上游函式,也要有 EXECUTE

## UI 建立流程
1. 打開 Databricks 側邊欄的 Serving。
2. 點 Create serving endpoint。
3. 輸入端點名稱。
4. 在 Entity 欄位選擇:
   - My models - Unity Catalog,或
   - My models - Model Registry
5. 選模型與版本。
6. 設定 traffic percentage。
7. 選 CPU 或 GPU compute。
8. 設定 compute scale-out:
   - Small:0-4 requests
   - Medium:8-16 requests
   - Large:16-64 requests
9. 產品環境不要開 scale to zero。
10. 視需要加上:
    - served entity 重新命名
    - instance profile
    - environment variables
    - inference table logging
11. 需要多版本就再加 served entities。
12. 流量高就開 route optimization。
13. 需要的話再配 AI Gateway。
14. 按 Create。

## REST API 範例
POST /api/2.0/serving-endpoints
{
  "name": "uc-model-endpoint",
  "config": {
    "served_entities": [
      {
        "name": "ads-entity",
        "entity_name": "catalog.schema.my-ads-model",
        "entity_version": "3",
        "min_provisioned_concurrency": 4,
        "max_provisioned_concurrency": 12,
        "scale_to_zero_enabled": false
      }
    ]
  }
}

## MLflow Deployments 範例
import mlflow
from mlflow.deployments import get_deploy_client

mlflow.set_registry_uri("databricks-uc")
client = get_deploy_client("databricks")
endpoint = client.create_endpoint(
    name="unity-catalog-model-endpoint",
    config={
        "served_entities": [
            {
                "name": "ads-entity",
                "entity_name": "catalog.schema.my-ads-model",
                "entity_version": "3",
                "min_provisioned_concurrency": 4,
                "max_provisioned_concurrency": 12,
                "scale_to_zero_enabled": False,
            }
        ]
    },
)

## Workspace Client SDK 範例
from databricks.sdk import WorkspaceClient
from databricks.sdk.service.serving import EndpointCoreConfigInput, ServedEntityInput

w = WorkspaceClient()
w.serving_endpoints.create(
    name="uc-model-endpoint",
    config=EndpointCoreConfigInput(
        served_entities=[
            ServedEntityInput(
                name="ads-entity",
                entity_name="catalog.schema.my-ads-model",
                entity_version="3",
                workload_size="Small",
                scale_to_zero_enabled=False,
            )
        ]
    ),
)

## GPU 端點範例
POST /api/2.0/serving-endpoints
{
  "name": "gpu-model-endpoint",
  "config": {
    "served_entities": [
      {
        "entity_name": "catalog.schema.my-gpu-model",
        "entity_version": "1",
        "workload_type": "GPU_SMALL",
        "workload_size": "Small",
        "scale_to_zero_enabled": false
      }
    ]
  }
}

## 營運規則
- 同一個團隊盡量固定一條部署路徑。
- 端點建立者身分要穩定。
- 若建立者失去 workspace membership,更新很可能失敗。
- scale to zero 當成成本選項,不要當 production 預設。
- 每次改端點設定,都重查權限。
- 建立成功不代表查詢一定成功,查詢權限要另外測。

這份模板就是我把官方文件拆完後,留下來真的能用的版本。你可以直接拿去當部署前檢查表,至少不會再把「誰建立的」和「誰能更新」這兩件事搞混。

來源主要來自 Databricks 官方文件 Create custom model serving endpoints。我這篇的重點整理、風險提醒、與可抄模板是我自己重新整理的,原始規則與介面說明則以官方文件為準。