如何在 Kubernetes 環境中運行 Spark 集羣

處理這麼大量的數據,背後的機器可能是數以千計,無法通過人工來監控機器的狀態。因此,本文將介紹用 Kubernetes 容器管理工具,並通過簡單示例,告訴你如何建立一個 Spark 集羣。

準備階段

1.需要擁有正在運行的 Kubernetes 集羣,並使用 Kubectl 爲其配置訪問權限。如果你還沒有可用的 Kubernetes 集羣,則可以使用 Minikube 在本地計算機上設置測試集羣 。

  • 我們建議將 Minikube 更新爲最新版本(編寫本文檔時爲0.19.0),因爲某些早期版本可能無法啓動具有所有必要組件的 Kubernetes 集羣。

2.需要具有適當的權限才能在集羣中創建和列出 Pod,ConfigMaps 和 Secrets。想要確認,你可以通過運行 Kubectl Get Pods,Kubectl Get Configmap 以及 Kubectl Get Secrets 列出這些資源。

  • 使用的服務帳戶或憑據也必須具有相應的權限,以便編輯 Pod 模板。

3.需要擁有 Kubernetes 支持的 Spark 配置。這可以從穩定版本的 Tarball 或通過建立 Kubernetes 支持的 Spark 來獲得。

  • 需要在羣集中配置 Kubernetes 的 DNS。

準備鏡像和驅動

Kubernetes 要求用戶提供的鏡像可以部署到容器的 Pod 中。鏡像是要建立在一個 Kubernetes 支持的容器中運行的運行時環境。Docker 是一個經常與 Kubernetes 一起使用的容器運行時環境。所以 Spark 提供了一些與 Docker 一起快速入門的支持。

如果你希望使用已經構建好的 Docker 鏡像,則可以使用 Kubespark 中發佈的鏡像 。鏡像如下:

如何在 Kubernetes 環境中運行 Spark 集羣


你也可以從源代碼構建這些 Docker 鏡像,或根據需求自定義它們。分佈式 Spark 包括基礎鏡像,驅動程序,執行程序,並分別對應 dockerfiles/spark-base/Dockerfile,dockerfiles/driver/Dockerfile, dockerfiles/executor/Dockerfile,和 dockerfiles/init-container/Dockerfile。

使用這些 Docker 文件來構建 Docker 鏡像,然後這些鏡像要發送到註冊中心進行標記。最後,將鏡像推送到註冊中心。

例如,如果註冊中心主機是 Registry-Host, 正在使用5000端口:

如何在 Kubernetes 環境中運行 Spark 集羣


請注意,這個 Spark-Base 是其他鏡像的基礎鏡像。必須在其他鏡像之前構建,其他鏡像可以按任意順序構建。

把程序提交到 Kubernetes

Kubernetes 應用程序可以通過 Spark-Submit 執行。

例如,要計算 Pi 的值,假設鏡像如上所述設置:

如何在 Kubernetes 環境中運行 Spark 集羣


通過 --Master 命令行將參數傳遞給 Spark-Submit 或通過 Spark.Master 在應用程序的配置中進行設置以便來指定的 Spark 主機必須是具有該格式的 URL k8s://<api_server_url> 。

使用主字符串前綴 K8s:// 將使 Spark 應用程序在 Kubernetes 集羣上啓動,API 服務器通過 Api_server_url 與之交互 。

如果 URL 中沒有指定 HTTP 協議,則默認爲 https。

例如,將主服務器設置 K8s://example.com:443 等同於將其設置爲 K8s://https://example.com:443,但在不同端口上不使用 TLS 連接時,要將主服務器將設置爲 k8s://http://example.com:8443。

如果您有 Kubernetes 集羣設置,則可以通過執行 Kubectl cluster-info 發現 Apiserver URL。

如何在 Kubernetes 環境中運行 Spark 集羣


在上面的例子中,特定的 Kubernetes 集羣可以通過指定 --master k8s://http://127.0.0.1:8080 參數來與 Spark-Submit 一起使用 。

請注意,當前只能在集羣模式下執行應用程序,並且驅動程序及其執行程序也要在集羣上運行。

最後,請注意,在上面的例子中,我們指定了一個具有特定 URI 的 Jar 包 Local:// 。該 URI 是已經在 Docker 鏡像中的示例 Jar 包的位置。下面討論使用計算機本地磁盤上的依賴關係。

當啓用 Kubernetes RBAC 時,默認驅動程序使用的服務帳戶可能沒有合適的 Pod 編輯權限來啓動執行程序 Pod。我們建議添加另一個服務帳戶,比如擁有必要權限的 Spark。例如:

如何在 Kubernetes 環境中運行 Spark 集羣


這樣,可以添加 --conf spark.kubernetes.authenticate.driver.serviceAccountName=spark 到上面的 Spark-Submit 命令行來指定要使用的服務帳戶。

依賴管理

從機器提交的應用程序依賴關係需要被髮送到資源中轉服務器 ,然後驅動程序和執行程序可以與之通信以檢索這些依賴關係。

表示運行此服務的最小 Kubernetes 資源的 YAML 文件位於該文件中 conf/kubernetes-resource-staging-server.yaml。這個 YAML 文件配置一個 ConfigMap 的資源中轉服務器的 Pod,並通過一個帶有固定節點端口的服務公開服務。

使用包含 YAML 文件部署資源中轉服務器需要您具有創建部署,服務和配置映射的權限。

要使用默認配置運行資源中轉服務器,可以創建 Kubernetes 資源:

如何在 Kubernetes 環境中運行 Spark 集羣


然後你可以像下面例子一樣計算 Pi 的值:

如何在 Kubernetes 環境中運行 Spark 集羣


資源中轉服務器的 Docker 鏡像也可以從源代碼構建,類似於驅動程序和執行程序鏡像。

Dockerfile 提供了 dockerfiles/resource-staging-server/Dockerfile。

提供的 YAML 文件專門將服務規範中的 NodePort 設置爲31000。如果端口31000在羣集的任何節點上都不可用,則應從服務規範中刪除 NodePort 字段,並允許 Kubernetes 羣集確定 NodePort。

請確保在提交你的應用程序時,根據 Kubernetes 集羣選擇的 NodePort 在資源中轉服務器 URI 中是可用的端口。

沒有資源中轉服務器的依賴管理

請注意,此資源中轉服務器僅用於提交本地依賴項。如果你的應用程序的依賴關係全部託管在遠程位置(如 HDFS 或 HTTP 服務器)中,那麼它們可能會被其適當的遠程 URI 引用。此外,應用程序依賴關係可以預先安裝到定製的 Docker 鏡像中。這些依賴關係可以通過在 Local://URI 中引用它們和用 / 或 SPARK_EXTRA_CLASSPATH 在 Dockerfiles 中設置環境變量來添加到類路徑中。

訪問 Kubernetes 集羣

Spark-Submit 也支持通過本地 Kubectl 代理提交 。

可以使用身份驗證代理直接與 Api 服務器進行通信,而無需將憑證傳遞給 Spark-Submit。 本地代理可以通過運行下面的命令啓動:

如何在 Kubernetes 環境中運行 Spark 集羣


如果我們的本地代理正在監聽8001端口,我們會提交如下所示的代碼:

如何在 Kubernetes 環境中運行 Spark 集羣


Spark 和 Kubernetes 集羣之間的通信是使用 Fabric8 Kubernetes-Client 庫執行的。當我們擁有 Fabric8 Kubernetes-Client 庫不支持的認證提供者時,可以使用上述機制。目前支持使用 X509 客戶端證書和 OAuth 令牌進行身份驗證。

運行 PySpark

在 Kubernetes 上運行 PySpark 時和在 Yarn 和 Mesos 上啓動時使用相同的 Spark-Submit 邏輯。Python 文件可以通過在 --Py-files 設置,

以下是一個示例提交:

如何在 Kubernetes 環境中運行 Spark 集羣


Kubernetes 中的動態分配

Kubernetes 上的 Spark 支持集羣模式下的動態分配。此模式需要運行外部 Shuffle 服務。這是一個典型的 Daemonset 與 Provisioned Hostpath Volume 。這個 Shuffle 服務可以由屬於不同的 SparkJobs 的執行者共享。

這裏提供了一個示例配置文件 conf/kubernetes-shuffle-service.yaml ,可以根據需要爲特定羣集定製配置文件。需要注意的是對於 Shuffle 服務適當地設置 spec.template.metadata.labels 是很重要的,因爲在羣集中可能有多個 Shuffle 服務實例在運行。這些標籤爲 Spark 應用程序提供了一種定位指定 Shuffle 服務的方法。

舉例來說,如果我們要使用的 Shuffle 服務在默認的命名空間,與 Pods app=spark-shuffle-service 和 Spark-version=2.2.0,我們可以使用這些標籤來定位工作啓動時指定的 Shuffle 服務。爲了運行啓用動態分配的作業,該命令可能如下所示:

如何在 Kubernetes 環境中運行 Spark 集羣


外部 Shuffle 服務必須安裝可以與執行程序 Pod 共享的目錄。提供的示例 YAML 規範將 HostPath 卷掛載到外部 Shuffle 服務 Pod,但這些 HostPath 卷也必須掛載到執行程序中。

使用外部隨機播放服務時,Spark.local.dir 配置中指定的目錄將作爲 HostPath 卷掛載到所有執行程序容器中。

爲確保不會意外掛載不正確的 HostPath 卷,Spark.Local.Dir 在使用 Kubernetes 時,必須在應用程序的配置中指定值,儘管在使用其他羣集管理器時默認爲 JVM 的臨時目錄。

高級

使用 TLS 保護資源中轉服務器

資源中轉服務器的默認配置不通過 TLS 進行保護。強烈建議將其配置爲保護通過中轉服務器提交的密鑰和 Jar 文件。

YAML 文件 Conf/kubernetes-resource-staging-server.yaml 包含保存資源中轉服務器配置的 ConfigMap 資源。

可以在這裏調整屬性以使資源中轉服務器監聽 TLS。

請參閱安全性頁面以獲取與 TLS 相關的可用設置。

資源中轉服務器的命名空間是 Kubernetes.ResourceStagingServer ,例如,服務器的密鑰庫的路徑將被設置 Spark.ssl.Kubernetes.ResourceStagingServer.KeyStore。

除了之前鏈接的安全頁面指定的設置之外,資源中轉服務器還支持以下附加配置:

如何在 Kubernetes 環境中運行 Spark 集羣


請注意,儘管可以在 ConfigMap 中設置屬性,但仍然需要考慮將適當的密鑰文件安裝到資源中轉服務器的容器中。

一個常見的機制就是使用 Kubernetes 機密作爲祕密卷。請參閱相應的 Kubernetes 文檔以獲取指導,並相應地調整提供的 YAML 文件中的資源中轉服務器規範。

最後,在提交應用程序時,你必須指定一個 TrustStore 或一個 PEM 編碼的證書文件,以通過 TLS 與資源中轉服務器進行通信。

可以設置 TrustStore,也可以設置 spark.ssl.kubernetes.resourceStagingServer.trustStore 證書文件 spark.ssl.kubernetes.resourceStagingServer.clientCertPem 。

例如,我們的 SparkPi 示例如下所示:

如何在 Kubernetes 環境中運行 Spark 集羣


視頻鏈接:https://www.youtube.com/watch?v=UywgL70FQ3s

作者:靳日陽,JFrog 研發工程師

具有多年軟件開發經驗;對Java主流技術、前沿框架都具有豐富的開發經驗;擅長Linux服務器,對優化,部署等有深入研究,熟悉Jenkins,持續集成及交付,DevOps等。

歡迎轉載,但轉載請註明作者與出處。謝謝!


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章