DBT、Airflow 和 Kubernetes的架構演進 - yan
如果您在 Kubernetes 叢集上部署 Airflow,並且正在尋找將 DBT 整合到 Airflow 中的方法,那麼本文可能會給您一些啟發。
需要對 Airflow、DBT(資料構建工具)和 Kubernetes 有一些基本的瞭解。
第 1 部分 — RPC 伺服器設定
Astronomer 的人給了我們一些很好的想法,告訴我們如何建立 DBT 和 Airflow 之間的整合。我們最初的設計深受他們這篇文章的啟發。
就像文章中推薦的一樣,我們設定了一個 CI/CD 流程,該流程manifest.json會在主分支上的每次新提交時生成一個新檔案。
然後,Airflow 例項隨後讀取該manifest.json檔案,為每個模型建立一個 DAG,該 DAG 還負責執行上游模型。
但是,我們認為有幾點可以改進:
- DBT 模型可能必須與 Airflow 例項放在一起,以便 Airflow 訪問它們並dbt run在它們上執行。假設 Airflow 儲存庫已經存在,DBT 相關檔案可能必須位於同一個儲存庫中。這可能會使儲存庫變得臃腫,分析工程師可能會發現很難維護 DBT 相關元件。
- 從技術上講,可以建立一個不同的儲存庫來儲存 DBT 模型,並讓 Airflow 例項簡單地從儲存 DBT 模型的目錄中讀取。在 Kubernetes 設定中,這可能意味著設定共享卷形式的額外複雜性,併為每次新更新複製所有 DBT 模型。
- 此外,隨著我們在 Airflow 上部署的各種工作負載,在同一個 Airflow 例項中安裝了越來越多的庫。我們希望保持庫的精簡以避免衝突和混亂的依賴問題。
在尋求解決這些問題的解決方案時,我們發現 DBT 為我們提供了一個開箱即用的外掛來執行 RPC 伺服器,這可能會有所幫助。
根據 DBT,“該伺服器在 dbt 專案的上下文中編譯和執行查詢。此外,RPC 伺服器提供的方法使您能夠列出和終止正在執行的程式。”。
本質上,這意味著一旦我們設定了伺服器,而不是將 DBT 模型放在 Airflow 儲存庫中,我們可以:
- 向 RPC 伺服器(已經擁有專案的上下文)提交請求以執行 DBT 命令
- 輪詢提交作業的狀態
- 工作完成後,解析響應並根據最終狀態決定做什麼
因此,對於從 parsing 生成的每個任務節點,我們將使用 a來執行滿足這些基本步驟的函式manifest.json,而不是使用 aBashOperator來執行。dbt runPythonOperator
隨著 DBT 儲存庫與 Airflow 儲存庫的分離,現在整體部署如下所示:
對於每個 DBT 任務,PythonOperator 執行以下函式:
使用 PythonOperator 建立 DBT 任務
下圖進一步細分了 Airflow 為特定模型執行 DBT 任務時發生的情況:
- 氣流排程器生成一個 pod 來執行 DBT 任務
- pod 向 RPC 伺服器發出請求,指定它要執行的命令
- RPC 伺服器接收到請求,然後啟動一個作業來執行命令
- pod 收到帶有作業 ID 的響應
- Pod 使用作業 ID 不斷向 RPC Server 發出請求以檢查作業的狀態
- 作業仍在執行
- RPC 伺服器響應作業仍在執行
- pod 發出另一個請求以檢查作業的狀態
- 最終,工作完成或失敗
- pod 將收到一個響應,說明工作已完成或失敗。Airflow 任務將被標記為成功或失敗。
透過這種設計,我們設法將 DBT 儲存庫與 Airflow 儲存庫分離。分析工程師可以使用 DBT 儲存庫,而無需擔心如何在生產環境中執行這些模型。資料工程師可以使用更精簡的儲存庫,並避免任何潛在的庫衝突問題。
第 2 部分 — KubernetesPodOperator 設定
RPC 伺服器能夠在一段時間內發揮其作用。但是,當我們新增更多模型並更頻繁地執行它們時,這種設定的弱點開始顯現。由於 RPC 伺服器是使用固定資源部署的,當有更多請求進入時,它無法自行擴充套件。
更糟糕的是,RPC 伺服器沒有內建佇列系統來處理傳入的請求負載。任務需要更長的時間才能完成。響應時間過長的任務被標記為“失敗”,並且 Airflow 觸發了重試,這會堆積到現有的作業上。該轉換系統的整體效能顯著下降。
正如我們所見,RPC 伺服器設定實際上是Kubernetes 叢集中構建的系統其餘部分的反模式。
當 Airflow 執行越來越多的任務時,會產生更多的 pod,並且叢集能夠擴充套件資源以滿足這些 pod 的需求。相反,RPC 伺服器必須使用其固定資源並嘗試執行所有被請求的模型。
我們試圖透過為 RPC 伺服器提供更多資源來解決此問題,但它不可擴充套件。增加的資源往往跟不上加班增加的 DBT 模型數量的增加。在停機期間,RPC 伺服器只是囤積資源而不執行任何作業,這會轉化為更高的伺服器成本。
在高需求期間嘗試擴大 RPC 伺服器的例項數量在技術上是可行的。但是,由於觸發 RPC 伺服器中的作業的 pod 必須從具有給定 'request_token' 的同一 RPC 伺服器例項輪詢,因此必須實現將請求路由回同一 RPC 伺服器的機制。
由於這種增加的複雜性,我們的團隊認為不值得進一步追求這種設計。
此時,該團隊一直在嘗試使用 KubernetesPodOperator 來處理無法使用預設運算子輕鬆構建的管道。我們發現使用 KubernetesPodOperator 的一個優勢是特定於工作負載的庫僅包含在映像中,而 Airflow 只是觸發作業的編排器,進而生成 Pod 以在叢集上執行工作負載。
我們可以為該 Pod 指定我們想要的資源,以及任何變數和配置。這是一個優雅的抽象,允許我們執行我們想要的任何工作。
因此,我們認為我們可以使用 KubernetesPodOperator 來執行 DBT 任務。對於解析manifest.json檔案的每個模型節點,而不是向 RPC 伺服器發出請求並等待響應的 PythonOperator,它可能是拉取 DBT 儲存庫映像的 KubernetesPodOperator,並指定自定義命令來執行該特定模型。
下面的程式碼片段說明了透過解析manifest.json檔案在每個節點上建立的任務:
使用 KuberenetesPodOperator 建立 DBT 任務
使用 KubernetesPodOperator 執行 DBT 任務
- 排程程式生成一個 pod 來執行 DBT 任務(簡化)
- 任務拉取最新的 DBT 倉庫映象
- 然後該任務執行特定於模型的自定義命令
在這種情況下,如果為叢集分配了足夠的節點,當有大量活躍的 DBT 任務時,叢集只會增加節點的數量來處理傳入的工作負載。與之前的迭代不同,資源現在是動態配置的。
結論
當前的設定滿足了我們為轉換層設計的所有要求。它具有高度可擴充套件性和穩定性。團隊可以在較小的程式碼庫上工作,並且更容易維護。從那以後,我們的工作量增加了幾倍,系統可以毫不費力地處理它們。
相關文章
- 架構的演進架構
- Airbnb的架構演進AI架構
- Serverless 架構的演進Server架構
- 今日頭條架構演進之路 — 高壓下的架構演進架構
- 架構演進之「微服務架構」架構微服務
- 今日頭條架構演進之路——高壓下的架構演進專題架構
- 聊聊演進式架構架構
- 京東咚咚架構演進架構
- 技術架構演進的思考架構
- 圖解分散式架構的發展和演進圖解分散式架構
- Serverless 架構模式及演進Server架構模式
- 雲原生架構下的微服務選型和演進架構微服務
- 統一接入層架構的演進架構
- 從MVC到DDD的架構演進MVC架構
- 圖解分散式架構的演進圖解分散式架構
- 滴滴機器學習平臺架構演進機器學習架構
- vivo推送平臺架構演進架構
- Flutter Fish Redux架構演進2.0FlutterRedux架構
- Python後端架構演進Python後端架構
- Serverless 架構演進與實踐Server架構
- Spotify廣告系統架構演進架構
- 服務拆分與架構演進架構
- 圖片服務架構演進架構
- 從零入門 Serverless | 架構的演進Server架構
- 淘寶10年的架構演進過程架構
- Java分散式架構的演進過程Java分散式架構
- 大型網站技術架構的演進網站架構
- UNIX的架構及UNIX/Windows演進圖架構Windows
- Repractise架構篇一: CMS的重構與演進架構
- Repractise架構篇一:CMS的重構與演進架構
- Ceph儲存後端ObjectStore架構和技術演進後端Object架構
- 日誌架構演進:從集中式到分散式的Kubernetes日誌策略架構分散式
- 閒魚基於Flutter技術的架構演進和創新Flutter架構
- 微服務的架構演進過程和多個解決方案微服務架構
- 軟體系統的架構演進以及叢集和分散式架構分散式
- 滴滴機器學習平臺架構演進之路機器學習架構
- 馬蜂窩支付中心架構演進架構
- 萬表商城Android架構演進Android架構