

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

# Amazon EMR 6.x에서 Docker를 사용하여 Spark 애플리케이션 실행
<a name="emr-spark-docker"></a>

**참고**  
설명된 절차는 Amazon EMR 버전 6.x에서만 작동합니다.

Amazon EMR 6.0.0을 사용하는 경우 Spark 애플리케이션이 클러스터의 개별 Amazon EC2 인스턴스에 종속 항목을 설치하는 대신 Docker 컨테이너를 사용하여 라이브러리 종속 항목을 정의할 수 있습니다. 도커로 Spark를 실행하려면 먼저 도커 레지스트리를 구성하고 Spark 애플리케이션을 제출할 때 추가 파라미터를 정의해야 합니다. 자세한 내용은 [Docker 통합 구성](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-plan-docker.html)을 참조하세요.

애플리케이션이 제출되면 YARN이 도커를 호출하여 지정된 도커 이미지를 가져와서 도커 컨테이너 내에서 Spark 애플리케이션을 실행합니다. 이를 통해 종속 항목을 쉽게 정의하고 분리할 수 있습니다. 작업 실행에 필요한 라이브러리를 사용하여 Amazon EMR 클러스터에서 인스턴스를 부트스트랩하거나 준비하는 시간이 단축됩니다.

## Docker에서 Spark를 실행할 때의 고려 사항
<a name="emr-spark-docker-considerations"></a>

도커로 Spark를 실행하기 전에 다음 사전 요구 사항을 충족하는지 확인하세요.
+ `docker` 패키지와 CLI는 코어 및 작업 노드에만 설치해야 합니다.
+ Amazon EMR 6.1.0 이상에서는 다음 명령을 사용하여 프라이머리 노드에 Docker를 설치할 수도 있습니다.
  + 

    ```
    sudo yum install -y docker
    sudo systemctl start docker
    ```
+ `spark-submit` 명령은 항상 Amazon EMR 클러스터의 프라이머리 인스턴스에서 실행해야 합니다.
+ 클러스터를 시작할 때 추가 파라미터를 정의하는 `container-executor` 분류 키와 함께 분류 API를 사용하여 도커 이미지를 확인하는 데 사용되는 도커 레지스트리를 정의해야 합니다.
  + `docker.trusted.registries`
  + `docker.privileged-containers.registries`
+ 도커 컨테이너에서 Spark 애플리케이션을 실행하려면 다음 구성 옵션이 필요합니다.
  + `YARN_CONTAINER_RUNTIME_TYPE=docker`
  + `YARN_CONTAINER_RUNTIME_DOCKER_IMAGE={DOCKER_IMAGE_NAME}`
+ Amazon ECR을 사용하여 도커 이미지를 검색하는 경우 클러스터를 자체적으로 인증하도록 구성해야 합니다. 이렇게 하려면 다음 구성 옵션을 사용해야 합니다.
  + YARN\$1CONTAINER\$1RUNTIME\$1DOCKER\$1CLIENT\$1CONFIG=\$1DOCKER\$1CLIENT\$1CONFIG\$1PATH\$1ON\$1HDFS\$1
+ Amazon EMR 6.1.0 이상에서는 ECR 자동 인증 기능이 활성화된 경우 나열된 명령 `YARN_CONTAINER_RUNTIME_DOCKER_CLIENT_CONFIG={DOCKER_CLIENT_CONFIG_PATH_ON_HDFS}`를 사용할 필요가 없습니다.
+ Spark와 함께 사용되는 모든 도커 이미지에는 Java가 설치되어 있어야 합니다.

필수 조건에 대한 자세한 내용은 [Docker 통합 구성](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-plan-docker.html)을 참조하세요.

## 도커 이미지 생성
<a name="emr-spark-docker-image"></a>

도커 이미지는 이미지에 포함할 패키지와 구성을 정의하는 Dockerfile을 사용하여 생성됩니다. 다음 두 가지 예제 Dockerfile은 PySpark와 SparkR을 사용합니다.

**PySpark Dockerfile**

이 Dockerfile에서 생성된 도커 이미지에는 Python 3 및 NumPy Python 패키지가 포함되어 있습니다. 이 Dockerfile은 Amazon Linux 2와 Amazon Corretto JDK 8을 사용합니다.

```
FROM amazoncorretto:8

RUN yum -y update
RUN yum -y install yum-utils
RUN yum -y groupinstall development

RUN yum list python3*
RUN yum -y install python3 python3-dev python3-pip python3-virtualenv

RUN python -V
RUN python3 -V

ENV PYSPARK_DRIVER_PYTHON python3
ENV PYSPARK_PYTHON python3

RUN pip3 install --upgrade pip
RUN pip3 install numpy pandas

RUN python3 -c "import numpy as np"
```

**SparkR Dockerfile**

이 Dockerfile에서 생성된 도커 이미지에는 R 및 randomForest CRAN 패키지가 포함되어 있습니다. 이 Dockerfile은 Amazon Linux 2와 Amazon Corretto JDK 8을 사용합니다.

```
FROM amazoncorretto:8

RUN java -version

RUN yum -y update
RUN amazon-linux-extras install R4

RUN yum -y install curl hostname

#setup R configs
RUN echo "r <- getOption('repos'); r['CRAN'] <- 'http://cran.us.r-project.org'; options(repos = r);" > ~/.Rprofile

RUN Rscript -e "install.packages('randomForest')"
```

Dockerfile 구문에 대한 자세한 내용은 [Dockerfile 참조 설명서](https://docs.docker.com/engine/reference/builder/)를 참조하세요.

## Amazon ECR에서 도커 이미지 사용
<a name="emr-spark-docker-ECR"></a>

Amazon Elastic Container Registry(Amazon ECR)는 개발자가 Docker 컨테이너 이미지를 간편하게 저장, 관리 및 배포할 수 있게 해주는 완전관리형 Docker 컨테이너 레지스트리입니다. Amazon ECR을 사용하는 경우 ECR 인스턴스를 신뢰하도록 클러스터를 구성해야 하며 클러스터가 Amazon ECR의 도커 이미지를 사용할 수 있도록 인증을 구성해야 합니다. 자세한 내용은 [Amazon ECR에 액세스하도록 YARN 구성](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-plan-docker.html#emr-docker-ECR)을 참조하세요.

Amazon EMR 호스트가 Amazon ECR에 저장된 이미지에 액세스할 수 있도록 하려면 클러스터에 인스턴스 프로파일과 연결된 `AmazonEC2ContainerRegistryReadOnly` 정책의 권한이 있어야 합니다. 자세한 내용은 [`AmazonEC2ContainerRegistryReadOnly` 정책](https://docs.aws.amazon.com/AmazonECR/latest/userguide/ecr_managed_policies.html#AmazonEC2ContainerRegistryReadOnly)을 참조하세요.

이 예제에서는 Amazon ECR 레지스트리를 신뢰할 수 있도록 다음 추가 구성으로 클러스터를 생성해야 합니다. *123456789123.dkr.ecr.us-east-1.amazonaws.com* 엔드포인트를 Amazon ECR 엔드포인트로 바꿉니다.

```
[
  {
    "Classification": "container-executor",
    "Configurations": [
      {
        "Classification": "docker",
        "Properties": {
          "docker.privileged-containers.registries": "local,centos,123456789123.dkr.ecr.us-east-1.amazonaws.com",
          "docker.trusted.registries": "local,centos,123456789123.dkr.ecr.us-east-1.amazonaws.com"
        }
      }
    ],
    "Properties": {}
  }
]
```

**Amazon ECR과 함께 PySpark 사용**

다음 예제에서는 PySpark Dockerfile을 사용하며, 이 Dockerfile을 태그 지정하여 Amazon ECR에 업로드합니다. Dockerfile을 업로드한 후 PySpark 작업을 실행하고 Amazon ECR의 도커 이미지를 참조할 수 있습니다.

클러스터를 시작한 후 SSH를 사용하여 코어 노드에 연결하고 다음 명령을 실행하여 PySpark Dockerfile 예제의 로컬 도커 이미지를 빌드합니다.

먼저 디렉터리와 Dockerfile을 만듭니다.

```
mkdir pyspark
vi pyspark/Dockerfile
```

PySpark Dockerfile의 내용을 붙여 넣고 다음 명령을 실행하여 도커 이미지를 빌드합니다.

```
sudo docker build -t local/pyspark-example pyspark/
```

예제용 `emr-docker-examples` ECR 리포지토리를 생성합니다.

```
aws ecr create-repository --repository-name emr-docker-examples
```

로컬로 빌드한 이미지를 태그 지정하고 ECR에 업로드합니다. 이때 *123456789123.dkr.ecr.us-east-1.amazonaws.com*을 해당 ECR 엔드포인트로 대체합니다.

```
sudo docker tag local/pyspark-example 123456789123.dkr.ecr.us-east-1.amazonaws.com/emr-docker-examples:pyspark-example
sudo docker push 123456789123.dkr.ecr.us-east-1.amazonaws.com/emr-docker-examples:pyspark-example
```

SSH를 사용하여 프라이머리 노드에 연결하고 `main.py`라는 파일 이름으로 Python 스크립트를 준비합니다. 다음 내용을 `main.py` 파일에 붙여 넣고 저장합니다.

```
from pyspark.sql import SparkSession
spark = SparkSession.builder.appName("docker-numpy").getOrCreate()
sc = spark.sparkContext

import numpy as np
a = np.arange(15).reshape(3, 5)
print(a)
```

Amazon EMR 6.0.0에서 작업을 제출하려면 도커 이미지의 이름을 참조합니다. 추가 구성 파라미터를 정의하여 작업 실행에 Docker가 런타임으로 사용되도록 합니다. Amazon ECR을 사용하는 경우 `YARN_CONTAINER_RUNTIME_DOCKER_CLIENT_CONFIG`에서 Amazon ECR에 대한 인증에 사용되는 보안 인증이 포함된 `config.json` 파일을 참조해야 합니다.

```
DOCKER_IMAGE_NAME=123456789123.dkr.ecr.us-east-1.amazonaws.com/emr-docker-examples:pyspark-example
DOCKER_CLIENT_CONFIG=hdfs:///user/hadoop/config.json
spark-submit --master yarn \
--deploy-mode cluster \
--conf spark.executorEnv.YARN_CONTAINER_RUNTIME_TYPE=docker \
--conf spark.executorEnv.YARN_CONTAINER_RUNTIME_DOCKER_IMAGE=$DOCKER_IMAGE_NAME \
--conf spark.executorEnv.YARN_CONTAINER_RUNTIME_DOCKER_CLIENT_CONFIG=$DOCKER_CLIENT_CONFIG \
--conf spark.yarn.appMasterEnv.YARN_CONTAINER_RUNTIME_TYPE=docker \
--conf spark.yarn.appMasterEnv.YARN_CONTAINER_RUNTIME_DOCKER_IMAGE=$DOCKER_IMAGE_NAME \
--conf spark.yarn.appMasterEnv.YARN_CONTAINER_RUNTIME_DOCKER_CLIENT_CONFIG=$DOCKER_CLIENT_CONFIG \
--num-executors 2 \
main.py -v
```

Amazon EMR 6.1.0 이상에서 작업을 제출하려면 도커 이미지의 이름을 참조합니다. ECR 자동 인증이 활성화된 경우 다음 명령을 실행합니다.

```
DOCKER_IMAGE_NAME=123456789123.dkr.ecr.us-east-1.amazonaws.com/emr-docker-examples:pyspark-example
spark-submit --master yarn \
--deploy-mode cluster \
--conf spark.executorEnv.YARN_CONTAINER_RUNTIME_TYPE=docker \
--conf spark.executorEnv.YARN_CONTAINER_RUNTIME_DOCKER_IMAGE=$DOCKER_IMAGE_NAME \
--conf spark.yarn.appMasterEnv.YARN_CONTAINER_RUNTIME_TYPE=docker \
--conf spark.yarn.appMasterEnv.YARN_CONTAINER_RUNTIME_DOCKER_IMAGE=$DOCKER_IMAGE_NAME \
--num-executors 2 \
main.py -v
```

작업이 완료되면 YARN 애플리케이션 ID를 기록하고 다음 명령을 사용하여 PySpark 작업의 출력을 얻습니다.

```
yarn logs --applicationId application_id | grep -C2 '\[\['
LogLength:55
LogContents:
[[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]]
```

**Amazon ECR과 함께 SparkR 사용**

다음 예제에서는 SparkR Dockerfile을 사용하며, 이 Dockerfile을 태그 지정하여 ECR에 업로드합니다. Dockerfile이 업로드된 후 SparkR 작업을 실행하고 Amazon ECR의 도커 이미지를 참조할 수 있습니다.

클러스터를 시작한 후 SSH를 사용하여 코어 노드에 연결하고 다음 명령을 실행하여 SparkR Dockerfile 예제의 로컬 Docker 이미지를 빌드합니다.

먼저 디렉터리와 Dockerfile을 만듭니다.

```
mkdir sparkr
vi sparkr/Dockerfile
```

SparkR Dockerfile의 내용을 붙여 넣고 다음 명령을 실행하여 도커 이미지를 빌드합니다.

```
sudo docker build -t local/sparkr-example sparkr/
```

로컬로 빌드한 이미지를 태그 지정하고 Amazon ECR에 업로드합니다. 이때 *123456789123.dkr.ecr.us-east-1.amazonaws.com*을 해당 Amazon ECR 엔드포인트로 대체합니다.

```
sudo docker tag local/sparkr-example 123456789123.dkr.ecr.us-east-1.amazonaws.com/emr-docker-examples:sparkr-example
sudo docker push 123456789123.dkr.ecr.us-east-1.amazonaws.com/emr-docker-examples:sparkr-example
```

SSH를 사용하여 프라이머리 노드에 연결하고 `sparkR.R`이라는 이름으로 R 스크립트를 준비합니다. 다음 내용을 `sparkR.R` 파일에 붙여 넣습니다.

```
library(SparkR)
sparkR.session(appName = "R with Spark example", sparkConfig = list(spark.some.config.option = "some-value"))

sqlContext <- sparkRSQL.init(spark.sparkContext)
library(randomForest)
# check release notes of randomForest
rfNews()

sparkR.session.stop()
```

Amazon EMR 6.0.0에서 작업을 제출하려면 도커 이미지의 이름을 참조합니다. 추가 구성 파라미터를 정의하여 작업 실행에 Docker가 런타임으로 사용되도록 합니다. Amazon ECR을 사용하는 경우 `YARN_CONTAINER_RUNTIME_DOCKER_CLIENT_CONFIG`에서 ECR에 대한 인증에 사용되는 보안 인증이 포함된 `config.json` 파일을 참조해야 합니다.

```
DOCKER_IMAGE_NAME=123456789123.dkr.ecr.us-east-1.amazonaws.com/emr-docker-examples:sparkr-example
DOCKER_CLIENT_CONFIG=hdfs:///user/hadoop/config.json
spark-submit --master yarn \
--deploy-mode cluster \
--conf spark.executorEnv.YARN_CONTAINER_RUNTIME_TYPE=docker \
--conf spark.executorEnv.YARN_CONTAINER_RUNTIME_DOCKER_IMAGE=$DOCKER_IMAGE_NAME \
--conf spark.executorEnv.YARN_CONTAINER_RUNTIME_DOCKER_CLIENT_CONFIG=$DOCKER_CLIENT_CONFIG \
--conf spark.yarn.appMasterEnv.YARN_CONTAINER_RUNTIME_TYPE=docker \
--conf spark.yarn.appMasterEnv.YARN_CONTAINER_RUNTIME_DOCKER_IMAGE=$DOCKER_IMAGE_NAME \
--conf spark.yarn.appMasterEnv.YARN_CONTAINER_RUNTIME_DOCKER_CLIENT_CONFIG=$DOCKER_CLIENT_CONFIG \
sparkR.R
```

Amazon EMR 6.1.0 이상에서 작업을 제출하려면 도커 이미지의 이름을 참조합니다. ECR 자동 인증이 활성화된 경우 다음 명령을 실행합니다.

```
DOCKER_IMAGE_NAME=123456789123.dkr.ecr.us-east-1.amazonaws.com/emr-docker-examples:sparkr-example
spark-submit --master yarn \
--deploy-mode cluster \
--conf spark.executorEnv.YARN_CONTAINER_RUNTIME_TYPE=docker \
--conf spark.executorEnv.YARN_CONTAINER_RUNTIME_DOCKER_IMAGE=$DOCKER_IMAGE_NAME \
--conf spark.yarn.appMasterEnv.YARN_CONTAINER_RUNTIME_TYPE=docker \
--conf spark.yarn.appMasterEnv.YARN_CONTAINER_RUNTIME_DOCKER_IMAGE=$DOCKER_IMAGE_NAME \
sparkR.R
```

작업이 완료되면 YARN 애플리케이션 ID를 기록하고 다음 명령을 사용하여 SparkR 작업의 출력을 얻습니다. 이 예제에는 RandomForest 라이브러리, 설치된 버전 및 릴리스 정보를 사용할 수 있는지 확인하는 테스트가 포함되어 있습니다.

```
yarn logs --applicationId application_id | grep -B4 -A10 "Type rfNews"
randomForest 4.6-14
Type rfNews() to see new features/changes/bug fixes.
Wishlist (formerly TODO):

* Implement the new scheme of handling classwt in classification.

* Use more compact storage of proximity matrix.

* Allow case weights by using the weights in sampling?

========================================================================
Changes in 4.6-14:
```