

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 使用 spark-submit 執行 Spark 作業
<a name="spark-submit"></a>

Amazon EMR 6.10.0 版及更高版本支援 `spark-submit` 作為命令列工具，可以使用它向 Amazon EMR on EKS 叢集提交 Spark 應用程式並執行。

**注意**  
Amazon EMR 會根據 vCPU 和記憶體使用量計算 Amazon EKS 定價。此計算適用於驅動程式和執行器 Pod。此計算從您下載 Amazon EMR 應用程式映像時開始，直到 Amazon EKS Pod 終止且四捨五入至最接近的秒數。

**Topics**
+ [為 Amazon EMR on EKS 設定 spark-submit](spark-submit-setup.md)
+ [開始針對 Amazon EMR on EKS 使用 spark-submit](spark-submit-gs.md)
+ [驗證 spark-submit 的 Spark 驅動程式服務帳戶安全需求](spark-submit-security.md)

# 為 Amazon EMR on EKS 設定 spark-submit
<a name="spark-submit-setup"></a>

完成下列任務進行設定，然後才能在 Amazon EMR on EKS 上使用 spark-submit 執行應用程式。如果已經註冊 Amazon Web Services (AWS) 且已在使用 Amazon EKS，則您幾乎可使用 Amazon EMR on EKS。如果已經完成任何先決條件，則可以跳過這些先決條件，然後繼續進行下一個。
+ **[安裝或更新至最新版本的 AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)**- 如果您已安裝 AWS CLI，請確認您擁有最新版本。
+ **[設定 kubectl 和 eksctl](https://docs.aws.amazon.com/eks/latest/userguide/install-kubectl.html) ** – eksctl 是您用來與 Amazon EKS 通訊的命令列工具。
+ **[開始使用 Amazon EKS – eksctl](https://docs.aws.amazon.com/eks/latest/userguide/getting-started-eksctl.html) ** – 請依照步驟在 Amazon EKS 中建立具有節點的新 Kubernetes 叢集。
+ **[選擇 Amazon EMR 基礎映像 URI](docker-custom-images-tag.md) (6.10.0 版或更高版本)** - Amazon EMR 6.10.0 版及更高版本支援 `spark-submit` 命令。
+ 確認驅動程式服務帳戶具有建立和監控執行程式 Pod 的適當許可。如需詳細資訊，請參閱[驗證 spark-submit 的 Spark 驅動程式服務帳戶安全需求](spark-submit-security.md)。
+ 設定本機 [AWS 憑證設定檔](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html)。
+ 從 Amazon EKS 主控台中，選擇您的 EKS 叢集，然後尋找位於**概觀**、**詳細資訊**，以及 **API 伺服器端點下的 EKS 叢集端點**。

# 開始針對 Amazon EMR on EKS 使用 spark-submit
<a name="spark-submit-gs"></a>

Amazon EMR 6.10.0 及更高版本支援 spark-submit，可在 Amazon EKS 叢集上執行 Spark 應用程式。以下章節說明如何提交 Spark 應用程式的命令。

## 執行 Spark 應用程式
<a name="spark-submit-run"></a>

完成以下步驟，以執行 Spark 應用程式：

1. 在使用 `spark-submit` 命令執行 Spark 應用程式之前，請先完成 [為 Amazon EMR on EKS 設定 spark-submit](spark-submit-setup.md) 中的步驟。

1. 使用 Amazon EMR on EKS 基礎映像執行容器。如需詳細資訊[，請參閱如何選取基礎映像 URI](https://docs.aws.amazon.com/emr/latest/EMR-on-EKS-DevelopmentGuide/docker-custom-images-tag.html)。

   ```
   kubectl run -it containerName --image=EMRonEKSImage --command -n namespace /bin/bash
   ```

1. 設定以下環境變數的值：

   ```
   export SPARK_HOME=spark-home
   export MASTER_URL=k8s://Amazon EKS-cluster-endpoint
   ```

1. 現在，使用下列命令提交 Spark 應用程式：

   ```
   $SPARK_HOME/bin/spark-submit \
    --class org.apache.spark.examples.SparkPi \
    --master $MASTER_URL \
    --conf spark.kubernetes.container.image=895885662937.dkr.ecr.us-west-2.amazonaws.com/spark/emr-6.10.0:latest \
    --conf spark.kubernetes.authenticate.driver.serviceAccountName=spark \
    --deploy-mode cluster \
    --conf spark.kubernetes.namespace=spark-operator \
    local:///usr/lib/spark/examples/jars/spark-examples.jar 20
   ```

如需有關將應用程式提交到 Spark 的詳細資訊，請參閱 Apache Spark 文件中的[提交應用程式](https://spark.apache.org/docs/latest/submitting-applications.html)。

**重要**  
`spark-submit` 僅支援叢集模式作為提交機制。

# 驗證 spark-submit 的 Spark 驅動程式服務帳戶安全需求
<a name="spark-submit-security"></a>

Spark 驅動程式 Pod 使用 Kubernetes 服務帳戶來存取 Kubernetes API 伺服器，以建立和監控執行程式 Pod。驅動程式服務帳戶必須具有適當的許可，才能列出、建立、編輯、修補及刪除叢集中的 Pod。透過執行以下命令，可確認您可列出這些資源：

```
kubectl auth can-i list|create|edit|delete|patch pods
```

執行每個命令，確認您具有必要的許可。

```
kubectl auth can-i list pods
kubectl auth can-i create pods
kubectl auth can-i edit pods
kubectl auth can-i delete pods
kubectl auth can-i patch pods
```

下列規則適用於此服務角色：

```
 rules:
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - "*"
- apiGroups:
  - ""
  resources:
  - services
  verbs:
  - "*"
- apiGroups:
  - ""
  resources:
  - configmaps
  verbs:
  - "*"
- apiGroups:
  - ""
  resources:
  - persistentvolumeclaims
  verbs:
  - "*"
```

# 為 spark-submit 設定服務帳戶 (IRSA) 的 IAM 角色
<a name="spark-submit-security-irsa"></a>

下列各節說明如何為服務帳戶 (IRSA) 設定 IAM 角色來驗證和授權 Kubernetes 服務帳戶，以便您可以執行存放在 Amazon S3 中的 Spark 應用程式。

## 先決條件
<a name="spark-submit-security-irsa-prereqs"></a>

在嘗試本文件中的任何範例之前，請確定您已完成下列先決條件：
+ [已完成設定 spark-submit](https://docs.aws.amazon.com/emr/latest/EMR-on-EKS-DevelopmentGuide/spark-submit-setup.html)
+ [建立 S3 儲存貯](https://docs.aws.amazon.com/AmazonS3/latest/userguide/creating-bucket.html)體並[上傳](https://docs.aws.amazon.com/AmazonS3/latest/userguide/uploading-an-object-bucket.html) Spark 應用程式 jar

## 設定 Kubernetes 服務帳戶以擔任 IAM 角色
<a name="spark-submit-security-irsa-configure-kubernetes"></a>

下列步驟說明如何設定 Kubernetes 服務帳戶以擔任 AWS Identity and Access Management (IAM) 角色。將 Pod 設定為使用服務帳戶後，他們可以存取 AWS 服務 角色有權存取的任何 。

1. 建立政策檔案以允許唯讀存取您[上傳](https://docs.aws.amazon.com/AmazonS3/latest/userguide/uploading-an-object-bucket.html)的 Amazon S3 物件：

   ```
   cat >my-policy.json <<EOF
   {
       "Version": "2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Action": [
                   "s3:GetObject",
                   "s3:ListBucket"
               ],
               "Resource": [
                   "arn:aws:s3:::<my-spark-jar-bucket>",
                   "arn:aws:s3:::<my-spark-jar-bucket>/*"
               ]
           }
       ]
   }
   EOF
   ```

1. 建立 IAM 政策。

   ```
   aws iam create-policy --policy-name my-policy --policy-document file://my-policy.json
   ```

1. 建立 IAM 角色，並將其與 Spark 驅動程式的 Kubernetes 服務帳戶建立關聯

   ```
   eksctl create iamserviceaccount --name my-spark-driver-sa --namespace spark-operator \
   --cluster my-cluster --role-name "my-role" \
   --attach-policy-arn arn:aws:iam::111122223333:policy/my-policy --approve
   ```

1. 建立具有 Spark 驅動程式服務帳戶所需[許可](https://docs.aws.amazon.com/emr/latest/EMR-on-EKS-DevelopmentGuide/spark-submit-security.html)的 YAML 檔案：

   ```
   cat >spark-rbac.yaml <<EOF
   apiVersion: rbac.authorization.k8s.io/v1
   kind: Role
   metadata:
     namespace: default
     name: emr-containers-role-spark
   rules:
   - apiGroups:
     - ""
     resources:
     - pods
     verbs:
     - "*"
   - apiGroups:
     - ""
     resources:
     - services
     verbs:
     - "*"
   - apiGroups:
     - ""
     resources:
     - configmaps
     verbs:
     - "*"
   - apiGroups:
     - ""
     resources:
     - persistentvolumeclaims
     verbs:
     - "*"
   ---
   apiVersion: rbac.authorization.k8s.io/v1
   kind: RoleBinding
   metadata:
     name: spark-role-binding
     namespace: default
   roleRef:
     apiGroup: rbac.authorization.k8s.io
     kind: Role
     name: emr-containers-role-spark
   subjects:
   - kind: ServiceAccount
     name: emr-containers-sa-spark
     namespace: default
   EOF
   ```

1. 套用叢集角色繫結組態。

   ```
   kubectl apply -f spark-rbac.yaml
   ```

1. `kubectl` 命令應該會傳回已建立帳戶的確認。

   ```
   serviceaccount/emr-containers-sa-spark created
   clusterrolebinding.rbac.authorization.k8s.io/emr-containers-role-spark configured
   ```

## 執行 Spark 應用程式
<a name="spark-submit-security-irsa-app-run"></a>

Amazon EMR 6.10.0 及更高版本支援 spark-submit，可在 Amazon EKS 叢集上執行 Spark 應用程式。完成以下步驟，以執行 Spark 應用程式：

1. 請確定您已完成[設定 Amazon EMR on EKS 的 spark-submit ](https://docs.aws.amazon.com/emr/latest/EMR-on-EKS-DevelopmentGuide/spark-submit-setup.html)中的步驟。

1. 設定以下環境變數的值：

   ```
   export SPARK_HOME=spark-home
   export MASTER_URL=k8s://Amazon EKS-cluster-endpoint
   ```

1. 現在，使用下列命令提交 Spark 應用程式：

   ```
   $SPARK_HOME/bin/spark-submit \
    --class org.apache.spark.examples.SparkPi \
    --master $MASTER_URL \
    --conf spark.kubernetes.container.image=895885662937.dkr.ecr.us-west-2.amazonaws.com/spark/emr-6.15.0:latest \
    --conf spark.kubernetes.authenticate.driver.serviceAccountName=emr-containers-sa-spark \
    --deploy-mode cluster \
    --conf spark.kubernetes.namespace=default \
    --conf "spark.driver.extraClassPath=/usr/lib/hadoop-lzo/lib/*:/usr/lib/hadoop/hadoop-aws.jar:/usr/share/aws/aws-java-sdk/*:/usr/share/aws/emr/emrfs/conf:/usr/share/aws/emr/emrfs/lib/*:/usr/share/aws/emr/emrfs/auxlib/*:/usr/share/aws/emr/security/conf:/usr/share/aws/emr/security/lib/*:/usr/share/aws/hmclient/lib/aws-glue-datacatalog-spark-client.jar:/usr/share/java/Hive-JSON-Serde/hive-openx-serde.jar:/usr/share/aws/sagemaker-spark-sdk/lib/sagemaker-spark-sdk.jar:/home/hadoop/extrajars/*" \
    --conf "spark.driver.extraLibraryPath=/usr/lib/hadoop/lib/native:/usr/lib/hadoop-lzo/lib/native:/docker/usr/lib/hadoop/lib/native:/docker/usr/lib/hadoop-lzo/lib/native" \
    --conf "spark.executor.extraClassPath=/usr/lib/hadoop-lzo/lib/*:/usr/lib/hadoop/hadoop-aws.jar:/usr/share/aws/aws-java-sdk/*:/usr/share/aws/emr/emrfs/conf:/usr/share/aws/emr/emrfs/lib/*:/usr/share/aws/emr/emrfs/auxlib/*:/usr/share/aws/emr/security/conf:/usr/share/aws/emr/security/lib/*:/usr/share/aws/hmclient/lib/aws-glue-datacatalog-spark-client.jar:/usr/share/java/Hive-JSON-Serde/hive-openx-serde.jar:/usr/share/aws/sagemaker-spark-sdk/lib/sagemaker-spark-sdk.jar:/home/hadoop/extrajars/*" \
    --conf "spark.executor.extraLibraryPath=/usr/lib/hadoop/lib/native:/usr/lib/hadoop-lzo/lib/native:/docker/usr/lib/hadoop/lib/native:/docker/usr/lib/hadoop-lzo/lib/native" \
    --conf spark.hadoop.fs.s3.customAWSCredentialsProvider=com.amazonaws.auth.WebIdentityTokenCredentialsProvider \
    --conf spark.hadoop.fs.s3.impl=com.amazon.ws.emr.hadoop.fs.EmrFileSystem \
    --conf spark.hadoop.fs.AbstractFileSystem.s3.impl=org.apache.hadoop.fs.s3.EMRFSDelegate \
    --conf spark.hadoop.fs.s3.buffer.dir=/mnt/s3 \
    --conf spark.hadoop.fs.s3.getObject.initialSocketTimeoutMilliseconds="2000" \
    --conf spark.hadoop.mapreduce.fileoutputcommitter.algorithm.version.emr_internal_use_only.EmrFileSystem="2" \
    --conf spark.hadoop.mapreduce.fileoutputcommitter.cleanup-failures.ignored.emr_internal_use_only.EmrFileSystem="true" \
    s3://my-pod-bucket/spark-examples.jar 20
   ```

1. 在 Spark 驅動程式完成 Spark 任務後，您應該會在提交結束時看到日誌行，指出 Spark 任務已完成。

   ```
   23/11/24 17:02:14 INFO LoggingPodStatusWatcherImpl: Application org.apache.spark.examples.SparkPi with submission ID default:org-apache-spark-examples-sparkpi-4980808c03ff3115-driver finished
   23/11/24 17:02:14 INFO ShutdownHookManager: Shutdown hook called
   ```

## 清除
<a name="spark-submit-security-irsa-cleanup"></a>

執行應用程式完成後，您可以使用下列命令執行清除。

```
kubectl delete -f spark-rbac.yaml
```