在 Kubernetes 上執行 Spark

Spark 可在由 Kubernetes 管理的叢集中執行。此功能使用已新增至 Spark 的原生 Kubernetes 排程器。

安全性

預設未啟用驗證等安全性功能。部署開放給網路或不受信任網路的叢集時,保護叢集存取權限以防止未經授權的應用程式在叢集上執行非常重要。在執行 Spark 之前,請參閱 Spark 安全性 和此文件中的特定安全性章節。

使用者身分

從專案提供的 Dockerfile 建置的映像包含預設 USER 指令,其預設 UID 為 185。這表示產生的映像將在容器內以這個 UID 執行 Spark 程序。注重安全性的部署應考慮提供自訂映像,其中 USER 指令會指定他們想要的非特權 UID 和 GID。產生的 UID 應在其補充群組中包含 root 群組,才能執行 Spark 可執行檔。使用提供的 docker-image-tool.sh 腳本建置自己映像的使用者可以使用 -u <uid> 選項指定想要的 UID。

或者,可以使用 Pod 範本 功能將 安全性內容 新增至 Spark 提交的 pod 中,其中 runAsUser。這可讓您覆寫映像本身中的 USER 指令。請記住,這需要使用者的配合,因此可能不適合共用環境。如果叢集管理員希望限制 pod 可執行的使用者,他們應使用 Pod 安全性政策

掛載磁碟區

如本文稍後 使用 Kubernetes 卷 所述,K8S 上的 Spark 提供組態選項,允許將某些卷類型掛載到驅動程式和執行器 pod 中。特別是,它允許使用 hostPath 卷,如 Kubernetes 文件中所述,已知此類卷有安全性漏洞。

叢集管理員應使用 Pod 安全性政策 來限制掛載 hostPath 卷的能力,以適當地符合其環境。

先決條件

運作方式

Spark cluster components

spark-submit 可以直接用於將 Spark 應用程式提交至 Kubernetes 叢集。提交機制運作方式如下

請注意,在已完成狀態下,驅動程式 Pod 不會 使用任何運算或記憶體資源。

驅動程式和執行器 pod 排程由 Kubernetes 處理。與 Kubernetes API 的通訊透過 fabric8 進行。透過使用其設定屬性,可以透過 節點選擇器 在可用節點的子集上排程驅動程式和執行器 pod。在未來的版本中,將可以使用更進階的排程提示,例如 節點/pod 相關性

將應用程式提交至 Kubernetes

Docker 映像

Kubernetes 要求使用者提供可在 pod 內的容器中部署的映像。這些映像會建置為在 Kubernetes 支援的容器執行時間環境中執行。Docker 是與 Kubernetes 經常搭配使用的容器執行時間環境。Spark(從版本 2.3 開始)附帶可供此目的使用的 Dockerfile,或自訂以符合個別應用程式的需求。它可以在 kubernetes/dockerfiles/ 目錄中找到。

Spark 也附帶 bin/docker-image-tool.sh 腳本,可供用於建置和發佈與 Kubernetes 後端搭配使用的 Docker 映像。

範例用法為

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

這將使用專案提供的預設 Dockerfiles 進行建置。若要查看可供自訂此工具行為的更多選項,包括提供自訂 Dockerfiles,請使用 -h 旗標執行。

預設上 bin/docker-image-tool.sh 會建置用於執行 JVM 工作的 Docker 映像。您需要選擇加入建置額外的語言繫結 Docker 映像。

範例用法為

# To build additional PySpark docker image
$ ./bin/docker-image-tool.sh -r <repo> -t my-tag -p ./kubernetes/dockerfiles/spark/bindings/python/Dockerfile build

# To build additional SparkR docker image
$ ./bin/docker-image-tool.sh -r <repo> -t my-tag -R ./kubernetes/dockerfiles/spark/bindings/R/Dockerfile build

您也可以直接使用 Apache Spark Docker 映像(例如 apache/spark:<version>)。

叢集模式

若要在叢集模式中啟動 Spark Pi,

$ ./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

Spark master,透過傳遞 --master 命令列參數給 spark-submit 或在應用程式的設定中設定 spark.master 來指定,必須是格式為 k8s://<api_server_host>:<k8s-apiserver-port> 的 URL。即使是 HTTPS 埠 443,也必須永遠指定埠。在 master 字串前面加上 k8s:// 會讓 Spark 應用程式在 Kubernetes 群集上啟動,並在 api_server_url 上與 API 伺服器聯絡。如果 URL 中未指定 HTTP 協定,則預設為 https。例如,將 master 設定為 k8s://example.com:443 等同於將其設定為 k8s://https://example.com:443,但要在不同埠上不使用 TLS 連線,則 master 會設定為 k8s://http://example.com:8080

在 Kubernetes 模式中,由 spark.app.name--name 參數指定給 spark-submit 的 Spark 應用程式名稱,預設用於命名建立的 Kubernetes 資源,例如驅動程式和執行器。因此,應用程式名稱必須包含小寫英數字元、-.,且必須以英數字元開頭和結尾。

如果您已設定 Kubernetes 群集,一種找出 apiserver URL 的方式是執行 kubectl cluster-info

$ kubectl cluster-info
Kubernetes master is running at http://127.0.0.1:6443

在上方的範例中,特定的 Kubernetes 群集可以使用 spark-submit,方法是將 --master k8s://http://127.0.0.1:6443 指定為 spark-submit 的參數。此外,也可以使用驗證代理程式 kubectl proxy 與 Kubernetes API 通訊。

可以透過以下方式啟動本機代理程式

$ kubectl proxy

如果本機代理程式在 localhost:8001 上執行,則 --master k8s://http://127.0.0.1:8001 可以用作 spark-submit 的參數。最後,請注意在上述範例中,我們使用具有 local:// 佈景的特定 URI 指定 jar。此 URI 是 Docker 映像中已存在的範例 jar 的位置。

用戶端模式

從 Spark 2.4.0 開始,可以在 Kubernetes 中以用戶端模式執行 Spark 應用程式。當應用程式以用戶端模式執行時,驅動程式可以在 Pod 內或實體主機上執行。在用戶端模式下執行應用程式時,建議考慮下列因素

用戶端模式網路

Spark 執行器必須能夠透過 Spark 執行器可路由的主機名稱和埠連線到 Spark 驅動程式。Spark 在用戶端模式下運作所需的特定網路設定會因設定而異。如果您在 Kubernetes Pod 內執行驅動程式,您可以使用無頭服務,讓驅動程式 Pod 可透過穩定的主機名稱從執行器路由。部署無頭服務時,請確保服務的標籤選擇器只會符合驅動程式 Pod,而不會符合其他 Pod;建議為驅動程式 Pod 指定一個足夠唯一的標籤,並在無頭服務的標籤選擇器中使用該標籤。透過 spark.driver.host 指定驅動程式的主機名稱,並透過 spark.driver.port 指定 Spark 驅動程式的埠。

用戶端模式執行器 Pod 垃圾回收

如果您在 Pod 中執行 Spark 驅動程式,強烈建議將 spark.kubernetes.driver.pod.name 設定為該 Pod 的名稱。設定此屬性時,Spark 排程器會使用OwnerReference部署執行器 Pod,進而確保一旦驅動程式 Pod 從叢集中刪除,應用程式的執行器 Pod 也會全部刪除。驅動程式會在 spark.kubernetes.namespace 指定的命名空間中尋找具有指定名稱的 Pod,而且會將指向該 Pod 的 OwnerReference 加入每個執行器 Pod 的 OwnerReferences 清單中。請小心不要將 OwnerReference 設定為實際上並非該驅動程式 Pod 的 Pod,否則錯誤刪除 Pod 時,執行器可能會過早終止。

如果您的應用程式未在 Pod 內執行,或者在應用程式實際上在 Pod 中執行時未設定 spark.kubernetes.driver.pod.name,請記住,在應用程式結束時,執行器 Pod 可能無法從叢集中正確刪除。Spark 排程器會嘗試刪除這些 Pod,但如果對 API 伺服器的網路要求因任何原因而失敗,這些 Pod 將會留在叢集中。當執行器無法連線到驅動程式時,執行器程序應該會結束,因此在應用程式結束後,執行器 Pod 不應該消耗叢集中的運算資源 (CPU 和記憶體)。

您可以使用 spark.kubernetes.executor.podNamePrefix 完全控制執行器 Pod 名稱。設定此屬性時,強烈建議讓它在同一個命名空間中的所有作業中保持唯一性。

驗證參數

在 client 模式中,使用確切的前綴 spark.kubernetes.authenticate 作為 Kubernetes 驗證參數。

IPv4 和 IPv6

從 3.4.0 開始,Spark 支援透過 IPv4/IPv6 雙重堆疊網路 功能,進一步支援僅 IPv6 的環境,此功能可將 IPv4 和 IPv6 位址分配給 Pod 和服務。根據 K8s 集群功能,spark.kubernetes.driver.service.ipFamilyPolicyspark.kubernetes.driver.service.ipFamilies 可以是 SingleStackPreferDualStackRequireDualStack 中的一個,以及 IPv4IPv6IPv4,IPv6IPv6,IPv4 中的一個。預設情況下,Spark 使用 spark.kubernetes.driver.service.ipFamilyPolicy=SingleStackspark.kubernetes.driver.service.ipFamilies=IPv4

若要僅使用 IPv6,您可以提交以下工作。

...
    --conf spark.kubernetes.driver.service.ipFamilies=IPv6 \

DualStack 環境中,您可能需要 java.net.preferIPv6Addresses=true for JVM 和 SPARK_PREFER_IPV6=true for Python 才能使用 IPv6

相依性管理

如果應用程式的相依性都託管在遠端位置,例如 HDFS 或 HTTP 伺服器,則可以使用其適當的遠端 URI 來參照它們。此外,應用程式相依性可以預先安裝到自訂建置的 Docker 映像中。這些相依性可以透過使用 local:// URI 和/或在 Dockerfile 中設定 SPARK_EXTRA_CLASSPATH 環境變數來新增到類別路徑中。在 spark-submit 中參照自訂建置 Docker 映像中的相依性時,也需要 local:// 架構。我們使用 file:// 架構或不使用架構(使用完整路徑)支援來自提交用戶端本機檔案系統的相依性,其中目的地應該是 Hadoop 相容的檔案系統。使用 S3 的典型範例是傳遞下列選項

...
--packages org.apache.hadoop:hadoop-aws:3.2.2
--conf spark.kubernetes.file.upload.path=s3a://<s3-bucket>/path
--conf spark.hadoop.fs.s3a.access.key=...
--conf spark.hadoop.fs.s3a.impl=org.apache.hadoop.fs.s3a.S3AFileSystem
--conf spark.hadoop.fs.s3a.fast.upload=true
--conf spark.hadoop.fs.s3a.secret.key=....
--conf spark.driver.extraJavaOptions=-Divy.cache.dir=/tmp -Divy.home=/tmp
file:///full/path/to/app.jar

應用程式 jar 檔案將上傳到 S3,然後在啟動驅動程式時,它將下載到驅動程式 pod 並新增到其類別路徑中。Spark 將在上傳路徑下產生一個具有隨機名稱的子目錄,以避免與並行執行的 Spark 應用程式發生衝突。使用者可以根據自己的需要管理所建立的子目錄。

應用程式 jar、以及由屬性 spark.jarsspark.filesspark.archives 指定的相依性,都支援用戶端架構。

重要:所有用戶端相依性都將上傳到指定路徑,且目錄結構為平面結構,因此檔案名稱必須唯一,否則檔案將會被覆寫。此外,請確保在衍生的 k8s 映像中,預設的 ivy 目錄具有必要的存取權限,或修改上述設定。如果您在叢集模式中使用 --packages,後者也很重要。

機密管理

Kubernetes 機密 可用於提供 Spark 應用程式的認證資訊,以存取安全服務。如要將使用者指定的機密掛載到驅動程式容器中,使用者可以使用 spark.kubernetes.driver.secrets.[SecretName]=<mount path> 形式的組態屬性。類似地,spark.kubernetes.executor.secrets.[SecretName]=<mount path> 形式的組態屬性可用於將使用者指定的機密掛載到執行器容器中。請注意,假設要掛載的機密與驅動程式和執行器 pod 屬於同一個名稱空間。例如,如要將名為 spark-secret 的機密掛載到驅動程式和執行器容器中的 /etc/secrets 路徑,請將下列選項新增到 spark-submit 指令

--conf spark.kubernetes.driver.secrets.spark-secret=/etc/secrets
--conf spark.kubernetes.executor.secrets.spark-secret=/etc/secrets

如要透過環境變數使用機密,請將下列選項新增到 spark-submit 指令

--conf spark.kubernetes.driver.secretKeyRef.ENV_NAME=name:key
--conf spark.kubernetes.executor.secretKeyRef.ENV_NAME=name:key

Pod 範本

Kubernetes 允許從 範本檔案 中定義 pod。Spark 使用者也可以類似地使用範本檔案來定義 Spark 組態不支援的驅動程式或執行器 pod 組態。為此,請指定 Spark 屬性 spark.kubernetes.driver.podTemplateFilespark.kubernetes.executor.podTemplateFile,以指向 spark-submit 程序可以存取的檔案。

--conf spark.kubernetes.driver.podTemplateFile=s3a://bucket/driver.yml
--conf spark.kubernetes.executor.podTemplateFile=s3a://bucket/executor.yml

為了讓驅動程式 pod 存取執行器 pod 範本檔案,系統會在建立驅動程式 pod 時自動將檔案掛載到驅動程式 pod 中的磁碟區。Spark 在取消封送這些範本檔案之後不會執行任何驗證,而是依賴 Kubernetes API 伺服器進行驗證。

請注意 Spark 對某些 Pod 組態有既定看法,因此 Pod 範本中的值永遠都會被 Spark 覆寫。因此,此功能的使用者應注意,指定 Pod 範本檔案只會讓 Spark 在 Pod 建置過程中以範本 Pod 而不是空 Pod 開始。有關詳細資訊,請參閱 Spark 會覆寫的 Pod 範本值完整清單

Pod 範本檔案也可以定義多個容器。在這種情況下,您可以使用 Spark 屬性 spark.kubernetes.driver.podTemplateContainerNamespark.kubernetes.executor.podTemplateContainerName 來指出哪個容器應作為驅動程式或執行器的基礎。如果未指定,或如果容器名稱無效,Spark 會假設清單中的第一個容器會是驅動程式或執行器容器。

使用 Kubernetes 磁碟區

使用者可以將下列 Kubernetes 類型的掛載到驅動程式和執行器 Pod

注意:請參閱此文件中的安全性部分,以了解與卷掛載相關的安全性問題。

若要將上述任何類型的卷掛載到驅動程式 Pod 中,請使用下列組態屬性

--conf spark.kubernetes.driver.volumes.[VolumeType].[VolumeName].mount.path=<mount path>
--conf spark.kubernetes.driver.volumes.[VolumeType].[VolumeName].mount.readOnly=<true|false>
--conf spark.kubernetes.driver.volumes.[VolumeType].[VolumeName].mount.subPath=<mount subPath>

特別是,VolumeType 可以是下列值之一:hostPathemptyDirnfspersistentVolumeClaimVolumeName 是您要在 Pod 規格中的volumes 欄位下用於卷的名稱。

每種受支援的卷類型可能有一些特定組態選項,可以使用下列格式的組態屬性來指定

spark.kubernetes.driver.volumes.[VolumeType].[VolumeName].options.[OptionName]=<value>

例如,具有卷名稱 imagesnfs 的伺服器和路徑可以使用下列屬性指定

spark.kubernetes.driver.volumes.nfs.images.options.server=example.com
spark.kubernetes.driver.volumes.nfs.images.options.path=/data

而且,使用下列屬性可以指定具有卷名稱 checkpointpvcpersistentVolumeClaim 的宣告名稱

spark.kubernetes.driver.volumes.persistentVolumeClaim.checkpointpvc.options.claimName=check-point-pvc-claim

用於將卷掛載到執行器 pod 的組態屬性使用前綴 spark.kubernetes.executor.,而非 spark.kubernetes.driver.

例如,您可以使用 OnDemand 作為宣告名稱和 storageClasssizeLimit 選項,如下所示,來掛載每個執行器的動態建立的持續卷宣告。這在 動態配置 的情況下很有用。

spark.kubernetes.executor.volumes.persistentVolumeClaim.data.options.claimName=OnDemand
spark.kubernetes.executor.volumes.persistentVolumeClaim.data.options.storageClass=gp
spark.kubernetes.executor.volumes.persistentVolumeClaim.data.options.sizeLimit=500Gi
spark.kubernetes.executor.volumes.persistentVolumeClaim.data.mount.path=/data
spark.kubernetes.executor.volumes.persistentVolumeClaim.data.mount.readOnly=false

如需每個支援卷類型的可用選項的完整清單,請參閱下列 Spark 屬性 區段。

PVC 導向執行器 pod 分配

由於磁碟是重要的資源類型之一,Spark 驅動程式透過一組組態提供細緻的控制。例如,預設情況下,依需求的 PVC 由執行器擁有,而 PVC 的生命週期與其擁有者執行器緊密結合。不過,依需求的 PVC 可以由驅動程式擁有,並在 Spark 工作的存續期間由其他執行器重複使用,方法如下。這可以減少 PVC 建立和刪除的負擔。

spark.kubernetes.driver.ownPersistentVolumeClaim=true
spark.kubernetes.driver.reusePersistentVolumeClaim=true

此外,自 Spark 3.4 起,Spark 驅動程式能夠執行以 PVC 為導向的執行器配置,這表示 Spark 會計算工作可以擁有的已建立 PVC 的總數,並在驅動程式擁有最大數量的 PVC 時暫停建立新的執行器。這有助於將現有的 PVC 從一個執行器轉移到另一個執行器。

spark.kubernetes.driver.waitToReusePersistentVolumeClaim=true

本機儲存

Spark 支援在混洗和其他作業期間使用卷來溢出資料。若要將卷用作本機儲存,卷的名稱應以 spark-local-dir- 開頭,例如

--conf spark.kubernetes.driver.volumes.[VolumeType].spark-local-dir-[VolumeName].mount.path=<mount path>
--conf spark.kubernetes.driver.volumes.[VolumeType].spark-local-dir-[VolumeName].mount.readOnly=false

具體來說,如果工作需要在執行器中執行大型混洗和排序作業,您可以使用持續卷宣告。

spark.kubernetes.executor.volumes.persistentVolumeClaim.spark-local-dir-1.options.claimName=OnDemand
spark.kubernetes.executor.volumes.persistentVolumeClaim.spark-local-dir-1.options.storageClass=gp
spark.kubernetes.executor.volumes.persistentVolumeClaim.spark-local-dir-1.options.sizeLimit=500Gi
spark.kubernetes.executor.volumes.persistentVolumeClaim.spark-local-dir-1.mount.path=/data
spark.kubernetes.executor.volumes.persistentVolumeClaim.spark-local-dir-1.mount.readOnly=false

若要透過內建的 KubernetesLocalDiskShuffleDataIO 外掛程式啟用混洗資料復原功能,我們需要具備下列條件。您可能還想另外啟用 spark.kubernetes.driver.waitToReusePersistentVolumeClaim

spark.kubernetes.executor.volumes.persistentVolumeClaim.spark-local-dir-1.mount.path=/data/spark-x/executor-x
spark.shuffle.sort.io.plugin.class=org.apache.spark.shuffle.KubernetesLocalDiskShuffleDataIO

如果未將任何卷設定為本機儲存,Spark 會在混洗和其他作業期間使用暫時的暫存空間將資料溢出到磁碟。當使用 Kubernetes 作為資源管理員時,將會為 spark.local.dir 或環境變數 SPARK_LOCAL_DIRS 中列出的每個目錄掛載一個 emptyDir 卷來建立 pod。如果未明確指定任何目錄,則會建立一個預設目錄並適當地加以組態。

emptyDir 卷使用 Kubernetes 的臨時儲存功能,且不會在 pod 的存續期間後持續存在。

使用 RAM 作為本機儲存

emptyDir 卷預設使用節點後端儲存空間作為暫存儲存空間,這種行為可能不適用於某些運算環境。例如,如果您有透過網路掛載遠端儲存空間的無磁碟節點,讓大量執行器對此遠端儲存空間進行 I/O 實際上可能會降低效能。

在這種情況下,您可能希望在設定檔中設定 spark.kubernetes.local.dirs.tmpfs=true,這會讓 emptyDir 卷設定為 tmpfs,也就是由 RAM 支援的卷。如此設定後,Spark 的本地儲存空間使用量會計入您的 pod 記憶體使用量,因此您可能希望透過適當增加 spark.{driver,executor}.memoryOverheadFactor 的值來增加您的記憶體要求。

內部檢視和除錯

以下列出您可以調查正在執行/已完成的 Spark 應用程式、監控進度並採取行動的不同方式。

存取記錄

可以使用 Kubernetes API 和 kubectl CLI 存取記錄。當 Spark 應用程式正在執行時,可以使用下列方式從應用程式串流記錄

$ kubectl -n=<namespace> logs -f <driver-pod-name>

如果已在叢集上安裝,也可以透過 Kubernetes 儀表板 存取相同的記錄。

存取驅動程式 UI

可以使用 kubectl port-forward 在本地端存取與任何應用程式相關的 UI。

$ kubectl port-forward <driver-pod-name> 4040:4040

然後,可以在 https://127.0.0.1:4040 上存取 Spark 驅動程式 UI。

除錯

可能會發生多種失敗。如果 Kubernetes API 伺服器拒絕 spark-submit 發出的要求,或因其他原因拒絕連線,提交邏輯應指出遇到的錯誤。但是,如果在應用程式執行期間發生錯誤,通常最好的調查方式可能是透過 Kubernetes CLI。

若要取得有關驅動程式 pod 周圍排程決策的一些基本資訊,您可以執行

$ kubectl describe pod <spark-driver-pod>

如果 pod 遇到執行時期錯誤,可以使用下列方式進一步探查狀態

$ kubectl logs <spark-driver-pod>

已失敗的執行器 Pod 的狀態和記錄可以透過類似的方式檢查。最後,刪除驅動程式 Pod 會清除整個 Spark 應用程式,包括所有執行器、相關服務等。驅動程式 Pod 可以視為 Spark 應用程式的 Kubernetes 表示。

Kubernetes 功能

組態檔

您的 Kubernetes 設定檔通常位於您的家目錄中的 .kube/config 中,或位於 KUBECONFIG 環境變數所指定的位址中。Kubernetes 上的 Spark 會嘗試使用這個檔案來對用於與 Kubernetes 集群互動的 Kubernetes 執行自動設定。提供各種 Spark 設定屬性,允許進一步自訂用戶端設定,例如使用替代驗證方法。

內容

Kubernetes 設定檔可以包含多個內容,允許在不同的集群和/或使用者身分之間切換。預設情況下,Kubernetes 上的 Spark 會在對 Kubernetes 執行自動設定時使用您的目前內容(可透過執行 kubectl config current-context 檢查)。

為了使用替代內容,使用者可以透過 Spark 設定屬性 spark.kubernetes.context 指定所需的內容,例如 spark.kubernetes.context=minikube

命名空間

Kubernetes 有 命名空間 的概念。命名空間是透過資源配額在多個使用者之間分割集群資源的方式。Kubernetes 上的 Spark 可以使用命名空間來啟動 Spark 應用程式。這可以使用 spark.kubernetes.namespace 設定來使用。

Kubernetes 允許使用 資源配額 來設定資源限制、物件數量等,在個別命名空間上。命名空間和資源配額可以由管理員結合使用,以控制執行 Spark 應用程式的 Kubernetes 集群中的共用和資源配置。

RBAC

在啟用 RBAC 的 Kubernetes 集群中,使用者可以設定 Kubernetes RBAC 角色和服務帳戶,由 Kubernetes 上的各種 Spark 元件使用來存取 Kubernetes API 伺服器。

Spark 驅動程式 Pod 使用 Kubernetes 服務帳戶來存取 Kubernetes API 伺服器,以建立和監控執行器 Pod。驅動程式 Pod 所使用的服務帳戶必須具有適當的權限,才能讓驅動程式執行其工作。具體來說,服務帳戶至少必須被授予 角色叢集角色,允許驅動程式 Pod 建立 Pod 和服務。預設情況下,如果在建立 Pod 時未指定服務帳戶,則會自動將 預設 服務帳戶指派給 spark.kubernetes.namespace 所指定的命名空間中的驅動程式 Pod。

根據已部署的 Kubernetes 版本和設定,此 預設 服務帳戶可能具有或不具有允許驅動程式 Pod 在預設 Kubernetes RBAC 政策下建立 Pod 和服務的角色。有時使用者可能需要指定已授予正確角色的客製化服務帳戶。Spark on Kubernetes 支援透過組態屬性 spark.kubernetes.authenticate.driver.serviceAccountName=<服務帳戶名稱> 指定驅動程式 Pod 要使用的客製化服務帳戶。例如,若要讓驅動程式 Pod 使用 spark 服務帳戶,使用者只需將下列選項新增至 spark-submit 指令

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

若要建立客製化服務帳戶,使用者可以使用 kubectl create serviceaccount 指令。例如,下列指令會建立一個名為 spark 的服務帳戶

$ kubectl create serviceaccount spark

若要授予服務帳戶 角色叢集角色,則需要 角色繫結叢集角色繫結。若要建立 角色繫結叢集角色繫結,使用者可以使用 kubectl create rolebinding(或 clusterrolebinding,針對 叢集角色繫結)指令。例如,下列指令會在 預設 名稱空間中建立一個 編輯 叢集角色,並將其授予上述建立的 spark 服務帳戶

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

請注意,角色 只能用於授予單一名稱空間內資源(例如 Pod)的存取權,而 叢集角色 則可用於授予存取所有名稱空間中叢集範圍資源(例如節點)以及名稱空間資源(例如 Pod)的權限。對於 Spark on Kubernetes,由於驅動程式總是會在同一個名稱空間中建立執行器 Pod,因此 角色 就已足夠,不過使用者也可以使用 叢集角色。有關 RBAC 授權和如何為 Pod 組態 Kubernetes 服務帳戶的詳細資訊,請參閱 使用 RBAC 授權為 Pod 組態服務帳戶

Spark 應用程式管理

Kubernetes 提供簡單的應用程式管理,透過叢集模式中的 spark-submit CLI 工具。使用者可以透過提供提交工作時印出的提交 ID 來終止工作。提交 ID 的格式為 namespace:driver-pod-name。如果使用者省略命名空間,則會使用目前 k8s 環境中設定的命名空間。例如,如果使用者已設定特定命名空間如下 kubectl config set-context minikube --namespace=spark,則預設會使用 spark 命名空間。另一方面,如果沒有將命名空間新增到特定環境,則預設會考量所有命名空間。這表示作業會影響與給定提交 ID 相符的所有 Spark 應用程式,不論命名空間為何。此外,用於應用程式管理的 spark-submit 使用與用於提交驅動程式相同的後端程式碼,因此相同的屬性(例如 spark.kubernetes.context 等)可以重複使用。

例如

$ spark-submit --kill spark:spark-pi-1547948636094-driver --master k8s://https://192.168.2.8:8443

使用者也可以使用 --status 標記列出應用程式狀態

$ spark-submit --status spark:spark-pi-1547948636094-driver --master  k8s://https://192.168.2.8:8443

這兩個作業都支援 glob 模式。例如,使用者可以執行

$ spark-submit --kill spark:spark-pi* --master  k8s://https://192.168.2.8:8443

上述指令會終止所有具有特定字首的應用程式。

使用者可以透過 spark.kubernetes.appKillPodDeletionGracePeriod 屬性指定 pod 終止的寬限期,使用 --conf 作為提供它的方式(所有 K8s pod 的預設值為 30 秒)。

未來工作

目前正在開發或計畫開發多項 Kubernetes 上的 Spark 功能。這些功能預計最終會納入 spark-kubernetes 整合的未來版本。

其中一些功能包括

組態

請參閱 組態頁面,以取得 Spark 組態的資訊。下列組態專屬於 Kubernetes 上的 Spark。

Spark 屬性

屬性名稱預設值意義自版本
spark.kubernetes.context (無) 用於 Kubernetes 用戶端程式庫初始自動組態的使用者 Kubernetes 組態檔案中的環境。未指定時,會使用使用者的目前環境。注意:許多自動組態的設定都可以透過使用其他 Spark 組態屬性來覆寫,例如 spark.kubernetes.namespace 3.0.0
spark.kubernetes.driver.master https://kubernetes.default.svc 用於驅動程式要求執行器或「local[*]」的驅動程式模式的內部 Kubernetes 主控 (API 伺服器) 位址。 3.0.0
spark.kubernetes.namespace default 用於執行驅動程式和執行器 pod 的命名空間。 2.3.0
spark.kubernetes.container.image (無) 用於 Spark 應用程式的容器映像。這通常是 example.com/repo/spark:v1.0.0 形式。此設定是必需的,且必須由使用者提供,除非為每種不同的容器類型提供明確的映像。 2.3.0
spark.kubernetes.driver.container.image (spark.kubernetes.container.image 的值) 用於驅動程式的自訂容器映像。 2.3.0
spark.kubernetes.executor.container.image (spark.kubernetes.container.image 的值) 用於執行器的自訂容器映像。 2.3.0
spark.kubernetes.container.image.pullPolicy IfNotPresent 在 Kubernetes 中提取映像時使用的容器映像提取政策。有效值為 AlwaysNeverIfNotPresent 2.3.0
spark.kubernetes.container.image.pullSecrets 用於從私人映像登錄提取映像的 Kubernetes 密碼的逗號分隔清單。 2.4.0
spark.kubernetes.allocation.batch.size 5 在每一輪執行器 pod 分配中一次啟動的 pod 數量。 2.3.0
spark.kubernetes.allocation.batch.delay 1s 每一輪執行器 pod 分配之間的等待時間。指定小於 1 秒的值可能會導致 spark 驅動程式過度使用 CPU。 2.3.0
spark.kubernetes.authenticate.submission.caCertFile (無) 在啟動驅動程式時透過 TLS 連線到 Kubernetes API 伺服器時,CA 憑證檔案的路徑。此檔案必須位於提交電腦的磁碟上。將此指定為路徑,而不是 URI (即不要提供架構)。在用戶端模式中,請改用 spark.kubernetes.authenticate.caCertFile 2.3.0
spark.kubernetes.authenticate.submission.clientKeyFile (無) 在啟動驅動程式時驗證 Kubernetes API 伺服器時,用戶端金鑰檔案的路徑。此檔案必須位於提交電腦的磁碟上。將此指定為路徑,而不是 URI (即不要提供架構)。在用戶端模式中,請改用 spark.kubernetes.authenticate.clientKeyFile 2.3.0
spark.kubernetes.authenticate.submission.clientCertFile (無) 在啟動驅動程式時驗證 Kubernetes API 伺服器時,用戶端憑證檔案的路徑。此檔案必須位於提交電腦的磁碟上。將此指定為路徑,而不是 URI (即不要提供架構)。在用戶端模式中,請改用 spark.kubernetes.authenticate.clientCertFile 2.3.0
spark.kubernetes.authenticate.submission.oauthToken (無) 啟動驅動程式時,用於對抗 Kubernetes API 伺服器進行驗證的 OAuth 令牌。請注意,與其他驗證選項不同,這應為用於驗證的令牌的確切字串值。在用戶端模式中,請改用 spark.kubernetes.authenticate.oauthToken 2.3.0
spark.kubernetes.authenticate.submission.oauthTokenFile (無) 啟動驅動程式時,用於對抗 Kubernetes API 伺服器進行驗證的 OAuth 令牌檔案路徑。此檔案必須位於提交機器磁碟上。請指定此路徑,而不要指定 URI(即不要提供架構)。在用戶端模式中,請改用 spark.kubernetes.authenticate.oauthTokenFile 2.3.0
spark.kubernetes.authenticate.driver.caCertFile (無) 請求執行器時,從驅動程式 Pod 透過 TLS 連線到 Kubernetes API 伺服器的 CA 憑證檔案路徑。此檔案必須位於提交機器磁碟上,並將上傳到驅動程式 Pod。請指定此路徑,而不要指定 URI(即不要提供架構)。在用戶端模式中,請改用 spark.kubernetes.authenticate.caCertFile 2.3.0
spark.kubernetes.authenticate.driver.clientKeyFile (無) 請求執行器時,從驅動程式 Pod 對抗 Kubernetes API 伺服器進行驗證的用戶端金鑰檔案路徑。此檔案必須位於提交機器磁碟上,並將上傳到驅動程式 Pod 作為 Kubernetes 祕密。請指定此路徑,而不要指定 URI(即不要提供架構)。在用戶端模式中,請改用 spark.kubernetes.authenticate.clientKeyFile 2.3.0
spark.kubernetes.authenticate.driver.clientCertFile (無) 請求執行器時,從驅動程式 Pod 對抗 Kubernetes API 伺服器進行驗證的用戶端憑證檔案路徑。此檔案必須位於提交機器磁碟上,並將上傳到驅動程式 Pod 作為 Kubernetes 祕密。請指定此路徑,而不要指定 URI(即不要提供架構)。在用戶端模式中,請改用 spark.kubernetes.authenticate.clientCertFile 2.3.0
spark.kubernetes.authenticate.driver.oauthToken (無) 請求執行器時,從驅動程式 Pod 對抗 Kubernetes API 伺服器進行驗證時使用的 OAuth 令牌。請注意,與其他驗證選項不同,這必須為用於驗證的令牌的確切字串值。此令牌值上傳到驅動程式 Pod 作為 Kubernetes 祕密。在用戶端模式中,請改用 spark.kubernetes.authenticate.oauthToken 2.3.0
spark.kubernetes.authenticate.driver.oauthTokenFile (無) 在請求執行器時,從驅動程式 pod 對 Kubernetes API 伺服器進行驗證時,包含要使用的權杖的 OAuth 權杖檔案路徑。請注意,與其他驗證選項不同,此檔案必須包含用於驗證的權杖的確切字串值。此權杖值會上傳到驅動程式 pod 中做為機密。在用戶端模式中,請改用 spark.kubernetes.authenticate.oauthTokenFile 2.3.0
spark.kubernetes.authenticate.driver.mounted.caCertFile (無) 在請求執行器時,透過 TLS 從驅動程式 pod 連線到 Kubernetes API 伺服器的 CA 憑證檔案路徑。驅動程式 pod 必須可以存取此路徑。指定此路徑為路徑,而不是 URI(即不提供架構)。在用戶端模式中,請改用 spark.kubernetes.authenticate.caCertFile 2.3.0
spark.kubernetes.authenticate.driver.mounted.clientKeyFile (無) 在請求執行器時,從驅動程式 pod 對 Kubernetes API 伺服器進行驗證的用戶端金鑰檔案路徑。驅動程式 pod 必須可以存取此路徑。指定此路徑為路徑,而不是 URI(即不提供架構)。在用戶端模式中,請改用 spark.kubernetes.authenticate.clientKeyFile 2.3.0
spark.kubernetes.authenticate.driver.mounted.clientCertFile (無) 在請求執行器時,從驅動程式 pod 對 Kubernetes API 伺服器進行驗證的用戶端憑證檔案路徑。驅動程式 pod 必須可以存取此路徑。指定此路徑為路徑,而不是 URI(即不提供架構)。在用戶端模式中,請改用 spark.kubernetes.authenticate.clientCertFile 2.3.0
spark.kubernetes.authenticate.driver.mounted.oauthTokenFile (無) 在請求執行器時,從驅動程式 pod 對 Kubernetes API 伺服器進行驗證時,包含要使用的 OAuth 權杖的檔案路徑。驅動程式 pod 必須可以存取此路徑。請注意,與其他驗證選項不同,此檔案必須包含用於驗證的權杖的確切字串值。在用戶端模式中,請改用 spark.kubernetes.authenticate.oauthTokenFile 2.3.0
spark.kubernetes.authenticate.driver.serviceAccountName default 在執行驅動程式 pod 時使用的服務帳戶。驅動程式 pod 在從 API 伺服器請求執行器 pod 時,會使用此服務帳戶。請注意,這不能與 CA 憑證檔案、用戶端金鑰檔案、用戶端憑證檔案和/或 OAuth 權杖同時指定。在用戶端模式中,請改用 spark.kubernetes.authenticate.serviceAccountName 2.3.0
spark.kubernetes.authenticate.executor.serviceAccountName (spark.kubernetes.authenticate.driver.serviceAccountName 的值) 執行 executor pod 時使用的服務帳戶。如果未設定此參數,後備邏輯會使用驅動程式的服務帳戶。 3.1.0
spark.kubernetes.authenticate.caCertFile (無) 在用戶端模式中,透過 TLS 連線到 Kubernetes API 伺服器時,CA 憑證檔案的路徑,以要求 executor。指定為路徑,而不是 URI(即不提供 scheme)。 2.4.0
spark.kubernetes.authenticate.clientKeyFile (無) 在用戶端模式中,要求 executor 時,用於對抗 Kubernetes API 伺服器進行驗證的用戶端金鑰檔案的路徑。指定為路徑,而不是 URI(即不提供 scheme)。 2.4.0
spark.kubernetes.authenticate.clientCertFile (無) 在用戶端模式中,要求 executor 時,用於對抗 Kubernetes API 伺服器進行驗證的用戶端憑證檔案的路徑。指定為路徑,而不是 URI(即不提供 scheme)。 2.4.0
spark.kubernetes.authenticate.oauthToken (無) 在用戶端模式中,要求 executor 時,用於對抗 Kubernetes API 伺服器進行驗證的 OAuth 權杖。請注意,與其他驗證選項不同,這必須是驗證要使用的權杖的確切字串值。 2.4.0
spark.kubernetes.authenticate.oauthTokenFile (無) 在用戶端模式中,要求 executor 時,包含用於對抗 Kubernetes API 伺服器進行驗證的 OAuth 權杖的檔案路徑。 2.4.0
spark.kubernetes.driver.label.[標籤名稱] (無) 標籤名稱 指定的標籤新增到驅動程式 pod。例如,spark.kubernetes.driver.label.something=true。請注意,Spark 也會將自己的標籤新增到驅動程式 pod 以進行簿記。 2.3.0
spark.kubernetes.driver.annotation.[註解名稱] (無) 註解名稱 指定的 Kubernetes 註解 新增到驅動程式 pod。例如,spark.kubernetes.driver.annotation.something=true 2.3.0
spark.kubernetes.driver.service.label.[標籤名稱] (無) 標籤名稱 指定的 Kubernetes 標籤 新增到驅動程式服務。例如,spark.kubernetes.driver.service.label.something=true。請注意,Spark 也會將自己的標籤新增到驅動程式服務以進行簿記。 3.4.0
spark.kubernetes.driver.service.annotation.[註解名稱] (無) 註解名稱 指定的 Kubernetes 註解 新增到驅動程式服務。例如,spark.kubernetes.driver.service.annotation.something=true 3.0.0
spark.kubernetes.executor.label.[標籤名稱] (無) 標籤名稱 指定的標籤新增到 executor pod。例如,spark.kubernetes.executor.label.something=true。請注意,Spark 也會將自己的標籤新增到 executor pod 以進行簿記。 2.3.0
spark.kubernetes.executor.annotation.[註解名稱] (無) 註解名稱 指定的 Kubernetes 註解 加入執行器 Pod。例如,spark.kubernetes.executor.annotation.something=true 2.3.0
spark.kubernetes.driver.pod.name (無) 驅動程式 Pod 的名稱。在叢集模式中,如果未設定此值,驅動程式 Pod 名稱會設為「spark.app.name」,並加上目前的 timestamp,以避免名稱衝突。在用戶端模式中,如果您的應用程式在 Pod 內執行,強烈建議您將此值設為驅動程式執行的 Pod 名稱。在用戶端模式中設定此值,可讓驅動程式成為其執行器 Pod 的擁有者,進而讓叢集清除執行器 Pod。 2.3.0
spark.kubernetes.executor.podNamePrefix (無) 用於執行器 Pod 名稱開頭的前置詞。它必須符合 Kubernetes DNS 標籤名稱 所定義的規則。前置詞會用於產生執行器 Pod 名稱,格式為 $podNamePrefix-exec-$id,其中 `id` 是正整數值,因此 `podNamePrefix` 的長度必須小於或等於 47(= 63 - 10 - 6)。 2.3.0
spark.kubernetes.submission.waitAppCompletion true 在叢集模式中,是否在結束啟動器程序前,等待應用程式完成。當變更為 false 時,啟動器在啟動 Spark 工作時,會呈現「發射後就忘記」的行為。 2.3.0
spark.kubernetes.report.interval 1s 在叢集模式中,目前 Spark 工作狀態報告之間的間隔。 2.3.0
spark.kubernetes.executor.apiPollingInterval 30s 檢查執行器狀態時,對 Kubernetes API 伺服器進行輪詢之間的間隔。 2.4.0
spark.kubernetes.driver.request.cores (無) 指定驅動程式 Pod 的 CPU 要求。值符合 Kubernetes 慣例。範例值包括 0.1、500m、1.5、5 等,CPU 單位的定義記載於 CPU 單位 中。如果已設定,此值優先於 spark.driver.cores,用於指定驅動程式 Pod CPU 要求。 3.0.0
spark.kubernetes.driver.limit.cores (無) 為驅動程式 Pod 指定一個硬 CPU 限制 2.3.0
spark.kubernetes.executor.request.cores (無) 指定每個執行器 Pod 的 CPU 要求。值符合 Kubernetes 慣例。範例值包括 0.1、500m、1.5、5 等,CPU 單位的定義記載於 CPU 單位 中。這與 spark.executor.cores 不同:如果已設定,它只會用於並優先於 spark.executor.cores,用於指定執行器 Pod CPU 要求。任務並行性(例如,執行器可以同時執行的任務數)不受此影響。 2.4.0
spark.kubernetes.executor.limit.cores (無) 為每個為 Spark 應用程式啟動的執行器 pod 指定硬式 CPU 限制 2.3.0
spark.kubernetes.node.selector.[labelKey] (無) 新增到驅動程式 pod 和執行器 pod 的節點選擇器,其中金鑰為 labelKey,值為組態的值。例如,將 spark.kubernetes.node.selector.identifier 設定為 myIdentifier,將導致驅動程式 pod 和執行器具有金鑰為 identifier,值為 myIdentifier 的節點選擇器。可透過設定多個具有此字首的組態,新增多個節點選擇器金鑰。 2.3.0
spark.kubernetes.driver.node.selector.[labelKey] (無) 新增到驅動程式 pod 的驅動程式節點選擇器,其中金鑰為 labelKey,值為組態的值。例如,將 spark.kubernetes.driver.node.selector.identifier 設定為 myIdentifier,將導致驅動程式 pod 具有金鑰為 identifier,值為 myIdentifier 的節點選擇器。可透過設定多個具有此字首的組態,新增多個驅動程式節點選擇器金鑰。 3.3.0
spark.kubernetes.executor.node.selector.[labelKey] (無) 新增到執行器 pod 的執行器節點選擇器,其中金鑰為 labelKey,值為組態的值。例如,將 spark.kubernetes.executor.node.selector.identifier 設定為 myIdentifier,將導致執行器具有金鑰為 identifier,值為 myIdentifier 的節點選擇器。可透過設定多個具有此字首的組態,新增多個執行器節點選擇器金鑰。 3.3.0
spark.kubernetes.driverEnv.[EnvironmentVariableName] (無) EnvironmentVariableName 指定的環境變數新增到驅動程式程序。使用者可以指定多個這些來設定多個環境變數。 2.3.0
spark.kubernetes.driver.secrets.[SecretName] (無) 將名為 SecretNameKubernetes Secret 新增到驅動程式 pod,路徑指定在值中。例如,spark.kubernetes.driver.secrets.spark-secret=/etc/secrets 2.3.0
spark.kubernetes.executor.secrets.[SecretName] (無) 將名為 SecretNameKubernetes Secret 新增到執行器 pod,路徑指定在值中。例如,spark.kubernetes.executor.secrets.spark-secret=/etc/secrets 2.3.0
spark.kubernetes.driver.secretKeyRef.[EnvName] (無) 將值參考為 Kubernetes Secret 的資料中鍵 key 的環境變數新增至驅動程式容器,名稱為 EnvName (大小寫敏感)。例如,spark.kubernetes.driver.secretKeyRef.ENV_VAR=spark-secret:key 2.4.0
spark.kubernetes.executor.secretKeyRef.[EnvName] (無) 將值參考為 Kubernetes Secret 的資料中鍵 key 的環境變數新增至執行器容器,名稱為 EnvName (大小寫敏感)。例如,spark.kubernetes.executor.secrets.ENV_VAR=spark-secret:key 2.4.0
spark.kubernetes.driver.volumes.[VolumeType].[VolumeName].mount.path (無) VolumeType 類型的名為 VolumeNameKubernetes Volume 新增至驅動程式 pod,路徑指定在值中。例如,spark.kubernetes.driver.volumes.persistentVolumeClaim.checkpointpvc.mount.path=/checkpoint 2.4.0
spark.kubernetes.driver.volumes.[VolumeType].[VolumeName].mount.subPath (無) 指定從 volume 掛載到驅動程式 pod 的 子路徑spark.kubernetes.driver.volumes.persistentVolumeClaim.checkpointpvc.mount.subPath=checkpoint 3.0.0
spark.kubernetes.driver.volumes.[VolumeType].[VolumeName].mount.readOnly (無) 指定掛載的 volume 是否為唯讀。例如,spark.kubernetes.driver.volumes.persistentVolumeClaim.checkpointpvc.mount.readOnly=false 2.4.0
spark.kubernetes.driver.volumes.[VolumeType].[VolumeName].options.[OptionName] (無) 設定傳遞至 Kubernetes 的 Kubernetes Volume 選項,OptionName 為鍵,具有指定值,必須符合 Kubernetes 選項格式。例如,spark.kubernetes.driver.volumes.persistentVolumeClaim.checkpointpvc.options.claimName=spark-pvc-claim 2.4.0
spark.kubernetes.executor.volumes.[VolumeType].[VolumeName].mount.path (無) VolumeType 類型的名為 VolumeNameKubernetes Volume 新增至執行器 pod,路徑指定在值中。例如,spark.kubernetes.executor.volumes.persistentVolumeClaim.checkpointpvc.mount.path=/checkpoint 2.4.0
spark.kubernetes.executor.volumes.[VolumeType].[VolumeName].mount.subPath (無) 指定從 volume 掛載到執行器 pod 的 子路徑spark.kubernetes.executor.volumes.persistentVolumeClaim.checkpointpvc.mount.subPath=checkpoint 3.0.0
spark.kubernetes.executor.volumes.[VolumeType].[VolumeName].mount.readOnly false 指定掛載的 volume 是否為唯讀。例如,spark.kubernetes.executor.volumes.persistentVolumeClaim.checkpointpvc.mount.readOnly=false 2.4.0
spark.kubernetes.executor.volumes.[VolumeType].[VolumeName].options.[OptionName] (無) 設定傳遞給 Kubernetes 的 Kubernetes Volume 選項,其中 `OptionName` 作為具有指定值的鍵。例如,`spark.kubernetes.executor.volumes.persistentVolumeClaim.checkpointpvc.options.claimName=spark-pvc-claim`。 2.4.0
spark.kubernetes.local.dirs.tmpfs false 設定用於備份 Spark 驅動程式和執行器 pod 中的 `SPARK_LOCAL_DIRS` 的 `emptyDir` 卷,以使用 `tmpfs` 備份,即 RAM。請參閱本頁稍早的 Local Storage 以進一步討論此問題。 3.0.0
spark.kubernetes.memoryOverheadFactor 0.1 這會設定記憶體開銷係數,將記憶體配置給非 JVM 記憶體,其中包括非堆積記憶體配置、非 JVM 任務、各種系統程序,以及當 `spark.kubernetes.local.dirs.tmpfs` 為 `true` 時的基於 `tmpfs` 的本地目錄。對於基於 JVM 的作業,此值預設為 0.10,而對於非 JVM 作業則為 0.40。這樣做是因為非 JVM 任務需要更多非 JVM 堆積空間,而此類任務通常會因「記憶體開銷超過」錯誤而失敗。這會以較高的預設值來預防此錯誤。這會被 `spark.driver.memoryOverheadFactor` 和 `spark.executor.memoryOverheadFactor` 明確設定的值覆寫。 2.4.0
spark.kubernetes.pyspark.pythonVersion "3" 這會設定用於執行驅動程式和執行器容器的 Docker 映像的主要 Python 版本。它只能是「3」。此設定已從 Spark 3.1.0 棄用,且實際上為無效操作。使用者應設定「spark.pyspark.python」和「spark.pyspark.driver.python」設定或「PYSPARK_PYTHON」和「PYSPARK_DRIVER_PYTHON」環境變數。 2.4.0
spark.kubernetes.kerberos.krb5.path (無) 指定要掛載在驅動程式和執行器上的 krb5.conf 檔案的本地位置,以進行 Kerberos 互動。請務必注意,定義的 KDC 必須在容器內可見。 3.0.0
spark.kubernetes.kerberos.krb5.configMapName (無) 指定包含 krb5.conf 檔案的 ConfigMap 的名稱,以掛載在驅動程式和執行器上,以進行 Kerberos 互動。定義的 KDC 必須在容器內可見。ConfigMap 也必須與驅動程式和執行器 pod 處於同一個命名空間。 3.0.0
spark.kubernetes.hadoop.configMapName (無) 指定包含 HADOOP_CONF_DIR 檔案的 ConfigMap 的名稱,以掛載在驅動程式和執行器上,以進行自訂 Hadoop 設定。 3.0.0
spark.kubernetes.kerberos.tokenSecret.name (無) 指定儲存現有委派權杖的機密的類型。這可讓作業使用者無需提供任何 Kerberos 憑證即可啟動作業。 3.0.0
spark.kubernetes.kerberos.tokenSecret.itemKey (無) 指定儲存現有委派權杖的資料的項目金鑰。這可讓工作使用者無需提供任何 Kerberos 認證即可啟動工作。 3.0.0
spark.kubernetes.driver.podTemplateFile (無) 指定包含驅動程式 pod 範本 的本機檔案。例如 spark.kubernetes.driver.podTemplateFile=/path/to/driver-pod-template.yaml 3.0.0
spark.kubernetes.driver.podTemplateContainerName (無) 指定要作為給定 pod 範本 中驅動程式的基礎的容器名稱。例如 spark.kubernetes.driver.podTemplateContainerName=spark-driver 3.0.0
spark.kubernetes.executor.podTemplateFile (無) 指定包含執行器 pod 範本 的本機檔案。例如 spark.kubernetes.executor.podTemplateFile=/path/to/executor-pod-template.yaml 3.0.0
spark.kubernetes.executor.podTemplateContainerName (無) 指定要作為給定 pod 範本 中執行器的基礎的容器名稱。例如 spark.kubernetes.executor.podTemplateContainerName=spark-executor 3.0.0
spark.kubernetes.executor.deleteOnTermination true 指定是否在發生失敗或正常終止時刪除執行器 pod。 3.0.0
spark.kubernetes.executor.checkAllContainers false 指定執行器 pod 是否應在判斷 pod 狀態時檢查所有容器(包括 sidecar),或僅檢查執行器容器。 3.1.0
spark.kubernetes.submission.connectionTimeout 10000 Kubernetes 執行個體在啟動驅動程式時使用的連線逾時(毫秒)。 3.0.0
spark.kubernetes.submission.requestTimeout 10000 Kubernetes 執行個體在啟動驅動程式時使用的要求逾時(毫秒)。 3.0.0
spark.kubernetes.trust.certificates false 如果設為 true,則客戶端只能使用權杖提交至 Kubernetes 群集。 3.2.0
spark.kubernetes.driver.connectionTimeout 10000 驅動程式中 Kubernetes 執行個體在要求執行器時使用的連線逾時(毫秒)。 3.0.0
spark.kubernetes.driver.requestTimeout 10000 驅動程式中 Kubernetes 執行個體在要求執行器時使用的要求逾時(毫秒)。 3.0.0
spark.kubernetes.appKillPodDeletionGracePeriod (無) 使用 spark-submit 刪除 Spark 應用程式時的寬限期(秒)。 3.0.0
spark.kubernetes.dynamicAllocation.deleteGracePeriod 5 秒 在強制終止之前,等待執行器正常關閉的時間長度。 3.0.0
spark.kubernetes.file.upload.path (無) 在群集模式下將檔案儲存在 spark 提交端的路徑。例如:spark.kubernetes.file.upload.path=s3a://<s3-bucket>/path 檔案應指定為 file://path/to/file 或絕對路徑。 3.0.0
spark.kubernetes.executor.decommissionLabel (無) 套用至正在退出或正被停用的 pod 的標籤。用於 pod 中斷預算、刪除成本和類似用途。 3.3.0
spark.kubernetes.executor.decommissionLabelValue (無) 當啟用 spark.kubernetes.executor.decommissionLabel 時,要與標籤一起套用的值。 3.3.0
spark.kubernetes.executor.scheduler.name (無) 指定每個 executor pod 的排程器名稱。 3.0.0
spark.kubernetes.driver.scheduler.name (無) 指定 driver pod 的排程器名稱。 3.3.0
spark.kubernetes.scheduler.name (無) 指定 driver 和 executor pod 的排程器名稱。如果設定 `spark.kubernetes.driver.scheduler.name` 或 `spark.kubernetes.executor.scheduler.name`,將會覆寫此設定。 3.3.0
spark.kubernetes.configMap.maxSize 1572864 config map 的最大大小限制。這可以根據 k8s 伺服器端的限制 進行設定。 3.1.0
spark.kubernetes.executor.missingPodDetectDelta 30s 當已註冊 executor 的 POD 從 Kubernetes API 伺服器的輪詢 POD 清單中遺失時,此 delta 時間會被視為註冊時間和輪詢時間之間可接受的時間差。超過此時間後,POD 會被視為從叢集中遺失,且 executor 將會被移除。 3.1.1
spark.kubernetes.decommission.script /opt/decom.sh 用於優雅除役的腳本位置。 3.2.0
spark.kubernetes.driver.service.deleteOnTermination true 如果為 true,driver 服務會在 Spark 應用程式終止時刪除。如果為 false,它會在 driver pod 刪除時清除。 3.2.0
spark.kubernetes.driver.service.ipFamilyPolicy SingleStack Driver 服務的 K8s IP 家族政策。有效值為 SingleStackPreferDualStackRequireDualStack 3.4.0
spark.kubernetes.driver.service.ipFamilies IPv4 K8s Driver 服務的 IP 家族清單。有效值為 IPv4IPv6 3.4.0
spark.kubernetes.driver.ownPersistentVolumeClaim true 如果為 true,driver pod 會成為隨選持久儲存空間宣告的擁有者,而不是 executor pod 3.2.0
spark.kubernetes.driver.reusePersistentVolumeClaim true 如果為 true,driver pod 會嘗試重複使用已刪除 executor pod 的 driver 擁有的隨選持久儲存空間宣告(如果存在)。這有助於透過略過持久儲存空間建立來減少 executor pod 建立延遲。請注意,根據定義,Terminating pod 狀態中的 pod 並非已刪除的 pod,且其資源(包括持久儲存空間宣告)仍無法重複使用。如果沒有可重複使用的宣告,Spark 會建立新的持久儲存空間宣告。換句話說,持久儲存空間宣告的總數有時可能會大於執行中 executor 的數量。此設定需要 spark.kubernetes.driver.ownPersistentVolumeClaim=true. 3.2.0
spark.kubernetes.driver.waitToReusePersistentVolumeClaim false 如果為 true,driver pod 會計算已建立的隨選持久儲存空間宣告數量,並在數量大於或等於 Spark 工作可以擁有的總量時等待。此設定需要 spark.kubernetes.driver.ownPersistentVolumeClaim=truespark.kubernetes.driver.reusePersistentVolumeClaim=true. 3.4.0
spark.kubernetes.executor.disableConfigMap false 如果為 true,停用 executor 的 ConfigMap 建立。 3.2.0
spark.kubernetes.driver.pod.featureSteps (無) 實作 `KubernetesFeatureConfigStep` 的額外 driver pod 功能步驟的類別名稱。這是一個開發人員 API。以逗號分隔。在所有 Spark 內部功能步驟之後執行。從 3.3.0 開始,您的 driver 功能步驟可以實作 `KubernetesDriverCustomFeatureConfigStep`,其中也可以使用 driver 設定。 3.2.0
spark.kubernetes.executor.pod.featureSteps (無) 實作 `KubernetesFeatureConfigStep` 的額外執行器 pod 功能步驟的類別名稱。這是開發人員 API。以逗號分隔。在所有 Spark 內部功能步驟之後執行。自 3.3.0 起,您的執行器功能步驟可以實作 `KubernetesExecutorCustomFeatureConfigStep`,其中執行器設定也可用。 3.2.0
spark.kubernetes.allocation.maxPendingPods Int.MaxValue 在此應用程式執行器配置期間允許的最大待處理 POD 數。Kubernetes 尚未知道這些新請求的執行器也計入此限制,因為它們會隨著時間變更為待處理 POD。此限制與資源設定檔無關,因為它會限制所有已使用資源設定檔的配置總和。 3.2.0
spark.kubernetes.allocation.pods.allocator direct 用於 pod 的配置器。可能的值為 direct(預設值)和 statefulset,或實作 `AbstractPodsAllocator` 類別的類別的完整類別名稱。未來版本可能會新增 Job 或 replicaset。這是開發人員 API,可能會隨時變更或移除。 3.3.0
spark.kubernetes.allocation.executor.timeout 600s 在一個新建立的執行器 POD 要求(尚未到達 POD 待處理狀態)被視為逾時並將被刪除之前等待的時間。 3.1.0
spark.kubernetes.allocation.driver.readinessTimeout 1s 在建立執行器 pod 之前等待驅動程式 pod 準備就緒的時間。此等待只會在應用程式啟動時發生。如果發生逾時,執行器 pod 仍會被建立。 3.1.3
spark.kubernetes.executor.enablePollingWithResourceVersion false 如果為 true,則在呼叫 pod 清單 API 時會將 `resourceVersion` 設定為 `0`,以允許 API 伺服器端快取。這應該小心使用。 3.3.0
spark.kubernetes.executor.eventProcessingInterval 1s 從 Kubernetes API 傳送的執行器事件連續檢查之間的間隔。 2.4.0
spark.kubernetes.executor.rollInterval 0s 執行器滾動作業之間的間隔。預設值為 `0s`,表示已停用。 3.3.0
spark.kubernetes.executor.minTasksPerExecutorBeforeRolling 0 滾動之前每個執行器的最小任務數。Spark 不會滾動總任務數小於此設定的執行器。預設值為零。 3.3.0
spark.kubernetes.executor.rollPolicy OUTLIER 執行器輪替政策:有效值包括 ID、ADD_TIME、TOTAL_GC_TIME、TOTAL_DURATION、FAILED_TASKS 和 OUTLIER(預設)。當執行器輪替發生時,Spark 會使用此政策選擇一個執行器並將其停用。內建政策基於執行器摘要,而新啟動的執行器會受到 spark.kubernetes.executor.minTasksPerExecutorBeforeRolling 保護。ID 政策會選擇執行器 ID 最小的執行器。ADD_TIME 政策會選擇新增時間最小的執行器。TOTAL_GC_TIME 政策會選擇總任務 GC 時間最長的執行器。TOTAL_DURATION 政策會選擇總任務時間最長的執行器。AVERAGE_DURATION 政策會選擇平均任務時間最長的執行器。FAILED_TASKS 政策會選擇失敗任務數最多的執行器。OUTLIER 政策會選擇統計資料異常的執行器,其異常值大於平均任務時間、總任務時間、總任務 GC 時間和失敗任務數(如果存在)的標準差至少兩倍。如果沒有異常值,則其運作方式類似於 TOTAL_DURATION 政策。 3.3.0

Pod 範本屬性

請參閱下表,以取得 Spark 會覆寫的 Pod 規格完整清單。

Pod 元資料

Pod 元資料金鑰修改後的數值說明
名稱 spark.kubernetes.driver.pod.name 的值 驅動程式 Pod 名稱會覆寫為 spark.kubernetes.driver.pod.name 的設定值或預設值。執行器 Pod 名稱不受影響。
命名空間 spark.kubernetes.namespace 的值 Spark 會對驅動程式和執行器命名空間做出強烈的假設。驅動程式和執行器命名空間都會取代為設定值或 Spark 設定值預設值。
標籤 加入來自 spark.kubernetes.{driver,executor}.label.* 的標籤 Spark 會加入 Spark 設定指定的其他標籤。
註解 加入來自 spark.kubernetes.{driver,executor}.annotation.* 的註解 Spark 會加入 Spark 設定指定的其他註解。

Pod 規格

Pod 規格金鑰修改後的數值說明
imagePullSecrets 加入來自 spark.kubernetes.container.image.pullSecrets 的影像提取密碼 會從 Spark 設定加入其他提取密碼到兩個執行器 Pod。
nodeSelector 加入來自 spark.kubernetes.node.selector.* 的節點選擇器 會從 Spark 設定加入其他節點選擇器到兩個執行器 Pod。
restartPolicy 「永不」 Spark 假設驅動程式和執行器永不重新啟動。
serviceAccount spark.kubernetes.authenticate.driver.serviceAccountName 的值 Spark 會使用 Spark 設定的值覆寫 serviceAccount,僅適用於驅動程式 Pod,且僅在指定 Spark 設定時。執行器 Pod 將保持不受影響。
serviceAccountName spark.kubernetes.authenticate.driver.serviceAccountName 的值 Spark 會使用 Spark 設定的值覆寫 serviceAccountName,僅適用於驅動程式 Pod,且僅在指定 Spark 設定時。執行器 Pod 將保持不受影響。
volumes spark.kubernetes.{driver,executor}.volumes.[VolumeType].[VolumeName].mount.path 新增磁碟區 Spark 會根據 Spark 設定新增磁碟區,以及傳遞 Spark 設定和 Pod 範本檔案所需的額外磁碟區。

容器規格

下列會影響驅動程式和執行器容器。Pod 規格中的所有其他容器將不受影響。

容器規格金鑰修改後的數值說明
env spark.kubernetes.driverEnv.[EnvironmentVariableName] 新增環境變數 Spark 會從 spark.kubernetes.driverEnv.[EnvironmentVariableName] 新增驅動程式環境變數,並從 spark.executorEnv.[EnvironmentVariableName] 新增執行器環境變數。
image spark.kubernetes.{driver,executor}.container.image 的值 映像會由 Spark 設定定義。
imagePullPolicy spark.kubernetes.container.image.pullPolicy 的值 Spark 會覆寫驅動程式和執行器的提取原則。
名稱 請參閱說明 如果 Pod 範本未定義,容器名稱將由 Spark 指定(驅動程式容器為「spark-kubernetes-driver」,每個執行器容器為「spark-kubernetes-executor」)。如果容器由範本定義,將使用範本的名稱。
resources 請參閱說明 CPU 限制由 spark.kubernetes.{driver,executor}.limit.cores 設定。CPU 由 spark.{driver,executor}.cores 設定。記憶體要求和限制由 spark.{driver,executor}.memoryspark.{driver,executor}.memoryOverhead 的值總和設定。其他資源限制由 spark.{driver,executor}.resources.{resourceName}.* 設定設定。
volumeMounts spark.kubernetes.driver.volumes.[VolumeType].[VolumeName].mount.{path,readOnly} 新增磁碟區 Spark 會根據 Spark 設定新增磁碟區,以及傳遞 Spark 設定和 Pod 範本檔案所需的額外磁碟區。

資源分配和組態概觀

請務必閱讀 設定頁面 上的「自訂資源排程和設定概觀」區段。本區段僅說明資源排程中與 Kubernetes 相關的特定面向。

使用者有責任適當設定 Kubernetes 群集,以提供可用資源,並理想地為每個容器隔離各項資源,讓資源不會在多個容器之間共用。如果資源未隔離,使用者有責任撰寫偵測腳本,讓資源不會在容器之間共用。請參閱 Kubernetes 文件,深入了解如何使用 自訂資源 設定 Kubernetes。

只要 Kubernetes 資源類型遵循 vendor-domain/resourcetype 的 Kubernetes 裝置外掛程式格式,Spark 便會自動處理將 Spark 組態 spark.{driver/executor}.resource.{resourceType} 轉換成 Kubernetes 組態。使用者必須使用 spark.{driver/executor}.resource.{resourceType}.vendor 組態指定廠商。如果您使用 Pod 範本,則不需要明確新增任何內容。您可以參閱 Kubernetes 文件,了解排程 GPU 的參考和範例。Spark 僅支援設定資源限制。

Kubernetes 沒有告知 Spark 分配給每個容器的資源位址。因此,使用者必須指定一個偵測腳本,讓執行器在啟動時執行,以偵測該執行器可用的資源。您可以在 examples/src/main/scripts/getGpusResources.sh 中找到範例腳本。腳本必須設定執行權限,而且使用者應設定權限以禁止惡意使用者修改它。腳本應以 ResourceInformation 類別的格式將 JSON 字串寫入 STDOUT。這包含資源名稱和僅供該執行器使用的資源位址陣列。

資源等級排程概觀

Spark 在 Kubernetes 上支援多項資源層級排程功能。

優先順序排程

Kubernetes 預設支援 Pod 優先順序

Spark on Kubernetes 允許透過 Pod 範本 定義工作優先順序。使用者可以在驅動程式或執行器 Pod 範本 spec 區段中指定 priorityClassName。以下是說明如何指定它的範例

apiVersion: v1
Kind: Pod
metadata:
  labels:
    template-label-key: driver-template-label-value
spec:
  # Specify the priority in here
  priorityClassName: system-node-critical
  containers:
  - name: test-driver-container
    image: will-be-overwritten

Kubernetes 上 Spark 的自訂 Kubernetes 排程器

Spark 允許使用者指定自訂 Kubernetes 排程器。

  1. 指定排程器名稱。

    使用者可以使用 spark.kubernetes.scheduler.namespark.kubernetes.{driver/executor}.scheduler.name 組態指定自訂排程器。

  2. 指定排程器相關組態。

    若要組態自訂排程器,使用者可以使用 Pod 範本、新增標籤 (spark.kubernetes.{driver,executor}.label.*)、註解 (spark.kubernetes.{driver/executor}.annotation.*) 或排程器特定組態 (例如 spark.kubernetes.scheduler.volcano.podGroupTemplateFile)。

  3. 指定排程器功能步驟。

    使用者也可以考慮使用 spark.kubernetes.{driver/executor}.pod.featureSteps 來支援更複雜的需求,包括但不限於

    • 為驅動程式/執行器排程建立其他 Kubernetes 自訂資源。
    • 根據設定或現有的 Pod 資訊動態設定排程器提示。

使用 Volcano 作為 Kubernetes 上 Spark 的自訂排程器

先決條件
建置

若要建立 Spark 散發版以及 Volcano 支援,例如 Spark 下載頁面 散發的版本,請參閱 “建立 Spark” 中的詳細資訊

./dev/make-distribution.sh --name custom-spark --pip --r --tgz -Psparkr -Phive -Phive-thriftserver -Pkubernetes -Pvolcano
用法

Spark on Kubernetes 允許使用 Volcano 作為自訂排程器。使用者可以使用 Volcano 支援更進階的資源排程:佇列排程、資源保留、優先順序排程等。

若要使用 Volcano 作為自訂排程器,使用者需要指定下列設定選項

# Specify volcano scheduler and PodGroup template
--conf spark.kubernetes.scheduler.name=volcano
--conf spark.kubernetes.scheduler.volcano.podGroupTemplateFile=/path/to/podgroup-template.yaml
# Specify driver/executor VolcanoFeatureStep
--conf spark.kubernetes.driver.pod.featureSteps=org.apache.spark.deploy.k8s.features.VolcanoFeatureStep
--conf spark.kubernetes.executor.pod.featureSteps=org.apache.spark.deploy.k8s.features.VolcanoFeatureStep
Volcano 功能步驟

Volcano 功能步驟可協助使用者建立 Volcano PodGroup,並設定驅動程式/執行器 Pod 註解以連結至這個 PodGroup

請注意,目前 Volcano 功能步驟僅支援驅動程式/作業等級的 PodGroup。

Volcano PodGroup 範本

Volcano 使用 CRD yaml 定義 PodGroup 規格。

Pod 範本 類似,Spark 使用者可以使用 Volcano PodGroup 範本來定義 PodGroup 規格設定。為此,請指定 Spark 屬性 spark.kubernetes.scheduler.volcano.podGroupTemplateFile,以指向 spark-submit 程序可以存取的檔案。以下是 PodGroup 範本的範例

apiVersion: scheduling.volcano.sh/v1beta1
kind: PodGroup
spec:
  # Specify minMember to 1 to make a driver pod
  minMember: 1
  # Specify minResources to support resource reservation (the driver pod resource and executors pod resource should be considered)
  # It is useful for ensource the available resources meet the minimum requirements of the Spark job and avoiding the
  # situation where drivers are scheduled, and then they are unable to schedule sufficient executors to progress.
  minResources:
    cpu: "2"
    memory: "3Gi"
  # Specify the priority, help users to specify job priority in the queue during scheduling.
  priorityClassName: system-node-critical
  # Specify the queue, indicates the resource queue which the job should be submitted to
  queue: default

使用 Apache YuniKorn 作為 Kubernetes 上 Spark 的自訂排程器

Apache YuniKorn 是一個 Kubernetes 資源排程器,提供進階的批次排程功能,例如作業排隊、資源公平性、最小/最大佇列容量和彈性的作業排序原則。有關可用的 Apache YuniKorn 功能,請參閱 核心功能

先決條件

安裝 Apache YuniKorn

helm repo add yunikorn https://apache.github.io/yunikorn-release
helm repo update
helm install yunikorn yunikorn/yunikorn --namespace yunikorn --version 1.3.0 --create-namespace --set embedAdmissionController=false

上述步驟會在現有的 Kubernetes 群集中安裝 YuniKorn v1.3.0。

開始使用

提交 Spark 作業,並附上下列額外選項

--conf spark.kubernetes.scheduler.name=yunikorn
--conf spark.kubernetes.driver.label.queue=root.default
--conf spark.kubernetes.executor.label.queue=root.default
--conf spark.kubernetes.driver.annotation.yunikorn.apache.org/app-id={{APP_ID}}
--conf spark.kubernetes.executor.annotation.yunikorn.apache.org/app-id={{APP_ID}}

請注意,{{APP_ID}} 是內建變數,會自動替換為 Spark 作業 ID。使用上述設定後,作業將由 YuniKorn 排程器排程,而非預設的 Kubernetes 排程器。

階段等級排程概觀

Kubernetes 支援階段層級排程