在 Kubernetes(K8s)中,Pod 是最小的可調(diào)度單元。當(dāng) Spark 任務(wù)運(yùn)行在 K8s 上時(shí),無論是 Driver 還是 Executor 都由一個(gè)單獨(dú)的 Pod 來表示。每個(gè) Pod 都被分配了一個(gè)唯一的 IP 地址,并且可以包含一個(gè)或多個(gè)容器(Container)。Driver 和 Executor 的 JVM 進(jìn)程都是在這些 Container 中啟動(dòng)、運(yùn)行和銷毀的。
當(dāng)一個(gè) Spark 作業(yè)被提交到 K8s 集群后,首先會(huì)被啟動(dòng)的是 Driver Pod。然后,Driver 負(fù)責(zé)按需向 Apiserver 請(qǐng)求創(chuàng)建 Executor Pods。Executor 負(fù)責(zé)執(zhí)行具體的 Task。一旦作業(yè)完成,Driver 將負(fù)責(zé)清理所有已創(chuàng)建的 Executor Pods。以下是一個(gè)簡要的關(guān)系示意圖:
- 用戶通過?
spark-submit
?向 K8s 集群提交 Spark 作業(yè)。 - K8s 集群中的 Master Node 接收請(qǐng)求并創(chuàng)建 Driver Pod。
- Driver Pod 內(nèi)部啟動(dòng) Driver JVM 進(jìn)程。
- Driver JVM 進(jìn)程根據(jù)作業(yè)需求向 Apiserver 請(qǐng)求創(chuàng)建 Executor Pods。
- Apiserver 分配資源并創(chuàng)建 Executor Pods。
- Executor Pods 內(nèi)部啟動(dòng) Executor JVM 進(jìn)程。
- Executor JVM 進(jìn)程執(zhí)行具體的 Task。
- 作業(yè)完成后,Driver JVM 進(jìn)程通知 Apiserver 清理所有的 Executor Pods。
- Apiserver 確認(rèn)并釋放 Executor Pods 所占用的資源。
- Driver Pod 完成其使命后,也會(huì)被清理。
這種設(shè)計(jì)使得 Spark 可以無縫地集成到 K8s 環(huán)境中,利用 K8s 的彈性伸縮和資源管理能力來高效地運(yùn)行大數(shù)據(jù)處理作業(yè)。
下圖描繪了完整的作業(yè)執(zhí)行流程。當(dāng)用戶完成 Spark 作業(yè)開發(fā)后,他們會(huì)將任務(wù)發(fā)布到調(diào)度系統(tǒng),并配置相關(guān)的運(yùn)行參數(shù)。調(diào)度系統(tǒng)會(huì)按照設(shè)定的時(shí)間間隔將任務(wù)提交到自研的 Launcher 中間件。這個(gè)中間件負(fù)責(zé)調(diào)用 spark-k8s-cli 工具,最終由該工具將任務(wù)提交到 K8s 集群上。
在 Executor 執(zhí)行具體的 Task 過程中,它們需要與外部的各種大數(shù)據(jù)組件進(jìn)行數(shù)據(jù)訪問和交互,包括 Hive、Iceberg、OLAP 數(shù)據(jù)庫以及 OSS-HDFS 等。而 Spark Executor 之間的數(shù)據(jù) Shuffle 操作則是由 CeleBorn 來實(shí)現(xiàn)的。
整個(gè)過程可以總結(jié)如下:
- 用戶開發(fā)并配置 Spark 作業(yè)。
- 將作業(yè)發(fā)布到調(diào)度系統(tǒng),并設(shè)置運(yùn)行參數(shù)。
- 調(diào)度系統(tǒng)按計(jì)劃將作業(yè)提交到 Launcher 中間件。
- Launcher 中間件調(diào)用 spark-k8s-cli 將作業(yè)提交到 K8s 集群。
- 在 K8s 集群上啟動(dòng) Driver 和 Executor Pods。
- Executor 執(zhí)行 Task 并與外部大數(shù)據(jù)組件進(jìn)行數(shù)據(jù)交互。
- CeleBorn 實(shí)現(xiàn) Executor 之間的數(shù)據(jù) Shuffle。
通過這種架構(gòu)設(shè)計(jì),Spark 作業(yè)能夠充分利用 K8s 的資源管理和彈性伸縮能力,同時(shí)與其他大數(shù)據(jù)組件無縫集成,以高效地處理大規(guī)模的數(shù)據(jù)處理任務(wù)。
在將 Spark 任務(wù)提交到 K8s 集群上時(shí),不同的公司可能會(huì)采取不同的方法。以下是目前常見的幾種做法以及我們?cè)诰€上所采用的任務(wù)提交和管理方式。
-
使用原生 spark-submit 原生的 spark-submit 命令可以直接提交作業(yè),集成起來簡單且符合用戶習(xí)慣。然而,這種方法不便于作業(yè)狀態(tài)跟蹤和管理,無法自動(dòng)配置 Spark UI 的 Service 和 Ingress,并且在任務(wù)結(jié)束后不能自動(dòng)清理資源。因此,在生產(chǎn)環(huán)境中并不適合使用這種方式。
-
使用 spark-on-k8s-operator 這是目前較常用的一種提交作業(yè)方式,需要先在 K8s 集群中安裝 spark-operator。客戶端通過 kubectl 提交 yaml 文件來運(yùn)行 Spark 作業(yè)。本質(zhì)上,這是對(duì)原生方式的擴(kuò)展,提供了作業(yè)管理、Service/Ingress 創(chuàng)建與清理、任務(wù)監(jiān)控、Pod 增強(qiáng)等功能。盡管此方法可在生產(chǎn)環(huán)境中使用,但它與大數(shù)據(jù)調(diào)度平臺(tái)的集成性較差,對(duì)于不熟悉 K8s 的用戶來說,學(xué)習(xí)曲線較為陡峭。
-
使用 spark-k8s-cli 在我們的生產(chǎn)環(huán)境中,我們使用 spark-k8s-cli 來提交任務(wù)。spark-k8s-cli 是一個(gè)可執(zhí)行文件,基于阿里云 emr-spark-ack 提交工具進(jìn)行了重構(gòu)、功能增強(qiáng)和深度定制。它融合了 spark-submit 和 spark-operator 兩種作業(yè)提交方式的優(yōu)點(diǎn),所有作業(yè)都能通過 spark-operator 管理,并支持交互式 spark-shell 和本地依賴的提交。同時(shí),它的使用方式與原生 spark-submit 完全一致。
起初,我們所有的 Spark Submit JVM 進(jìn)程都啟動(dòng)在 Gateway Pod 中。但在使用一段時(shí)間后,我們發(fā)現(xiàn)這種穩(wěn)定性不足,一旦 Gateway Pod 異常,所有正在進(jìn)行的 Spark 任務(wù)都會(huì)失敗。此外,Spark 任務(wù)的日志輸出也難以管理。因此,我們將 spark-k8s-cli 改為每個(gè)任務(wù)使用單獨(dú)的 Submit Pod 方式。Submit Pod 會(huì)申請(qǐng)啟動(dòng)任務(wù)的 Driver,Submit Pod 和 Driver Pod 都運(yùn)行在固定的 ECS 節(jié)點(diǎn)上。Submit Pod 之間完全獨(dú)立,任務(wù)結(jié)束后,Submit Pod 也會(huì)自動(dòng)釋放。下圖展示了 spark-k8s-cli 的提交和運(yùn)行原理。
關(guān)于 spark-k8s-cli,除了基本的任務(wù)提交功能外,我們還實(shí)施了其他一些增強(qiáng)和定制化功能。文章來源:http://www.zghlxwxcb.cn/news/detail-803542.html
- 支持多集群任務(wù)提交:spark-k8s-cli 支持將任務(wù)提交到同地域內(nèi)的多個(gè)不同的 K8s 集群上。這實(shí)現(xiàn)了集群之間的負(fù)載均衡和故障轉(zhuǎn)移切換,增強(qiáng)了系統(tǒng)的可用性和穩(wěn)定性。
- 資源不足時(shí)的自動(dòng)排隊(duì)等待:我們實(shí)現(xiàn)了類似 Yarn 資源不足時(shí)的自動(dòng)排隊(duì)等待功能。當(dāng) K8s 設(shè)置了資源 Quota,并且 Quota 達(dá)到上限時(shí),任務(wù)會(huì)直接失敗。我們的解決方案可以確保在資源有限的情況下,任務(wù)能夠有序地進(jìn)行。
- 異常處理與容錯(cuò):增加了對(duì) K8s 網(wǎng)絡(luò)通信等異常的處理、創(chuàng)建或啟動(dòng)失敗后的重試機(jī)制。這些功能對(duì)于偶發(fā)的集群抖動(dòng)和網(wǎng)絡(luò)異常提供了容錯(cuò)能力,保證了系統(tǒng)的可靠性。
- 大規(guī)模補(bǔ)數(shù)任務(wù)限流與管控:支持按照不同部門或業(yè)務(wù)線,對(duì)大規(guī)模補(bǔ)數(shù)任務(wù)進(jìn)行限流和管控。這樣可以有效地管理和優(yōu)化系統(tǒng)資源使用,防止某些任務(wù)過度消耗資源,影響整體性能。
- 內(nèi)置告警功能:內(nèi)嵌了任務(wù)提交失敗、容器創(chuàng)建或啟動(dòng)失敗以及運(yùn)行超時(shí)等告警功能。這有助于及時(shí)發(fā)現(xiàn)并解決問題,提高運(yùn)維效率。
通過這些增強(qiáng)和定制化功能,spark-k8s-cli 不僅提高了 Spark 作業(yè)在 K8s 上的運(yùn)行效率,也提升了整個(gè)系統(tǒng)的穩(wěn)定性和可管理性。文章來源地址http://www.zghlxwxcb.cn/news/detail-803542.html
到了這里,關(guān)于云原生架構(gòu)設(shè)計(jì)與實(shí)現(xiàn):Spark 在 K8s 上運(yùn)行的基本原理的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!