本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
使用 Pod 範本
從亞馬遜 EMR 版本 5.33.0 或 6.3.0 開始,EKS 上的亞馬遜 EMR 支持星火的網繭模板功能。網繭是一或多個容器的群組,其中包含共用儲存區和網路資源,以及如何執行容器的規格。網繭範本是決定如何執行每個網繭的規格。您可以使用 pod 範本檔案來定義 Spark 組態不支援的驅動程式或執行程式網繭組態。如需 Spark 的網繭範本功能的詳細資訊,請參閱網繭範本
注意
Pod 範本功能僅適用於驅動程式和執行程式 Pod。您無法使用網繭範本設定工作控制器網繭。
常用案例
您可以使用網繭範本搭配 EKS 上的 Amazon EMR,定義如何在共用 EKS 叢集上執行 Spark 任務,並節省成本並改善資源使用率和效能。
-
為了降低成本,您可以安排 Spark 驅動程式任務在 Amazon EC2 隨需執行個體上執行,同時排程 Spark 執行程式任務在 Amazon EC2 競價型執行個體上執行。
-
若要提高資源使用率,您可以支援多個團隊在同一個 EKS 叢集上執行其工作負載。每個團隊都會獲得一個指定的 Amazon EC2 節點群組,以便在其上執行工作負載。您可以使用網繭範本將對應的容許套用至其工作負載。
-
若要改善監控,您可以執行個別的記錄容器,將記錄檔轉寄至現有的監視應用程式。
例如,下列網繭範本檔案示範常見的使用案例。
apiVersion: v1 kind: Pod spec: volumes: - name: source-data-volume emptyDir: {} - name: metrics-files-volume emptyDir: {} nodeSelector: eks.amazonaws.com/nodegroup: emr-containers-nodegroup containers: - name: spark-kubernetes-driver # This will be interpreted as driver Spark main container env: - name: RANDOM value: "random" volumeMounts: - name: shared-volume mountPath: /var/data - name: metrics-files-volume mountPath: /var/metrics/data - name: custom-side-car-container # Sidecar container image: <side_car_container_image> env: - name: RANDOM_SIDECAR value: random volumeMounts: - name: metrics-files-volume mountPath: /var/metrics/data command: - /bin/sh - '-c' - <command-to-upload-metrics-files> initContainers: - name: spark-init-container-driver # Init container image: <spark-pre-step-image> volumeMounts: - name: source-data-volume # Use EMR predefined volumes mountPath: /var/data command: - /bin/sh - '-c' - <command-to-download-dependency-jars>
Pod 範本完成下列任務:
-
添加 Spark 主容器啟動之前執行的新初
始化容器。初始化容器共享 source-data-volume
與 Spark 主容器調用的EmptyDir卷。您可以讓 init 容器執行初始化步驟,例如下載相依性或產生輸入資料。然後星火主容器消耗數據。 -
添加與 Spark 主容器一起執行的另一個側車
容器。這兩個容器正在共用另一個稱為的 EmptyDir
磁碟區metrics-files-volume
。您的 Spark 工作可以產生指標,例如 Prometheus 指標。然後,Spark 作業可以將指標放入文件中,並讓附屬容器將文件上傳到您自己的 BI 系統,以備將 future 分析。 -
新增環境變數至 Spark 主容器。你可以讓你的工作消耗環境變量。
-
定義節點選取器
,以便僅在 emr-containers-nodegroup
節點群組上排程網繭。這有助於隔離工作和團隊的運算資源。
使用 Amazon EMR on EKS 的 Pod 範本
若要在 EKS 上透過 Amazon EMR 啟用網繭範本功能,請設定 Spark 屬性,spark.kubernetes.driver.podTemplateFile
並指spark.kubernetes.executor.podTemplateFile
向 Amazon S3 中的網繭範本檔案。Spark 然後下載 pod 範本檔案,並使用它來建構驅動程式和執行程式 Pod。
注意
Spark 使用工作執行角色來載入網繭範本,因此任務執行角色必須具有存取 Amazon S3 的權限,才能載入網繭範本。如需詳細資訊,請參閱建立任務執行角色。
您可以使用指SparkSubmitParameters
定網繭範本的 Amazon S3 路徑,如下列任務執行 JSON 檔案所示。
{ "name": "myjob", "virtualClusterId": "123456", "executionRoleArn": "iam_role_name_for_job_execution", "releaseLabel": "
release_label
", "jobDriver": { "sparkSubmitJobDriver": { "entryPoint": "entryPoint_location", "entryPointArguments": ["argument1
", "argument2
", ...], "sparkSubmitParameters": "--class <main_class> \ --conf spark.kubernetes.driver.podTemplateFile=s3://path_to_driver_pod_template
\ --conf spark.kubernetes.executor.podTemplateFile=s3://path_to_executor_pod_template
\ --conf spark.executor.instances=2 \ --conf spark.executor.memory=2G \ --conf spark.executor.cores=2 \ --conf spark.driver.cores=1" } } }
或者,您可以使用指configurationOverrides
定網繭範本的 Amazon S3 路徑,如下列任務執行 JSON 檔案所示。
{ "name": "myjob", "virtualClusterId": "123456", "executionRoleArn": "iam_role_name_for_job_execution", "releaseLabel": "
release_label
", "jobDriver": { "sparkSubmitJobDriver": { "entryPoint": "entryPoint_location", "entryPointArguments": ["argument1
", "argument2
", ...], "sparkSubmitParameters": "--class <main_class> \ --conf spark.executor.instances=2 \ --conf spark.executor.memory=2G \ --conf spark.executor.cores=2 \ --conf spark.driver.cores=1" } }, "configurationOverrides": { "applicationConfiguration": [ { "classification": "spark-defaults", "properties": { "spark.driver.memory":"2G", "spark.kubernetes.driver.podTemplateFile":"s3://path_to_driver_pod_template
", "spark.kubernetes.executor.podTemplateFile":"s3://path_to_executor_pod_template
" } } ] } }
注意
-
在 EKS 上的 Amazon EMR 搭配使用網繭範本功能時,您需要遵循安全準則,例如隔離不受信任的應用程式程式碼。如需詳細資訊,請參閱安全最佳實務。
-
您無法使用 and 來變更 Spark 主容器名稱
spark.kubernetes.driver.podTemplateContainerName
spark.kubernetes.executor.podTemplateContainerName
,因為這些名稱是硬式編碼為spark-kubernetes-driver
和spark-kubernetes-executors
。如果您想要自訂 Spark 主容器,則必須使用這些硬式編碼名稱在網繭範本中指定容器。
Pod 範本欄位
在 EKS 上使用 Amazon EMR 設定網繭範本時,請考慮下列欄位限制。
-
EKS 上的 Amazon EMR 僅允許網繭範本中的下列欄位啟用適當的任務排程。
這些是允許的網繭層級欄位:
-
apiVersion
-
kind
-
metadata
-
spec.activeDeadlineSeconds
-
spec.affinity
-
spec.containers
-
spec.enableServiceLinks
-
spec.ephemeralContainers
-
spec.hostAliases
-
spec.hostname
-
spec.imagePullSecrets
-
spec.initContainers
-
spec.nodeName
-
spec.nodeSelector
-
spec.overhead
-
spec.preemptionPolicy
-
spec.priority
-
spec.priorityClassName
-
spec.readinessGates
-
spec.runtimeClassName
-
spec.schedulerName
-
spec.subdomain
-
spec.terminationGracePeriodSeconds
-
spec.tolerations
-
spec.topologySpreadConstraints
-
spec.volumes
這些是允許的 Spark 主容器級別字段:
-
env
-
envFrom
-
name
-
lifecycle
-
livenessProbe
-
readinessProbe
-
resources
-
startupProbe
-
stdin
-
stdinOnce
-
terminationMessagePath
-
terminationMessagePolicy
-
tty
-
volumeDevices
-
volumeMounts
-
workingDir
當您在網繭範本中使用任何不允許的欄位時,Spark 會擲回例外狀況,且工作失敗。下列範例會顯示 Spark 控制器記錄檔中的錯誤訊息,因為不允許的欄位。
Executor pod template validation failed. Field container.command in Spark main container not allowed but specified.
-
-
EKS 上的 Amazon EMR 會在網繭範本中預先定義下列參數。您在網繭範本中指定的欄位不得與這些欄位重疊。
以下是預先定義的磁碟區名稱:
-
emr-container-communicate
-
config-volume
-
emr-container-application-log-dir
-
emr-container-event-log-dir
-
temp-data-dir
-
mnt-dir
-
home-dir
-
emr-container-s3
以下是僅適用於 Spark 主容器的預先定義磁碟區裝載:
-
名稱:
emr-container-communicate
; MountPath:/var/log/fluentd
-
名稱:
emr-container-application-log-dir
; MountPath:/var/log/spark/user
-
名稱:
emr-container-event-log-dir
; MountPath:/var/log/spark/apps
-
名稱:
mnt-dir
; MountPath:/mnt
-
名稱:
temp-data-dir
; MountPath:/tmp
-
名稱:
home-dir
; MountPath:/home/hadoop
這些是僅適用於 Spark 主容器的預定義環境變量:
-
SPARK_CONTAINER_ID
-
K8S_SPARK_LOG_URL_STDERR
-
K8S_SPARK_LOG_URL_STDOUT
-
SIDECAR_SIGNAL_FILE
注意
您仍然可以使用這些預先定義的磁碟區,並將它們掛載到額外的附屬容器中。例如,您可以使用
emr-container-application-log-dir
並將其掛接到網繭範本中定義的自己的附屬容器。如果您指定的欄位與網繭範本中的任何預先定義欄位衝突,Spark 會擲回例外狀況,而工作會失敗。下列範例會顯示 Spark 應用程式記錄檔中的錯誤訊息,因為與預先定義的欄位衝突。
Defined volume mount path on main container must not overlap with reserved mount paths: [<reserved-paths>]
-
邊車容器考量
亞馬遜 EMR 控制由亞馬遜 EMR 在 EKS 上佈建的網繭的生命週期。邊車容器應遵循 Spark 主容器的生命週期相同。如果您在網繭中插入額外的附屬容器,建議您與 Amazon EMR 定義的網繭生命週期管理整合,以便 Spark 主容器結束時,並行容器可以自行停止。
為了降低成本,我們建議您實施一個過程,以防止帶有並行容器的驅動程序 Pod 在任務完成後繼續運行。Spark 驅動程序刪除執行程序吊艙時執行程序完成。但是,當驅動程序完成時,額外的附加的附加容器將繼續運行。網繭會計費,直到 EKS 上的 Amazon EMR 清理驅動程式網繭為止,通常在驅動程式 Spark 主容器完成後不到一分鐘。為了降低成本,您可以將其他附加的附屬容器與 Amazon EMR on EKS 為驅動程式和執行程式網繭定義的生命週期管理機制整合,如下節所述。
Spark 驅動程序和執行程序莢中的主容器/var/log/fluentd/main-container-terminated
每兩秒發送heartbeat
一次文件。透過將 Amazon EMR 預先定義的emr-container-communicate
磁碟區掛載新增至附屬容器,您可以定義附屬容器的子流程,以定期追蹤此檔案的上次修改時間。然後,如果它發現 Spark 主容器停止更長的持續時間,子進程會自行停止。heartbeat
下列範例會示範追蹤活動訊號檔案並自行停止的子程序。將您的 _volume_mount
取代為掛接預先定義磁碟區的路徑。該腳本被捆綁由邊車容器使用的圖像內。在網繭範本檔案中,您可以使用下列命令sub_process_script.sh
和指定附屬容器main_command
。
MOUNT_PATH="
your_volume_mount
" FILE_TO_WATCH="$MOUNT_PATH/main-container-terminated" INITIAL_HEARTBEAT_TIMEOUT_THRESHOLD=60 HEARTBEAT_TIMEOUT_THRESHOLD=15 SLEEP_DURATION=10 function terminate_main_process() { # Stop main process } # Waiting for the first heartbeat sent by Spark main container echo "Waiting for file $FILE_TO_WATCH to appear..." start_wait=$(date +%s) while ! [[ -f "$FILE_TO_WATCH" ]]; do elapsed_wait=$(expr $(date +%s) - $start_wait) if [ "$elapsed_wait" -gt "$INITIAL_HEARTBEAT_TIMEOUT_THRESHOLD" ]; then echo "File $FILE_TO_WATCH not found after $INITIAL_HEARTBEAT_TIMEOUT_THRESHOLD seconds; aborting" terminate_main_process exit 1 fi sleep $SLEEP_DURATION; done; echo "Found file $FILE_TO_WATCH; watching for heartbeats..." while [[ -f "$FILE_TO_WATCH" ]]; do LAST_HEARTBEAT=$(stat -c %Y $FILE_TO_WATCH) ELAPSED_TIME_SINCE_AFTER_HEARTBEAT=$(expr $(date +%s) - $LAST_HEARTBEAT) if [ "$ELAPSED_TIME_SINCE_AFTER_HEARTBEAT" -gt "$HEARTBEAT_TIMEOUT_THRESHOLD" ]; then echo "Last heartbeat to file $FILE_TO_WATCH was more than $HEARTBEAT_TIMEOUT_THRESHOLD seconds ago at $LAST_HEARTBEAT; terminating" terminate_main_process exit 0 fi sleep $SLEEP_DURATION; done; echo "Outside of loop, main-container-terminated file no longer exists" # The file will be deleted once the fluentd container is terminated echo "The file $FILE_TO_WATCH doesn't exist any more;" terminate_main_process exit 0