

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

# 서비스 계정에 대한 IAM 역할(IRSA)을 사용하여 클러스터 액세스 권한 설정
<a name="spark-operator-security-irsa"></a>

이 섹션에서는 예를 사용하여 AWS Identity and Access Management 역할을 수임하도록 Kubernetes 서비스 계정을 구성하는 방법을 보여줍니다. 그런 다음 서비스 계정을 사용하는 포드는 역할에 액세스 권한이 있는 모든 AWS 서비스에 액세스할 수 있습니다.

다음 예제에서는 Spark 애플리케이션을 실행하여 Amazon S3에 있는 파일의 단어 수를 계산합니다. 이를 위해 서비스 계정에 대한 IAM 역할(IRSA)을 설정하여 Kubernetes 서비스 계정을 인증하고 권한을 부여할 수 있습니다.

**참고**  
이 예제에서는 Spark 운영자의 'spark-operator' 네임스페이스와 Spark 애플리케이션을 제출하는 네임스페이스를 사용합니다.

## 사전 조건
<a name="spark-operator-security-irsa-prereqs"></a>

이 페이지의 예제를 사용하기 전에 다음 필수 조건을 완료합니다.
+ [Spark 운영자를 설정합니다]().
+ [Spark 운영자 설치](spark-operator-gs.md#spark-operator-install).
+ [Amazon S3 버킷을 생성](https://docs.aws.amazon.com/AmazonS3/latest/userguide/creating-bucket.html)합니다.
+ 좋아하는 시를 `poem.txt` 텍스트 파일에 저장하고 파일을 S3 버킷에 업로드합니다. 이 페이지에서 생성한 Spark 애플리케이션이 텍스트 파일의 내용을 읽습니다. S3에 파일을 업로드하는 방법에 대한 자세한 내용은 *Amazon Simple Storage Service 사용 설명서*에서 [버킷에 객체 업로드](https://docs.aws.amazon.com/AmazonS3/latest/userguide/uploading-an-object-bucket.html)를 참조하세요.

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

다음 단계를 사용하여 포드가 액세스 권한이 있는 서비스에 액세스하는 데 사용할 수 있는 IAM 역할을 수임하도록 Kubernetes AWS 서비스 계정을 구성합니다.

1. 를 완료한 후 [사전 조건](#spark-operator-security-irsa-prereqs) AWS Command Line Interface 를 사용하여 Amazon S3에 업로드한 `example-policy.json` 파일에 대한 읽기 전용 액세스를 허용하는 파일을 생성합니다.

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

1. IAM 정책 `example-policy`를 생성합니다.

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

1. 다음으로 IAM 역할 `example-role`을 생성하고 이를 Spark 드라이버의 Kubernetes 서비스 계정과 연결합니다.

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

1. Spark 드라이버 서비스 계정에 필요한 클러스터 역할 바인딩이 포함된 yaml 파일을 생성합니다.

   ```
   cat >spark-rbac.yaml <<EOF
   apiVersion: v1
   kind: ServiceAccount
   metadata:
     name: driver-account-sa
   ---
   apiVersion: rbac.authorization.k8s.io/v1
   kind: ClusterRoleBinding
   metadata:
     name: spark-role
   roleRef:
     apiGroup: rbac.authorization.k8s.io
     kind: ClusterRole
     name: edit
   subjects:
     - kind: ServiceAccount
       name: driver-account-sa
       namespace: spark-operator
   EOF
   ```

1. 클러스터 역할 바인딩 구성을 적용합니다.

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

kubectl 명령은 성공적인 계정 생성을 확인합니다.

```
serviceaccount/driver-account-sa created
clusterrolebinding.rbac.authorization.k8s.io/spark-role configured
```

## Spark 운영자에서 애플리케이션 실행
<a name="spark-operator-security-irsa-run"></a>

[Kubernetes 서비스 계정 구성]() 후 [사전 조건](#spark-operator-security-irsa-prereqs)의 일부로 업로드한 텍스트 파일의 단어 수를 계산하는 Spark 애플리케이션을 실행할 수 있습니다.

1. Amazon EMR 버전 6을 기반으로 단어 수 계산 애플리케이션을 위한 `SparkApplication` 정의를 사용하여 새 파일 `word-count.yaml`을 만듭니다.

   ```
   cat >word-count.yaml <<EOF
   apiVersion: "sparkoperator.k8s.io/v1beta2"
   kind: SparkApplication
   metadata:
     name: word-count
     namespace: spark-operator
   spec:
     type: Java
     mode: cluster
     image: "895885662937.dkr.ecr.us-west-2.amazonaws.com/spark/emr-6.10.0:latest"
     imagePullPolicy: Always
     mainClass: org.apache.spark.examples.JavaWordCount
     mainApplicationFile: local:///usr/lib/spark/examples/jars/spark-examples.jar
     arguments:
       - s3://my-pod-bucket/poem.txt
     hadoopConf:
      # EMRFS filesystem
       fs.s3.customAWSCredentialsProvider: com.amazonaws.auth.WebIdentityTokenCredentialsProvider
       fs.s3.impl: com.amazon.ws.emr.hadoop.fs.EmrFileSystem
       fs.AbstractFileSystem.s3.impl: org.apache.hadoop.fs.s3.EMRFSDelegate
       fs.s3.buffer.dir: /mnt/s3
       fs.s3.getObject.initialSocketTimeoutMilliseconds: "2000"
       mapreduce.fileoutputcommitter.algorithm.version.emr_internal_use_only.EmrFileSystem: "2"
       mapreduce.fileoutputcommitter.cleanup-failures.ignored.emr_internal_use_only.EmrFileSystem: "true"
     sparkConf:
       # Required for EMR Runtime
       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/*
       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
       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/*
       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
     sparkVersion: "3.3.1"
     restartPolicy:
       type: Never
     driver:
       cores: 1
       coreLimit: "1200m"
       memory: "512m"
       labels:
         version: 3.3.1
       serviceAccount: my-spark-driver-sa
     executor:
       cores: 1
       instances: 1
       memory: "512m"
       labels:
         version: 3.3.1
   EOF
   ```

   버전 7 릴리스에서 Spark 운영자를 사용하는 경우 구성 값 중 일부를 조정합니다.

   ```
   cat >word-count.yaml <<EOF
   apiVersion: "sparkoperator.k8s.io/v1beta2"
   kind: SparkApplication
   metadata:
     name: word-count
     namespace: spark-operator
   spec:
     type: Java
     mode: cluster
     image: "895885662937.dkr.ecr.us-west-2.amazonaws.com/spark/emr-7.7.0:latest"
     imagePullPolicy: Always
     mainClass: org.apache.spark.examples.JavaWordCount
     mainApplicationFile: local:///usr/lib/spark/examples/jars/spark-examples.jar
     arguments:
       - s3://my-pod-bucket/poem.txt
     hadoopConf:
      # EMRFS filesystem
       fs.s3.customAWSCredentialsProvider: com.amazonaws.auth.WebIdentityTokenCredentialsProvider
       fs.s3.impl: com.amazon.ws.emr.hadoop.fs.EmrFileSystem
       fs.AbstractFileSystem.s3.impl: org.apache.hadoop.fs.s3.EMRFSDelegate
       fs.s3.buffer.dir: /mnt/s3
       fs.s3.getObject.initialSocketTimeoutMilliseconds: "2000"
       mapreduce.fileoutputcommitter.algorithm.version.emr_internal_use_only.EmrFileSystem: "2"
       mapreduce.fileoutputcommitter.cleanup-failures.ignored.emr_internal_use_only.EmrFileSystem: "true"
     sparkConf:
       # Required for EMR Runtime
       spark.driver.extraClassPath: /usr/lib/hadoop-lzo/lib/*:/usr/lib/hadoop/hadoop-aws.jar:/usr/share/aws/aws-java-sdk/*:/usr/share/aws/aws-java-sdk-v2/*:/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/*
       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
       spark.executor.extraClassPath: /usr/lib/hadoop-lzo/lib/*:/usr/lib/hadoop/hadoop-aws.jar:/usr/share/aws/aws-java-sdk/*:/usr/share/aws/aws-java-sdk-v2/*:/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/*
       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
     sparkVersion: "3.3.1"
     restartPolicy:
       type: Never
     driver:
       cores: 1
       coreLimit: "1200m"
       memory: "512m"
       labels:
         version: 3.3.1
       serviceAccount: my-spark-driver-sa
     executor:
       cores: 1
       instances: 1
       memory: "512m"
       labels:
         version: 3.3.1
   EOF
   ```

1. Spark 애플리케이션을 제출합니다.

   ```
   kubectl apply -f word-count.yaml
   ```

   kubectl 명령은 `word-count`라고 하는 `SparkApplication` 객체를 성공적으로 생성했다는 확인을 반환합니다.

   ```
   sparkapplication.sparkoperator.k8s.io/word-count configured
   ```

1. `SparkApplication` 객체에 대한 이벤트를 확인하려면 다음 명령을 실행합니다.

   ```
   kubectl describe sparkapplication word-count -n spark-operator
   ```

   kubectl 명령은 이벤트와 함께 `SparkApplication`에 대한 설명을 반환합니다.

   ```
   Events:
     Type     Reason                               Age                    From            Message
     ----     ------                               ----                   ----            -------
     Normal   SparkApplicationSpecUpdateProcessed  3m2s (x2 over 17h)     spark-operator  Successfully processed spec update for SparkApplication word-count
     Warning  SparkApplicationPendingRerun         3m2s (x2 over 17h)     spark-operator  SparkApplication word-count is pending rerun
     Normal   SparkApplicationSubmitted            2m58s (x2 over 17h)    spark-operator  SparkApplication word-count was submitted successfully
     Normal   SparkDriverRunning                   2m56s (x2 over 17h)    spark-operator  Driver word-count-driver is running
     Normal   SparkExecutorPending                 2m50s                  spark-operator  Executor [javawordcount-fdd1698807392c66-exec-1] is pending
     Normal   SparkExecutorRunning                 2m48s                  spark-operator  Executor [javawordcount-fdd1698807392c66-exec-1] is running
     Normal   SparkDriverCompleted                 2m31s (x2 over 17h)    spark-operator  Driver word-count-driver completed
     Normal   SparkApplicationCompleted            2m31s (x2 over 17h)    spark-operator  SparkApplication word-count completed
     Normal   SparkExecutorCompleted               2m31s (x2 over 2m31s)  spark-operator  Executor [javawordcount-fdd1698807392c66-exec-1] completed
   ```

이제 애플리케이션이 S3 파일에 있는 단어 수를 계산합니다. 단어 수를 확인하려면 드라이버의 로그 파일을 참조하세요.

```
kubectl logs pod/word-count-driver -n spark-operator
```

kubectl 명령은 word-count 애플리케이션의 결과와 함께 로그 파일의 콘텐츠를 반환해야 합니다.

```
INFO DAGScheduler: Job 0 finished: collect at JavaWordCount.java:53, took 5.146519 s
                Software: 1
```

Spark 운영자를 통해 Spark에 애플리케이션을 제출하는 방법에 대한 자세한 내용은 GitHub의 *Kubernetes Operator for Apache Spark (spark-on-k8s-operator)* 설명서에서 [Using a SparkApplication](https://www.kubeflow.org/docs/components/spark-operator/user-guide/using-sparkapplication/)을 참조하세요.