使用 Amazon EMR 6.x 通过 Docker 运行 Spark 应用程序 - Amazon EMR

使用 Amazon EMR 6.x 通过 Docker 运行 Spark 应用程序

借助 Amazon EMR 6.0.0,Spark 应用程序可以使用 Docker 容器来定义其库依赖项,而不是在集群中的单个 Amazon EC2 实例上安装依赖项。要使用 Docker 运行 Spark,您必须首先配置 Docker 注册表,并在提交 Spark 应用程序时定义其他参数。有关更多信息,请参阅配置 Docker 集成

提交应用程序时,YARN 调用 Docker 来拉取指定的 Docker 映像并在 Docker 容器内运行 Spark 应用程序。这让您可以轻松地定义和隔离依赖项。它可以通过执行任务所需的库来缩短在 Amazon EMR 集群中引导启动或准备实例的时间。

利用 Docker 运行 Spark 时的注意事项

使用 Docker 运行 Spark 时,请确保满足以下先决条件:

  • docker 程序包和 CLI 仅安装在核心节点和任务节点上。

  • 在 Amazon EMR 6.1.0 及更高版本中,您也可以使用以下命令在主节点安装 Docker。

    • sudo yum install -y docker sudo systemctl start docker
  • spark-submit 命令应始终从 Amazon EMR 集群上的主实例运行。

  • 用于解析 Docker 映像的 Docker 注册表必须使用带有 container-executor 分类键的分类 API 来定义,以便在启动集群时定义其他参数:

    • docker.trusted.registries

    • docker.privileged-containers.registries

  • 要在 Docker 容器中执行 Spark 应用程序,需要以下配置选项:

    • YARN_CONTAINER_RUNTIME_TYPE=docker

    • YARN_CONTAINER_RUNTIME_DOCKER_IMAGE={DOCKER_IMAGE_NAME}

  • 使用 Amazon ECR 检索 Docker 镜像时,必须将集群配置为对自身进行身份验证。为此,您必须使用以下配置选项:

    • YARN_CONTAINER_RUNTIME_DOCKER_CLIENT_CONFIG={DOCKER_CLIENT_CONFIG_PATH_ON_HDFS}

  • 在 EMR 6.1.0 及更高版本中,当自用 ECR 自动身份验证时,您不需要使用列出的命令 YARN_CONTAINER_RUNTIME_DOCKER_CLIENT_CONFIG={DOCKER_CLIENT_CONFIG_PATH_ON_HDFS}

  • 与 Spark 一起使用的任何 Docker 映像都必须在 Docker 映像中安装了 Java。

有关先决条件的更多信息,请参阅配置 Docker 集成

创建 Docker 镜像

Docker 映像是使用 Dockerfile 创建的,该文件定义了要包含在映像中的程序包和配置。以下两个示例 Dockerfile 文件使用 PySpark 和 SparkR。

PySpark Dockerfile

从该 Dockerfile 创建的 Docker 映像包括 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 创建的 Docker 映像包括 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 参考文档

使用来自 Amazon ECR 的 Docker 镜像

Amazon Elastic Container Registry(Amazon ECR)是一个完全托管式 Docker 容器注册表,可让开发人员轻松地存储、管理和部署 Docker 容器镜像。使用 Amazon ECR 时,必须将集群配置为信任您的 ECR 实例,并且必须配置身份验证,以便集群使用来自 Amazon ECR 的 Docker 镜像。有关更多信息,请参阅配置 YARN 以访问 Amazon ECR

要确保 EMR 主机可以访问存储在 Amazon ECR 中的镜像,集群必须具有通过 AmazonEC2ContainerRegistryReadOnly 策略授予的与实例配置文件关联的权限。有关更多信息,请参阅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": {} } ]

将 PySpark 与 Amazon ECR 结合使用

以下示例使用 PySpark Dockerfile,该文件将被标记并上传到 Amazon ECR。上载 Dockerfile 之后,您可以运行 PySpark 任务并从 Amazon ECR 中引用 Docker 镜像。

启动集群后,使用 SSH 连接到核心节点,并运行以下命令从 PySpark Dockerfile 示例构建本地 Docker 映像。

首先,创建一个目录和一个 Dockerfile。

mkdir pyspark vi pyspark/Dockerfile

粘贴 PySpark Dockerfile 的内容,然后运行以下命令来构建 Docker 映像。

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)

要在 EMR 6.0.0 上提交任务,请引用 Docker 镜像的名称。定义其他配置参数,以确保作业执行使用 Docker 作为运行时。使用 Amazon ECR 时,YARN_CONTAINER_RUNTIME_DOCKER_CLIENT_CONFIG 必须引用 config.json 文件,其中包含用于对 Amazon ECR 进行身份验证的凭证。

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

在 EMR 6.1.0 及更高版本中,要提交作业,请引用 Docker 镜像的名称。启用 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]]

将 SparkR 与 Amazon ECR 结合使用

以下示例使用 SparkR Dockerfile,该文件将被标记并上传到 ECR。上载此 Dockerfile 之后,您可以运行 SparkR 任务并从 Amazon ECR 中引用 Docker 镜像。

启动集群后,使用 SSH 连接到核心节点,并运行以下命令从 SparkR Dockerfile 示例构建本地 Docker 映像。

首先,创建一个目录和该 Dockerfile。

mkdir sparkr vi sparkr/Dockerfile

粘贴 SparkR Dockerfile 的内容并运行以下命令来构建 Docker 映像。

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()

要在 EMR 6.0.0 上提交任务,请引用 Docker 镜像的名称。定义其他配置参数,以确保作业执行使用 Docker 作为运行时。使用 Amazon ECR 时,YARN_CONTAINER_RUNTIME_DOCKER_CLIENT_CONFIG 必须引用 config.json 文件,其中包含用于对 ECR 进行身份验证的凭证。

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

在 EMR 6.1.0 及更高版本中,要提交作业,请引用 Docker 镜像的名称。启用 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: