溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Spark 3.0 on Kubernetes的模式是怎樣的

發(fā)布時(shí)間:2021-12-24 09:38:04 來源:億速云 閱讀:146 作者:iii 欄目:大數(shù)據(jù)

這篇文章主要介紹“Spark 3.0 on Kubernetes的模式是怎樣的”,在日常操作中,相信很多人在Spark 3.0 on Kubernetes的模式是怎樣的問題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”Spark 3.0 on Kubernetes的模式是怎樣的”的疑惑有所幫助!接下來,請(qǐng)跟著小編一起來學(xué)習(xí)吧!

Spark 3.0發(fā)布后,對(duì)Kubernetes的原生支持得到大幅增強(qiáng),從而方便了Spark在云原生環(huán)境中的快速部署和運(yùn)行實(shí)例的管理。

1. Standalone 模式

Spark 運(yùn)行在 Kubernetes 集群上的第一種可行方式是將 Spark 以 Standalone 模式運(yùn)行,但是很快社區(qū)就提出使用 Kubernetes 原生 Scheduler 的運(yùn)行模式,也就是 Native 的模式。

2. Kubernetes Native 模式

Native 模式簡(jiǎn)而言之就是將 Driver 和 Executor Pod 化,用戶將之前向 YARN 提交 Spark 作業(yè)的方式提交給 Kubernetes 的 apiserver,提交命令如下:

$ bin/spark-submit \    --master k8s://https://<k8s-apiserver-host>:<k8s-apiserver-port> \    --deploy-mode cluster \    --name spark-pi \    --class org.apache.spark.examples.SparkPi \    --conf spark.executor.instances=5 \    --conf spark.kubernetes.container.image=<spark-image> \    local:///path/to/examples.jar

其中 master 就是 kubernetes 的 apiserver 地址。提交之后整個(gè)作業(yè)的運(yùn)行方式如下,先將 Driver 通過 Pod 啟動(dòng)起來,然后 Driver 會(huì)啟動(dòng) Executor 的 Pod。這些方式很多人應(yīng)該都了解了,就不贅述了,詳細(xì)信息可以參考:https://spark.apache.org/docs/latest/running-on-kubernetes.html 。

Spark 3.0 on Kubernetes的模式是怎樣的

3. Spark Operator

除了這種直接向 Kubernetes Scheduler 提交作業(yè)的方式,還可以通過 Spark Operator 的方式來提交。Operator 在 Kubernetes 中是一個(gè)里程碑似的產(chǎn)物。在 Kubernetes 剛面世的時(shí)候,關(guān)于有狀態(tài)的應(yīng)用如何部署在 Kubernetes 上一直都是官方不愿意談?wù)摰脑掝},直到 StatefulSet 出現(xiàn)。StatefulSet 為有狀態(tài)應(yīng)用的部署實(shí)現(xiàn)了一種抽象,簡(jiǎn)單來說就是保證網(wǎng)絡(luò)拓?fù)浜痛鎯?chǔ)拓?fù)洹5菭顟B(tài)應(yīng)用千差萬別,并不是所有應(yīng)用都能抽象成 StatefulSet,強(qiáng)行適配反正加重了開發(fā)者的心智負(fù)擔(dān)。

然后 Operator 出現(xiàn)了。我們知道 Kubernetes 給開發(fā)者提供了非常開放的一種生態(tài),你可以自定義 CRD,Controller 甚至 Scheduler。而 Operator 就是 CRD + Controller 的組合形式。開發(fā)者可以定義自己的 CRD,比如我定義一種 CRD 叫 EtcdCluster 如下:

apiVersion: "etcd.database.coreos.com/v1beta2"kind: "EtcdCluster"metadata:  name: "example-etcd-cluster"spec:  size: 3  version: "3.1.10"  repository: "quay.io/coreos/etcd"

提交到 Kubernetes 之后 Etcd 的 Operator 就針對(duì)這個(gè) yaml 中的各個(gè)字段進(jìn)行處理,最后部署出來一個(gè)節(jié)點(diǎn)規(guī)模為 3 個(gè)節(jié)點(diǎn)的 etcd 集群。你可以在 github 的這個(gè) repo:https://github.com/operator-framework/awesome-operators 中查看目前實(shí)現(xiàn)了 Operator 部署的分布式應(yīng)用。

Google 云平臺(tái),也就是 GCP 在 github 上面開源了 Spark 的 Operator,repo 地址:GoogleCloudPlatform/spark-on-k8s-operator。Operator 部署起來也是非常的方便,使用 Helm Chart 方式部署如下,你可以簡(jiǎn)單認(rèn)為就是部署一個(gè) Kubernetes 的 API Object (Deployment)。

$ helm repo add incubator http://storage.googleapis.com/kubernetes-charts-incubator
$ helm install incubator/sparkoperator --namespace spark-operator

這個(gè) Operator 涉及到的 CRD 如下:

ScheduledSparkApplication
|__ ScheduledSparkApplicationSpec
    |__ SparkApplication
|__ ScheduledSparkApplicationStatus

|__ SparkApplication
|__ SparkApplicationSpec
    |__ DriverSpec
        |__ SparkPodSpec
    |__ ExecutorSpec
        |__ SparkPodSpec
    |__ Dependencies
    |__ MonitoringSpec
        |__ PrometheusSpec
|__ SparkApplicationStatus
    |__ DriverInfo

如果我要提交一個(gè)作業(yè),那么我就可以定義如下一個(gè) SparkApplication 的 yaml,關(guān)于 yaml 里面的字段含義,可以參考上面的 CRD 文檔。

apiVersion: sparkoperator.k8s.io/v1beta1kind: SparkApplicationmetadata:  ...spec:  deps: {}  driver:    coreLimit: 200m    cores: 0.1    labels:      version: 2.3.0    memory: 512m    serviceAccount: spark  executor:    cores: 1    instances: 1    labels:      version: 2.3.0    memory: 512m  image: gcr.io/ynli-k8s/spark:v2.4.0  mainApplicationFile: local:///opt/spark/examples/jars/spark-examples_2.11-2.3.0.jar  mainClass: org.apache.spark.examples.SparkPi  mode: cluster  restartPolicy:      type: OnFailure      onFailureRetries: 3      onFailureRetryInterval: 10      onSubmissionFailureRetries: 5      onSubmissionFailureRetryInterval: 20  type: Scalastatus:  sparkApplicationId: spark-5f4ba921c85ff3f1cb04bef324f9154c9  applicationState:    state: COMPLETED  completionTime: 2018-02-20T23:33:55Z  driverInfo:    podName: spark-pi-83ba921c85ff3f1cb04bef324f9154c9-driver    webUIAddress: 35.192.234.248:31064    webUIPort: 31064    webUIServiceName: spark-pi-2402118027-ui-svc    webUIIngressName: spark-pi-ui-ingress    webUIIngressAddress: spark-pi.ingress.cluster.com  executorState:    spark-pi-83ba921c85ff3f1cb04bef324f9154c9-exec-1: COMPLETED  LastSubmissionAttemptTime: 2018-02-20T23:32:27Z

提交作業(yè)。

$ kubectl apply -f spark-pi.yaml

對(duì)比來看 Operator 的作業(yè)提交方式似乎顯得更加的冗長(zhǎng)復(fù)雜,但是這也是一種更 kubernetes 化的 api 部署方式,也就是 Declarative API,聲明式 API。

4. 挑戰(zhàn)

基本上,目前市面的大部門公司都是使用上面兩種方式來做 Spark on Kubernetes 的,但是我們也知道在 Spark Core 里面對(duì) Kubernetes 的這種 Native 方式支持其實(shí)并不是特別成熟,還有很多可以改善的地方,下面簡(jiǎn)單舉例幾個(gè)地方:

1.scheduler 差異

資源調(diào)度器可以簡(jiǎn)單分類成集中式資源調(diào)度器和兩級(jí)資源調(diào)度器。兩級(jí)資源調(diào)度器有一個(gè)中央調(diào)度器負(fù)責(zé)宏觀資源調(diào)度,對(duì)于某個(gè)應(yīng)用的調(diào)度則由下面分區(qū)資源調(diào)度器來做。兩級(jí)資源調(diào)度器對(duì)于大規(guī)模應(yīng)用的管理調(diào)度往往能有一個(gè)良好的支持,比如性能方面,缺點(diǎn)也很明顯,實(shí)現(xiàn)復(fù)雜。其實(shí)這種設(shè)計(jì)思想在很多地方都有應(yīng)用,比如內(nèi)存管理里面的 tcmalloc 算法,Go 語言的內(nèi)存管理實(shí)現(xiàn)。大數(shù)據(jù)的資源調(diào)度器 Mesos/Yarn,某種程度上都可以歸類為兩級(jí)資源調(diào)度器。

集中式資源調(diào)度器對(duì)于所有的資源請(qǐng)求進(jìn)行響應(yīng)和決策,這在集群規(guī)模大了之后難免會(huì)導(dǎo)致一個(gè)單點(diǎn)瓶頸,毋庸置疑。但是 Kubernetes 的 scheduler 還有一點(diǎn)不同的是,它是一種升級(jí)版,一種基于共享狀態(tài)的集中式資源調(diào)度器。Kubernetes 通過將整個(gè)集群的資源緩存到 scheduler 本地,在進(jìn)行資源調(diào)度的時(shí)候在根據(jù)緩存的資源狀態(tài)來做一個(gè) “樂觀” 分配(assume + commit)來實(shí)現(xiàn)調(diào)度器的高性能。

Kubernetes 的默認(rèn)調(diào)度器在某種程度上并不能很好的 match Spark 的 job 調(diào)度需求,對(duì)此一種可行的技術(shù)方案是再提供一種 custom scheduler 或者直接重寫,比如 Spark on Kubernetes Native 方式的參與者之一的大數(shù)據(jù)公司 Palantir 就開源了他們的 custom scheduler,github repo: https://github.com/palantir/k8s-spark-scheduler。

2. Shuffle 處理

由于 Kubernetes 的 Executor Pod 的 Shuffle 數(shù)據(jù)是存儲(chǔ)在 PV 里面,一旦作業(yè)失敗就需要重新掛載新的 PV 從頭開始計(jì)算。針對(duì)這個(gè)問題,F(xiàn)acebook 提出了一種 Remote Shuffle Service 的方案,簡(jiǎn)單來說就是將 Shuffle 數(shù)據(jù)寫在遠(yuǎn)端。直觀感受上來說寫遠(yuǎn)端怎么可能比寫本地快呢?而寫在遠(yuǎn)端的一個(gè)好處是 Failover 的時(shí)候不需要重新計(jì)算,這個(gè)特性在作業(yè)的數(shù)據(jù)規(guī)模異常大的時(shí)候比較有用。

3. 集群規(guī)模

基本上現(xiàn)在可以確定的是 Kubernetes 會(huì)在集群規(guī)模達(dá)到五千臺(tái)的時(shí)候出現(xiàn)瓶頸,但是在很早期的時(shí)候 Spark 發(fā)表論文的時(shí)候就聲稱 Spark Standalone 模式可以支持一萬臺(tái)規(guī)模。Kubernetes 的瓶頸主要體現(xiàn)在 master 上,比如用來做元數(shù)據(jù)存儲(chǔ)的基于 raft 一致性協(xié)議的 etcd 和 apiserver 等。對(duì)此在剛過去的 2019 上海 KubeCon 大會(huì)上,阿里巴巴做了一個(gè)關(guān)于提高 master 性能的 session: 了解 Kubernetes Master 的可擴(kuò)展性和性能,感興趣的可以自行了解。

4.Pod 驅(qū)逐(Eviction)問題

在 Kubernetes 中,資源分為可壓縮資源(比如 CPU)和不可壓縮資源(比如內(nèi)存),當(dāng)不可壓縮資源不足的時(shí)候就會(huì)將一些 Pod 驅(qū)逐出當(dāng)前 Node 節(jié)點(diǎn)。國(guó)內(nèi)某個(gè)大廠在使用 Spark on kubernetes 的時(shí)候就遇到因?yàn)榇疟P IO 不足導(dǎo)致 Spark 作業(yè)失敗,從而間接導(dǎo)致整個(gè)測(cè)試集都沒有跑出來結(jié)果。如何保證 Spark 的作業(yè) Pod (Driver/Executor) 不被驅(qū)逐呢?這就涉及到優(yōu)先級(jí)的問題,1.10 之后開始支持。但是說到優(yōu)先級(jí),有一個(gè)不可避免的問題就是如何設(shè)置我們的應(yīng)用的優(yōu)先級(jí)?常規(guī)來說,在線應(yīng)用或者 long-running 應(yīng)用優(yōu)先級(jí)要高于 batch job,但是顯然對(duì)于 Spark 作業(yè)來說這并不是一種好的方式。

5. 作業(yè)日志

Spark on Yarn 的模式下,我們可以將日志進(jìn)行 aggregation 然后查看,但是在 Kubernetes 中暫時(shí)還是只能通過 Pod 的日志查看,這塊如果要對(duì)接 Kubernetes 生態(tài)的話可以考慮使用 fluentd 或者 filebeat 將 Driver 和 Executor Pod 的日志匯總到 ELK 中進(jìn)行查看。

6.Prometheus 生態(tài)

Prometheus 作為 CNCF 畢業(yè)的第二個(gè)項(xiàng)目,基本是 Kubernetes 監(jiān)控的標(biāo)配,目前 Spark 并沒有提供 Prometheus Sink。而且 Prometheus 的數(shù)據(jù)讀取方式是 pull 的方式,對(duì)于 Spark 中 batch job 并不適合使用 pull 的方式,可能需要引入 Prometheus 的 pushgateway。

到此,關(guān)于“Spark 3.0 on Kubernetes的模式是怎樣的”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI