

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

# spark-submit과 관련된 서비스 계정에 대한 IAM 역할(IRSA) 설정
<a name="spark-submit-security-irsa"></a>

다음 섹션에서는 서비스 계정에 대한 IAM 역할(IRSA)을 설정하여 Amazon S3에 저장된 Spark 애플리케이션을 실행할 수 있도록 Kubernetes 서비스 계정을 인증하고 권한을 부여하하는 방법을 설명합니다.

## 사전 조건
<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)하고 Spark 애플리케이션 jar을 [업로드](https://docs.aws.amazon.com/AmazonS3/latest/userguide/uploading-an-object-bucket.html)함

## IAM 역할을 수임하도록 Kubernetes 서비스 계정 구성
<a name="spark-submit-security-irsa-configure-kubernetes"></a>

다음 단계에서는 AWS Identity and Access Management (IAM) 역할을 수임하도록 Kubernetes 서비스 계정을 구성하는 방법을 다룹니다. 서비스 계정을 사용하도록 포드를 구성한 후 해당 포드는 역할에 액세스 권한이 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 이상에서는 Amazon EKS 클러스터에서 Spark 애플리케이션을 실행하기 위해 spark-submit을 지원합니다. 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
```