在當(dāng)今互聯(lián)網(wǎng)和移動應(yīng)用快速發(fā)展的浪潮下,大數(shù)據(jù)和微服務(wù)應(yīng)用受到越來越多技術(shù)人員的青睞,其中Spark和Kubernetes容器管理平臺技術(shù)也逐漸成為企業(yè)技術(shù)人員必備技能。如何快速部署集群?如何安全高效的運(yùn)維?是否可以將大數(shù)據(jù)平臺和容器管理平臺有效的結(jié)合起來?也是很多人一直以來探索和研究的方向。
本文我們將和大家一起來探索如何在微軟容器服務(wù)Azure Kubernetes Services(AKS)上輕松部署運(yùn)行Spark應(yīng)用的兩種方式。
方法一:通過AKS的API Server直接提交Spark任務(wù)
從Spark 2.3開始,Spark原生已經(jīng)支持Kubernetes,這意味著您無需提前構(gòu)建Spark集群,在Spark Client提交任務(wù)的時候,只需要指定Kubernetes的API Server地址和端口,即可運(yùn)行Spark任務(wù)。在使用spark-submit提交任務(wù)的時候,既可以指定Cluster Mode,又可以指定Client Mode。其工作原理如下:
當(dāng)任務(wù)提交成功之后,會在K8S集群里面起一個運(yùn)行Spark driver的Pod
這個Spark driver會在Pod中創(chuàng)建executors,然后連到這些executor,并執(zhí)行應(yīng)用代碼。
當(dāng)應(yīng)用執(zhí)行完成之后,運(yùn)行executor的pod會被終止并刪除,但運(yùn)行Spark driver的Pod會一直保留,并顯示為”completed”狀態(tài)直到被手動刪除。在此期間,可以kubectl logs命令查看Spark的日志。
通過Spark-Submit向AKS集群提交Spark任務(wù)
1.創(chuàng)建AKS集群
在Azure Portal上搜索”kubernete”,然后進(jìn)入到AKS的管理界面,可根據(jù)向?qū)Э焖賱?chuàng)建一個AKS集群。本次示例我們采用了3個節(jié)點(diǎn)的Worker Node,機(jī)型為B2ms,網(wǎng)絡(luò)模式為Basic(Kubenet)。有關(guān)創(chuàng)建集群和連接集群的步驟,您也可以參考本文檔。成功創(chuàng)建之后,可以通過下面的命令看到AKS集群的信息,記錄下master節(jié)點(diǎn)的地址。
2.準(zhǔn)備Spark環(huán)境。下載Spark安裝文件,將其解壓
3.創(chuàng)建Azure Container registries鏡像倉庫。在Azure Portal中搜索”container registries”,按默認(rèn)參數(shù)創(chuàng)建一個鏡像倉庫。創(chuàng)建完成之后,在Access keys界面,點(diǎn)擊Enable啟用Admin user,記錄下repo的地址,用戶名和密碼,使用docker login登錄到ACR,然后使用az cli將AKS集群和ACR進(jìn)行關(guān)聯(lián)。(請將標(biāo)紅的地方修改為自己的參數(shù)值,后續(xù)不再說明)
4.準(zhǔn)備Spark Docker Image。創(chuàng)建spark image,并將其上傳到Azure Container Registries鏡像倉庫中。其中-r后面跟上一步創(chuàng)建的repo地址,-t后面跟版本號
5.創(chuàng)建運(yùn)行Spark任務(wù)的service account,并綁定相應(yīng)的role
6.準(zhǔn)備一個Spark應(yīng)用jar包,將其傳到Azure Blob上,權(quán)限設(shè)置為公網(wǎng)可訪問?;蛘呤褂帽敬问纠峁┑膉ar包。
在運(yùn)行的過程中,可以通過kubectl get pod–watch進(jìn)行觀察,我們會看到spark-pi-xxxx-driver先運(yùn)行起來,然后會起3個spark-pi-xxxx-exec-N pod作為executor,任務(wù)完成之后,executor pod會自動刪除,只保留driver pod信息,通過kubectl logs DRIVER_POD_NAME可以看到計(jì)算的PI結(jié)果。
7.在Spark任務(wù)執(zhí)行的過程中,我們也可以通過port forward的方法,將driver的端口映射到本機(jī)來訪問spark UI.
然后瀏覽器訪問http://localhost:4040即可訪問到Spark UI
通過client mode訪問到運(yùn)行在AKS集群中的spark-shell
從Spark 2.4.0開始,Spark原生支持在k8s上以client模式提交任務(wù)。但Spark executors必須能通過主機(jī)名和端口連接到Spark Driver上。Spark Driver既可以在物理機(jī)上運(yùn)行,也可以跑在pod里面。為了使Spark executors能夠解析到spark driver的DNS名稱,本次我們將創(chuàng)建一個ubuntu的pod,在pod中配置spark client的環(huán)境。
創(chuàng)建ubuntu pod的命令為:
之后會自動進(jìn)入到ubuntu pod的shell,接下來的命令全部都在ubuntu pod shell中輸入
進(jìn)入Spark Shell之后,就可以看到spark master的地址即為aks的地址,之后就可以通過交互式方法跑Spark的任務(wù)了
通過上述方法,我們已經(jīng)實(shí)現(xiàn)了在AKS集群中運(yùn)行Spark任務(wù)PI,好處是在不跑Spark任務(wù)的時候,不消耗任何資源,任務(wù)跑完之后,pod會被刪除,也不會占用AKS集群的資源。
方法二:使用Spark Operator在AKS里面運(yùn)行Spark集群
K8s Operator是K8s的一個擴(kuò)展功能,通過K8S Operator可以通過自定義資源來創(chuàng)建應(yīng)用?;谶@個功能,我們可以借助于一些第三方的Operator在k8s里面運(yùn)行一個長期穩(wěn)定的Spark集群。本次我們以radanalytics.io提供的Apache Spark Operator為例,來演示如何創(chuàng)建一個Spark集群以及如何直接提交Spark Application.
操作步驟:
1.在AKS集群上使用下面的命令部署Apache Spark Operator,部署完成之后可以通過kubectl get operators命令來進(jìn)行確認(rèn),PHASE顯示為”Successed”則表示已部署成功
2.將下面的內(nèi)容保存成sparkdemo.yaml,然后執(zhí)行kubectl appy-f sparkdemo.yaml命令,將會創(chuàng)建一個master node,兩個worker node的Spark集群.
3.運(yùn)行kubectl get sparkcluster命令來檢查SparkCluster已經(jīng)創(chuàng)建成功,使用kubectl get pod可以看到master和worker運(yùn)行的pod信息。通過kubectl get svc可以看到spark cluster連接的服務(wù)地址
4.接下來可以通過自己的應(yīng)用,或者部署JupyterNotebook,或在pod中訪問到spark master的地址,在訪問的時候通過–master k8s://my-spark-cluster:7077的方式進(jìn)行指定。
5.您也可以通過SparkApplication直接向k8s集群提交spark任務(wù),示例yaml如下:
小結(jié)
我們在上述方法中探討了在AKS環(huán)境中運(yùn)行Spark集群的兩種方式:原生集成方式和Spark Operator方式。對于原生集成方式,需要Spark2.3以上的版本(Spark Shell則需要2.4.0以上版本),在不運(yùn)行任務(wù)的時候,可以自動銷毀pod以節(jié)約資源。Spark Operator是由第三方提供的,提供了通過Yaml的方式管理集群,運(yùn)行Spark應(yīng)用。另外由于集群是長期在aks環(huán)境中運(yùn)行,因此可以和豐富的k8s管理工具做集成。大家可以根據(jù)自己的實(shí)際需求,來選擇最適合自己的方式來運(yùn)行。