基於 K8S 構建 Zeppelin 大資料視覺化分析工具

語言: CN / TW / HK

背景

大多數網際網路企業都提供有類似 Notebook 類的產品,採用互動式的方式進行資料分析、資料建模及資料視覺化。主要實現大多都是基於 jupyter 、Zeppelin 進行定製化開發,重點會打通大資料計算、儲存及底層資源管理,支援常見的機器學習和深度學習計算框架。

目前部門這塊主要的產品是資料查詢平臺 BigQuery,主要是用於 Hive sql 資料分析查詢,底層是 Tez 計算引擎跑在 yarn 叢集上,缺乏互動式可程式設計分析工具,無法滿足於機器學習、深度學習等迭代計算以及結果視覺化的需求,需要補充 Notebook 互動式程式設計能力以及對 spark 計算引擎等的支援。Apache Zeppelin 是一款大資料分析和視覺化工具類似於 jupyter notebook 互動式程式碼編輯器,滿足這些需求,同時相較於 Juypter 其更適合於大資料企業應用。

文章主要分幾個方面進行介紹,先對 Zeppelin 進行介紹,接著會講下 Zeppelin 的生產實踐,包括如何定製化去做 K8S 叢集上的部署、資源的隔離、檔案資料的上傳和持久化。

Zeppelin 介紹

Apache Zeppelin 是一款大資料分析和視覺化工具,可以讓資料分析師在一個基於 Web 頁面的筆記本中,使用不同的語言,對不同資料來源中的資料進行互動式分析,並對分析結果進行視覺化的工具。可以承擔資料接入、資料分析、資料視覺化、以及大資料建模的全流程,前端提供豐富的視覺化圖形庫,後端支援 Spark、HBase、Flink 等大資料系統,並支援 Spark、Python、JDBC、Markdown、Shell 、ES 等各種常用 Interpreter,這使得開發者可以方便地使用 SQL 在 Zeppelin 中做資料開發。

主要功能和特點

  • 視覺化互動式資料分析 ,使用者通過視覺化介面,互動式地輸入指令、程式碼提交給 Zeppelin 編譯執行。

  • Notebook 管理 使用者通過 Web 頁面輕鬆地實現 Notebook 應用的增加、修改、執行和刪除,支援應用的快速匯入匯出。

  • 資料視覺化指令、程式碼提交後 Zeppelin 返回結果給使用者,如果是結構化的資料,Zeppelin 提供視覺化機制,通過各類圖表展示資料,十分方便。

  • 直譯器配置 使用者可以配置系統內建的 Spark、JDBC、Elasticsearch 等直譯器,支援按組管理直譯器、為一個 Notebook 應用繫結多個直譯器。

  • 執行任務管理 使用者將 Notebook 應用提交給 Zeppelin 執行,也可以停止正在執行的任務。

  • 使用者認證 Zeppelin 提供完善的使用者認證機制。

  • Notebook 應用一鍵分享 除錯完畢的 Notebook 應用可以提供統一訪問的 HTTP 地址給外部應用訪問。

  • IntelliJ 提供的 big data tool 外掛實現 Zeppelin 高效的本地資料開發和除錯

一張官方支援直譯器的全景圖:

Zeppelin 架構

Zeppelin 架構主要分從三塊:Zeppelin 前端、Zeppelin Server、Zeppelin Interpreter;Zeppelin 前端是基於 AngularJS ;Zeppelin Server 是一個基於 Jetty 的輕量級 Web Server。主要負責 Zeppelin 服務配置資訊管理、Interpreter 配置資訊和生命週期管理、Note 儲存管理、外掛機制管理以及登陸許可權管理。

Zeppelin 前端和 Zeppelin Server 之間的通訊機制主要有 Rest api 和 WebSocket 兩種。Zeppelin Server 和 Zeppelin Interpreter 是通過 Thrift RPC 來通訊,而且他們彼此之間是雙向通訊,Zeppelin Server 可以向 Zeppelin Interpreter 傳送請求,Zeppelin Interpreter 也可以向 Zeppelin Server 傳送請求。

Interpreter 元件是指各個計算引擎在 Zeppelin 這邊的適配。比如 Python,Spark,Flink 等等。每個 Interpreter 都 run 在一個單獨的 JVM 程序裡,這個 JVM 程序可以是和 Zeppelin Server 在同一臺機器上(預設方式),也可以 run 在 Zeppelin 叢集裡的其他任何機器上或者 K8s 叢集的一個 Pod 裡。

Interpreter 支援動態載入 maven 格式依賴包的能力,多 JVM 隔離 runtime 依賴。Thrift-Based 跨語言 IPC(Inter-Process-Communication)機制(規定 repl 直譯器整合和平臺之間的資料交換的格式和時序)。抽象出 repl 直譯器生命週期管理介面,各 repl 直譯器受 zeppelinServer 端控制。

關於為什麼要採用單獨的 JVM 程序來啟動 repl 直譯器,原因有以下兩點:

  • zeppelin 旨在提供一個開放的框架,支援多種語言和產品,由於每種語言和產品都是各自獨立演進的,各自的執行時依賴也各不相同,甚至是相互衝突的,如果放在同一 JVM 中,僅解決衝突,維護各個產品之間的相容性都是一項艱鉅的任務,某些產品版本甚至是完全不能相容的。

  • 大資料分析,是否具有橫向擴充套件能力是生產可用的一項重要的衡量指標,如果將 repl 程序與主程序合在一起,會驗證影響系統性能。

因此,在有必要的時候,zeppelin 採用獨立 JVM 的方式來啟動 repl 程序,並且採用 Thrift 協議定義了主程序 ZeppelinServer 與 RemoteInterpreterServer 程序(直譯器程序)之間的通訊協議。

Zeppelin 生產實踐

Zeppelin 單機多程序方式執行,不滿足可擴充套件性、隔離性。當前大資料儲存和計算的分離以及 Zeppelin 的核心引擎直譯器 Spark 跑 Kubernetes 方案的成熟因此部署到 Kubernetes 上以映象容器的方式啟動,也就是水到渠成的事情,可以解決 Zeppelin 的擴充套件性、安全性、隔離性問題。生產上 K8S 叢集也會遇到,如何去做資源隔離以及直譯器空閒如何回收,要去打通大資料儲存、HIVE 資料訪問,提供檔案上傳資料持久化等功能。

部署到 K8S 需要解決如下問題:

如何解去對接 K8S 管理 Zeppelin 生命週期?包括 Zeppelin 服務的啟動、狀態、Zeppelin 停止、資源回收?

如何去為每個使用者生成 Zeppelin Server 解決多租房問題,並暴露統一的服務訪問入口?

如何解決 Zeppelin Server 停止後,使用者建立的 Note 資料能夠持久化不隨著服務的停止而刪除?

K8S 部署

K8S 部署相比於單機上部署可以帶來如下好處:

單機多程序情況下,擴充套件能力有限,尤其是執行需要佔用資源諸如 Spark 、tensorflow 等任務,採用 K8S 多程序以多 POD 的形式能夠排程到 K8S 不同的 NODE 這樣擴充套件性大大增強。

直譯器執行在容器中,避免安裝依賴對系統環境進行更改,併產生依賴包衝突,同時 shell 直譯器之類的存在著檔案刪除、非法訪問等非安全性的操作,執行依賴以映象的方式交付,程序執行在容器中,大大提高了安全性。

K8S 部署的整體架構如下圖所示:

架構主要分為三部分:

  • Zeppelin 服務的啟動,停止和狀態獲取,這塊主要包含呼叫 k8s Api 去建立 Namespace、ConfigMap、Service、RBAC、PV、PVC 以及 Zeppelin Server Deployment 等 Zeppelin 啟動相關的 k8s 物件,這裡我們做了相關個性化開發,首先是通過呼叫 JAVA K8S API 去建立 Zeppelin K8S 物件,其次就是通過掛載 NFS 或 S3 解決 notebook 無法持久化儲存問題、接著就是另外新增 init container 容器去實現多個使用者 demo note 的拷貝操作,其中還會涉及以 configmap 和環境變數 實現相關動態引數的傳遞。

  • Zeppelin 服務的訪問,這塊主要設計了為每個使用者建立獨立的 namespace,並啟動一個獨立 zeppelin server 去做多租戶, 每個使用者暴露不同的訪問 url,然後部署一個 nginx 並建立暴露 NodePort 型別 nginx Service 去代理不同使用者的訪問連結 ,通過 nginx 解析 url location 獲取不同使用者 namespace 及具體的 location 拼裝成最終不同使用者反向代理的 DNS 地址.

  • 這部分改造的相對比較少,主要就是 Zeppelin 如何去啟動 Interpreter 以及之間的通訊。

打通計算和儲存

Zeppelin 支援許多大資料計算引擎,生產支援的話需要解決依賴包安裝、環境變數配置、直譯器配置等工作,既然是平臺化的支援,應該這些功能在 Zeppelin Server 啟動後就可以直接使用,不需要使用者在做許多配置這類繁瑣的工作,這塊的話我們在設計開發的時候,打通底層 spark 訪問 HDFS、新建了 HIVE SQL 直譯器,不需要使用者額外配置可以直接訪問生產 Hive 、HDFS 並解決了許可權認證、包依賴等問題。

比如說,通過映象內建 hdfs、hive、yarn 客戶端,提供相應線上的配置檔案,傳遞不同的使用者認證資訊解決依賴及訪問許可權問題,配置 DNS 域名解析,搞定 K8S 叢集和大資料叢集訪問許可權,最終能夠讓 spark hive 任務正常執行起來。

資源隔離及回收

問題背景:

使用者用 zeppelin 跑 spark 任務配置多達 100 個 executor,400G 記憶體導致 K8S 叢集中其他任務無法排程。

原因分析:

這個比較容易分析到,主要 k8s 叢集 CPU、記憶體是有限制的,不可能無限擴容,當申請的資源過多,如果沒有排程和隔離策略的話就會影響到其他任務的排程,同時的話 如果 k8s 分配出去的資源無法回收,總有一天會有資源用盡導致其他任務無法排程的情況。

解決方案:

K8S 官方提供了資源隔離方案,有基於節點選擇的、任務親和度的、以及 namespace 資源限制的,還有就是啟動任務資源限制的,這塊我們採取的最基本的節點標記選擇,具體如下圖所示:

對 K8S 叢集的計算節點打上不同的標記,規定了一些節點是 notebook 公用的節點,預設建立的 Zeppelin notebook 會排程到這些 公用資源組節點上去,如果有些 notebook 比較重要就會指定到另外的資源組中,這塊實現比較簡單,一個就是就是為要執行的任務打上需要排程到某些標記的節點,另外就是提供管理介面,提前對 k8s 中的計算節點打上標記,這樣 k8s 在進行任務排程時,會去自動過濾選擇符合條件的節點。

針對資源限制和回收的問題在啟動時候增加的配置引數,規定了 pod 啟動的資源限制以及服務空閒後多久會被回收,如下圖所示:

這塊資源限制,主要是在呼叫 k8s api 建立 pod 時候 增加 request 和 limit 對 cpu 和記憶體進行限制。

資源回收主要是前端選擇空閒停止時間,後端服務程序獲取配置引數,在 Zeppelin server 與直譯器互動請求的地方啟動執行緒,不停更新互動時間,直到判斷空閒超過配置時間,觸發程序退出操作。

檔案上傳及資料持久化

問題背景:

  • 使用者建立 zeppelin notebook 重啟後 notebook 消失

  • Zeppelin 不支援本地檔案上傳以及上傳後的檔案如何共享到不同直譯器的 Pod 中。

解決方案:

這裡的問題比較明顯,主要是容器中所進行的檔案修改並不會持久化,容器停止重新啟動後又是一個新的環境,在其中建立的 notebook、安裝的依賴包都會隨著下次啟動而消失,為了能夠持久的儲存使用者資料,就需要去掛載網路儲存或者物件儲存,這塊的話就比較常規了為每個啟動的 Zeppelin Server 掛載一個 NFS 網路儲存,同時通過 subpath 引數為每個使用者建立不同的子目錄解決使用者資料隔離的問題。不同使用者掛載到容器中就是同一個網路儲存不同的子目錄。同時也提供了 S3 網路儲存掛載方式,具體可以檢視參考資料。

另外一種情況是,使用者在做資料探索和資料分析,所訪問的資料要麼是從網路中下載的資料,要麼就是 HDFS 中的檔案,要麼就是具體的直譯器自身的訪問資料方式,相對於 jupyter notebook ,zeppelin 本身就沒有提供檔案上傳的操作,這塊我們進行了定製化提供檔案上傳操作,只不過這個檔案上傳操作稍微有點特殊,還記得之前提到 zeppelin 執行到 k8s 中的架構 interpreter 是執行在不同機器節點的 pod 中,上傳到 zeppelin server 中的資料要在其他直譯器中能夠使用,這就需要 zeppelin 和其他 interpreter pod 也需要掛載對應的網路儲存,這塊我們在建立 interpreter pod 時就會同樣增加網路儲存的掛載操作。

總結和展望

Zeppelin notebook 可以滿足資料開發、資料分析及產品運營報表分析以及大資料互動式建模,通過部署到 K8S 叢集中可以解決其擴充套件性、安全性、多租戶等問題。並在生產實踐中進行了一些定製化功能,同時積極擁抱開源社群,對 Zeppelin 中的程式碼存在通用的問題進行了修復並提交了社群如: ZEPPELIN-5379ZEPPLIN-5349 ,另外 Zeppelin on k8s 的未來還有許多事情需要去解決,比如 Flink on Zeppelin 如何跑在 K8S 之中,web shell、Spark web ui 跑在 K8S 遇到的訪問連結如何開啟,zeppelin 定時排程以及其他直譯器如何執行在 Zeppelin K8S 環境中等功能,在之後的迭代開發中會繼續緊跟社群完善相關功能。

參考資料

https://zeppelin.apache.org/

https://zhuanlan.zhihu.com/p/372250644

https://www.yuque.com/jeffzhangjianfeng/ggi5ys/shby78