dbt 部署與環境管理

在 dbt 的旅程中,我們大部分時間都在本地端 (Local) 進行開發與測試。然而,要讓數據產生真正的商業價值,我們必須將這些經過驗證的程式碼「部署」到生產環境 (Production),並建立自動化的執行流程。

本章節將深入探討如何管理不同環境 (profiles.yml)、使用最強大的指令 (dbt build)、以及如何建立現代化的 CI/CD 流程。

環境管理 profiles.yml

dbt 使用 profiles.yml 來管理資料庫連線資訊與環境設定。在實務上,我們至少會區分兩個環境:

  1. Development (Dev): 開發環境。每位開發者通常擁有自己獨立的 Schema (例如 dbt_alice),在這裡可以自由嘗試、破壞與重建,互不干擾。
  2. Production (Prod): 生產環境。通常使用統一且唯讀權限較高的 Schema (例如 analytics),只有通過自動化測試的程式碼才能寫入此處。

使用 Targets 切換環境

由於連線資訊不同,我們利用 Targets 來定義這些設定。以下是一個更進階、符合安全規範的 profiles.yml 範例:

my_company_dbt:
  target: dev # 預設使用 dev 環境
  outputs:
    # 開發環境:使用開發者個人憑證
    dev:
      type: bigquery
      method: oauth
      project: my-gcp-project-dev
      dataset: dbt_alice # 開發者個人 schema
      threads: 4

    # 生產環境:通常使用 Service Account
    prod:
      type: bigquery
      method: service-account
      project: my-gcp-project-prod
      dataset: analytics # 正式 schema
      keyfile: /path/to/service-account.json
      threads: 8

參數說明 (以 BigQuery 為例):

  • target: 預設要使用哪一個設定檔 (例如 dev),若執行指令沒加 --target 就會用這個。
  • method: 認證方式。
    • oauth: 開發者使用 gcloud auth login 後的憑證,免去管理 Key File 的麻煩,適合本機開發。
    • service-account: 伺服器端使用,需搭配 keyfile JSON 憑證路徑。
  • project: GCP 專案 ID (Billing Project)。
  • dataset: dbt 預設寫入的目標資料集 (對應其他資料庫的 Schema)。
  • threads: 平行處理的執行緒數量。設為 8 代表同時可以跑 8 個 models,加快執行速度。

安全性最佳實踐:使用環境變數

絕對不要將密碼或金鑰檔案路徑直接寫死 (Hard-code) 在 profiles.yml 並提交到 Git。這會造成嚴重的資安風險。

dbt 支援使用 env_var 函數來讀取環境變數。這才是正確的做法:

prod:
  type: postgres
  host: { { env_var('DBT_PROD_HOST') } }
  user: { { env_var('DBT_PROD_USER') } }
  pass: { { env_var('DBT_PROD_PASSWORD') } } # 從環境變數讀取密碼,安全!
  schema: analytics

在執行 dbt 之前,你可以在終端機或 CI/CD pipeline 中設定這些變數:

export DBT_PROD_PASSWORD='super_secret_password'
dbt run --target prod

使用 dbt build 進行部署

在 dbt 1.0 之前,部署腳本通常長這樣:

dbt seed
dbt run
dbt test
dbt snapshot

這種序列式執行的缺點是:如果 dbt run 成功建立了 Model A,但隨後的 dbt test 發現 Model A 數據有誤,這時候錯誤的數據已經留在資料庫裡供下游使用了。

dbt build 指令解決了這個問題。它會以 DAG (相依性圖) 的順序,針對每個資源依序執行: run -> test

dbt build 的運作邏輯

假設 Model B 依賴於 Model A。執行 dbt build 時:

  1. 執行 Model A (run)。
  2. 立刻 執行針對 Model A 的測試 (test)。
  3. 如果 Model A 測試失敗
    • 標記 Model A 為 Error。
    • 跳過 (Skip) Model B 的執行 (因為上游已經髒了)。
  4. 如果 Model A 測試通過
    • 繼續執行 Model B。

這種 Fail-fast (快速失敗) 機制確保了生產環境的資料品質,避免「垃圾進,垃圾出」。

在生產環境或 CI 流程中,請永遠使用 dbt build 代替 run + test

CI/CD 策略:自動化整合與部署

一個成熟的 dbt 專案,不應該由工程師手動在筆電上跑 dbt build --target prod 來更新資料。你需要自動化工具 (如 GitHub Actions, GitLab CI, dbt Cloud)。

Continuous Integration (CI):Slim CI

當你發起一個 Pull Request (PR) 時,CI 系統應該要自動檢查這段程式碼是否會壞掉。

除此之外,隨著專案變大,跑一次完整的 dbt build 可能要花一小時。我們不希望 PR 審查等這麼久。這時可以使用 dbt 的 Slim CI 功能,只跑有被修改的模型及其下游

dbt 透過比較當前程式碼與「上次成功的編譯結果 (Manifest)」來判斷哪些檔案被修改了 (state:modified)。

CI 指令範例:

# 1. 取得 master branch 的 manifest 檔案 (通常從 S3 下載)
aws s3 cp s3://my-dbt-artifacts/manifest.json ./state/

# 2. 只執行修改過的模型 (state:modified) 及其第一層下游 (+)
dbt build --select state:modified+ --state ./state

指令參數解析:

這段指令的白話文是:「請比較現在的程式碼與之前的版本,找出有修改的部分,並重新執行這些部分以及所有會被影響到的下游。

詳細拆解:

  1. --state ./state (與誰比): 告訴 dbt 去哪裡找「上次成功的紀錄」。我們通常會把上次在 Production 跑完的紀錄 (manifest.json) 下載到 ./state 資料夾給 dbt 參考。

    • 什麼是 manifest.json 這是 dbt 的「專案全景圖」。每當你執行 dbt compiledbt run 完畢,dbt 就會產生這個檔案,裡面詳細記錄了專案中所有的 models、tests、以及它們之間的依賴關係與設定。擁有它,dbt 才知道專案以前長什麼樣子。
  2. state:modified (誰改了): dbt 會自動比對現在的程式碼與 ./state 裡的紀錄。如果發現某個 model 的 SQL 或設定檔有變動,就會把它列入執行名單。

  3. + (影響誰): 這是 dbt 的選擇語法,代表「加上所有下游」。
    舉例:假設 Model B 讀取 Model A 的資料 (A -> B)。

    • 如果你修改了 A,但只跑 A,那麼 B 的資料可能就會變成舊的或錯誤的。
    • 加上 + 號 (state:modified+),dbt 就會聰明地執行 Model A 加上 Model B,確保整條資料鏈路都是最新的。

這樣可以將 CI 時間從數十分鐘縮短到幾分鐘,大幅提升開發效率。

Continuous Deployment (CD) vs Orchestration

在 dbt 的語境下,這兩個詞常被混用,但概念稍有不同:

  1. Deployment (部署):通常指將最新的 dbt project code 更新到執行環境,或是更新 dbt docs 靜態網站。這通常發生在 Merge to main branch 時。
  2. Orchestration (排程執行):指定期 (例如每天早上 8 點) 執行 dbt build 來更新報表數據。

常見的排程工具:

  • dbt Cloud: 官方託管服務,最簡單,設定排程與 CI/CD 非常直覺,支援 Slim CI。
  • Airflow: 數據工程界最流行的 Orchestrator。可以精細控制 dbt task 與其他非 dbt task (如 Python 爬蟲) 的依賴關係。
  • GitHub Actions / GitLab CI: 適合小型專案,透過 Cron schedule 觸發 workflow。
  • Dagster / Prefect: 新一代的 Orchestrator,對 dbt 有很好的整合支援(軟體定義資產)。

生產環境最佳實踐 Checkist

在準備上線前,請檢查以下項目:

  • 獨立的 Service Account:Prod 環境不應使用個人的資料庫帳號,應建立專用的 Service Account (如 dbt_runner)。
  • Schema分離:確保 Prod 的 Schema (如 analytics) 與 Dev 的 Schema (如 dbt_alice) 完全分開。
  • 唯讀權限控制:除了 dbt Service Account 外,BI 工具或分析師對 Prod Schema 應設定為 ReadOnly 權限,避免誤刪資料。
  • Artifacts 保存:每次 Prod 執行後,建議將 target/manifest.json 上傳到 S3/GCS。這是 Slim CI 用來比對差異的基準,也是各種 Metadata 工具的來源。
  • 警報機制 (Alerting):當 dbt build 失敗時,必須發送 Slack 或 Email 通知給值班工程師 (On-call)。

總結

dbt 的部署不僅僅是指令的執行,更是一套關於品質保證自動化的哲學。

  • 善用 profiles.yml 與環境變數做好安全隔離。
  • 全面採用 dbt build 確保資料品質與相依性安全。
  • 導入 Slim CI 提升開發速度。
  • 選擇合適的排程工具 (Orchestrator) 讓數據管線穩定運行。