Kubernetes助力Spark大數據分析

  • 2019 年 12 月 11 日
  • 筆記

Kubernetes 作為一個廣受歡迎的開源容器協調系統,是Google於2014年醞釀的項目。從Google趨勢上看到,Kubernetes自2014年以來熱度一路飆升,短短几年時間就已超越了大數據分析領域的長老Hadoop。本公眾號之前的文章(Kubernetes核心組件解析)也對Kubernetes的幾個組件做了一些詳細的剖析,本文就帶領大家一起看看Kubernetes和Spark碰到一起會擦出什麼樣的火花。

Spark2.3.0之前的版本只原生支援Standalone、YARN和Mesos三種部署模式,也就是說要遷移Spark2.3.0之前的Spark到Kuberbetes上,還得準備一層Standalone、YARN或者Mesos環境,不過Spark2.3.0已經引入了對Kubernetes的原生支援。

Spark2.3.0可以將編寫好的數據處理程式直接通過spark-submit提交到Kubernetes集群,通過創建一個Drive Pod和一系列Executor Pods,然後共同協調完成計算任務,整體過程的官方示意圖如下。

當我們通過spark-submit將Spark作業提交到Kubernetes集群時,會執行以下流程:

1. Spark在Kubernetes Pod中創建Spark Driver

2. Driver調用Kubernetes API創建ExecutorPods,Executor Pods執行作業程式碼

3. 計算作業結束,Executor Pods回收並清理

4. Driver Pod處於completed狀態,保留日誌,直到Kubernetes GC或者手動清理

Spark原生支援Kubernetes最大的好處是,不用在Kubernetes集群上再建立一層資源調度系統,只要建立一個新Spark容器鏡像,並指派合適的RBAC許可權角色,給所要執行的Spark應用程式,就可以在Kubernetes集群上運行Spark程式了。

接下來就介紹如何在一個Kubernetes上運行Spark程式。

1前提條件

(1) 我們測試的是Spark 2.3.0,由於Spark on Kubernetes任務提交後,實際上在集群中是以custom resources和custom controller的形式運行,所以我們需要一個1.7+版本的k8s集群,同時需要啟動Kubernetes DNS和RBAC。

(2) Spark2.3.0版本的二進位包,下載鏈接https://archive.apache.org/dist/spark/spark-2.3.0/spark-2.3.0-bin-hadoop2.6.tgz

2打包製作Spark鏡像

(1) 解壓並進入到解壓後的Spark安裝文件路徑

$ tar -zxvf spark-2.3.0-bin-hadoop2.6

$ cd spark-2.3.0-bin-hadoop2.6

(2) 製作Spark基礎鏡像

  • 使用Spark提供的docker-image-tool.sh腳本製作

$ ./bin/docker-image-tool.sh -r <repo> -t my-tag build

$ ./bin/docker-image-tool.sh -r <repo> -t my-tag push

  • 使用docker build命令製作

$ docker build -t registry/spark:2.3.0 -f kubernetes/dockerfiles/spark/Dockerfile .

(3) 查看鏡像

$ docker images | grep registry/spark

3運行Spark官方例子

(1) 獲取集群資訊,確認Kubernetes master地址

$ kubectl cluster-info

(2) 為Spark創建一個RBAC的role

$ kubectl create serviceaccount spark

$ kubectl create clusterrolebinding spark-role –clusterrole=edit –serviceaccount=default:spark –namespace=default

(3) 運行如下命令,向Kubernetes集群提交計算π值的例子

$/spark-2.3.0-bin-hadoop2.6/bin/spark-submit

–master k8s://k8s-master

–deploy-mode cluster

–name spark-pi

–class org.apache.spark.examples.SparkPi

–conf spark.kubernetes.authenticate.driver.serviceAccountName=spark

–conf spark.executor.instances=2

–conf spark.kubernetes.container.image=registry/spark:2.3.0

local:///opt/spark/examples/jars/spark-examples_2.11-2.3.0.jar

(4) 查看運行狀態,計算π值的例子運行很快,可以看到它已經運行結束了

$ kubectl get po

(5) 查看運行日誌,可以看到π值已經計算出來了

$ kubectl logs -f spark-pi-63abb54cf382394d95413f43744c65ed-Drive

至此,使用官方的例子體驗Spark on Kubernetes就完成了。那麼,如何提交自己編寫的Spark程式到Kubernetes集群呢?

其實只需把自己寫好的Spark程式編譯成jar文件,然後打包到Spark基礎鏡像中,就可以提交到Kubernetes集群中運行了。

4運行自己編寫的Spark程式

(1)準備源程式碼。以一個wordcount程式為例。程式會從一個小說網站下載《了不起的蓋茨比》的英文版小說,然後對其做詞頻統計,源程式碼如下:

import org.apache.commons.io.IOUtils import org.apache.spark.sql.functions._ import java.net.URL import org.apache.spark.sql.SparkSession class WordCount { def main(args: Array[String]) { val spark = SparkSession .builder .appName("CopyData") .getOrCreate() import spark.implicits._ val bankText = spark.sparkContext.parallelize( IOUtils.toString( new URL("http://novel.tingroom.com/novel_down.php?aid=319&dopost=txt") ).split("n")) bankText.flatMap(p=>{ val pattern = "[^a-zA-Z0-9-']".r val line = pattern.replaceAllIn(p," ") line.split(" ") }).map((_,1)).reduceByKey(_+_).sortBy(p=>p._2,false).toDF("word","count"). where(length('word)>4).show } }

(2) 源程式碼編譯為wordcount.jar文件,並編寫Dockerfile文件,內容如下:

FROM registry/spark:2.3.0

RUN mkdir -p /opt/spark/jars

COPY wordcount.jar /opt/spark/jars

(3)wordcount.jar和DockerFlie文件放在同一路徑下,並在該路徑下運行docker bulid命令打包鏡像:

$docker build -t registry/spark_wordcount:latest -f Dockerfile .

(4)使用如下命令將wordcount程式提交到Kubernetes集群:

/home/nsfocus/dengxincheng/spark-2.3.1-bin-hadoop2.6/bin/spark-submit

–master k8s://192.168.19.13:6443

–deploy-mode cluster

–name wordcount

–class example.wordcount.WordCount

–conf spark.kubernetes.authenticate.driver.serviceAccountName=spark

–conf spark.executor.instances=2

–conf spark.kubernetes.container.image=registry/spark_wordcount:latest

local:///opt/spark/jars/wordcount.jar

(5)當任務運行完了之後,使用kubectl logs查看wordcount程式運行所對應drive pod內的日誌,可以得詞頻最高的前20個詞,如下圖。

5總結

新版的Spark加入對Kubernetes的原生支援,統一了Spark程式在Kubernetes上所有工作負載的控制層,這樣可以簡化群集管理並提高資源利用率。總的來說,使用Kubernetes原生調度的Spark主要有以下優點:

原生資源調度:不再需要二級調度,直接使用Kubernetes原生的調度模組,實現與其他應用的混布;

資源隔離:任務可以提交到指定的namespace,這樣可以復用Kubernetes原生的qouta限制,實現任務資源的限制;

用戶自定義:用戶可以在Spark基礎鏡像中打上自己的Application, 更加靈活和方便;

內容編輯:安全大數據分析實驗室 鄧新程 責任編輯:肖晴