如何自定义 Docker 镜像 - Amazon EMR
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

如何自定义 Docker 镜像

请按照以下步骤自定义 Amazon EMR on EKS 的 Docker 镜像。

下面是您在自定义 Docker 镜像时可能希望考虑的其他选项:

先决条件

步骤 1:从 Amazon Elastic Container Registry(Amazon ECR)中检索基础镜像

基础映像包含用于访问其他 Amazon 服务的 Amazon EMR 运行时系统和连接器。对于 Amazon EMR 6.9.0 及更高版本,您可以从 Amazon ECR Public Gallery 获取基础映像。浏览图库以找到映像链接,然后将映像拉到本地工作区。例如,对于 Amazon EMR 6.14.0 发行版,以下 docker pull 命令将为您提供最新的标准基础映像。您可以将 emr-6.14.0:latest 替换为 emr-6.14.0-spark-rapids:latest,检索带 Nvidia RAPIDS Accelerator 的映像。您也可以将 emr-6.14.0:latest 替换为 emr-6.14.0-java11:latest,使用 Java 11 运行时系统检索映像。

docker pull public.ecr.aws/emr-on-eks/spark/emr-6.14.0:latest

如果您想检索 Amazon EMR 6.9.0 或更早版本的基础映像,或者如果您希望从每个区域中的 Amazon ECR 注册账户中检索,请使用以下步骤:

  1. 选择基础镜像 URI。镜像 URI 遵循格式(ECR-registry-account.dkr.ecr.Region.amazonaws.com/spark/container-image-tag),示例如下。

    895885662937.dkr.ecr.us-west-2.amazonaws.com/spark/emr-6.6.0:latest

    要选择您所在区域的基础镜像,请参阅如何选择基础镜像 URI

  2. 登录存储基础镜像的 Amazon ECR 存储库。使用 Amazon ECR 注册账户和所选Amazon区域来替换 895885662937us-west-2

    aws ecr get-login-password --region us-west-2 | docker login --username AWS --password-stdin 895885662937.dkr.ecr.us-west-2.amazonaws.com
  3. 将基础镜像拉入本地 Workspace。用所选的容器镜像标签替换 emr-6.6.0:latest

    docker pull 895885662937.dkr.ecr.us-west-2.amazonaws.com/spark/emr-6.6.0:latest

步骤 2:自定义基础镜像

请按照以下步骤来自定义您从 Amazon ECR 中拉取的基础镜像。

  1. 在您的本地 Workspace 上创建新的 Dockerfile

  2. 编辑您刚刚创建的 Dockerfile 并添加以下内容。该 Dockerfile 使用您从 895885662937.dkr.ecr.us-west-2.amazonaws.com/spark/emr-6.6.0:latest 中提取的容器镜像。

    FROM 895885662937.dkr.ecr.us-west-2.amazonaws.com/spark/emr-6.6.0:latest USER root ### Add customization commands here #### USER hadoop:hadoop
  3. 将命令添加到 Dockerfile 以自定义基础镜像。例如,添加命令来安装 Python 库,如以下 Dockerfile 所示。

    FROM 895885662937.dkr.ecr.us-west-2.amazonaws.com/spark/emr-6.6.0:latest USER root RUN pip3 install --upgrade boto3 pandas numpy // For python 3 USER hadoop:hadoop
  4. 在创建 Dockerfile 的同一目录中,请运行以下命令构建 Docker 镜像。为 Docker 镜像提供一个名称,例如 emr6.6_custom

    docker build -t emr6.6_custom .

步骤 3:(可选但建议)验证自定义镜像

我们建议您在发布自定义镜像之前测试它的兼容性。您可以使用 Amazon EMR on EKS 自定义镜像 CLI 检查您的镜像是否具有在 Amazon EMR on EKS 上运行所需要的文件结构和正确配置。

注意

Amazon EMR on EKS 的自定义镜像 CLI 无法确认您的镜像没有错误。在删除基础镜像的依赖项时要格外小心。

可以执行以下步骤,验证您的自定义镜像。

  1. 下载并安装 Amazon EMR on EKS 自定义镜像 CLI。有关更多信息,请参阅 Amazon EMR on EKS 自定义镜像 CLI 安装指南

  2. 运行以下命令以测试安装。

    emr-on-eks-custom-image --version

    下面是此类输出的示例。

    Amazon EMR on EKS Custom Image CLI Version: x.xx
  3. 运行以下命令以验证您的自定义镜像。

    emr-on-eks-custom-image validate-image -i image_name -r release_version [-t image_type]
    • -i 指定需要验证的本地镜像 URI。它可以是镜像 URI,也可以是为镜像定义的任何名称或标签。

    • -r 为基础镜像指定确切的发布版本,例如 emr-6.6.0-latest

    • -t 指定镜像类型。如果这是 Spark 镜像,请输入 spark。默认值为 spark。当前 Amazon EMR on EKS 自定义镜像 CLI 版本仅支持 Spark 运行时镜像。

    如果您成功运行命令并且自定义镜像满足所有必需的配置和文件结构,则返回的输出会显示所有测试结果,如以下示例所示。

    Amazon EMR on EKS Custom Image Test Version: x.xx ... Checking if docker cli is installed ... Checking Image Manifest [INFO] Image ID: xxx [INFO] Created On: 2021-05-17T20:50:07.986662904Z [INFO] Default User Set to hadoop:hadoop : PASS [INFO] Working Directory Set to /home/hadoop : PASS [INFO] Entrypoint Set to /usr/bin/entrypoint.sh : PASS [INFO] SPARK_HOME is set with value: /usr/lib/spark : PASS [INFO] JAVA_HOME is set with value: /etc/alternatives/jre : PASS [INFO] File Structure Test for spark-jars in /usr/lib/spark/jars: PASS [INFO] File Structure Test for hadoop-files in /usr/lib/hadoop: PASS [INFO] File Structure Test for hadoop-jars in /usr/lib/hadoop/lib: PASS [INFO] File Structure Test for bin-files in /usr/bin: PASS ... Start Running Sample Spark Job [INFO] Sample Spark Job Test with local:///usr/lib/spark/examples/jars/spark-examples.jar : PASS ----------------------------------------------------------------- Overall Custom Image Validation Succeeded. -----------------------------------------------------------------

    如果自定义镜像不满足所需的配置或文件结构,则会出现错误消息。返回的输出提供了错误配置或文件结构相关信息。

步骤 4:发布自定义镜像

将新的 Docker 镜像发布到您的 Amazon ECR 注册表。

  1. 运行以下命令创建用于存储 Docker 镜像的 Amazon ECR 存储库。为存储库提供一个名称,例如 emr6.6_custom_repo。将 us-west-2 替换为您的区域。

    aws ecr create-repository \ --repository-name emr6.6_custom_repo \ --image-scanning-configuration scanOnPush=true \ --region us-west-2

    有关更多信息,请参阅《Amazon ECR 用户指南》中的创建存储库

  2. 运行以下命令对您的默认注册表进行身份验证。

    aws ecr get-login-password --region us-west-2 | docker login --username AWS --password-stdin aws_account_id.dkr.ecr.us-west-2.amazonaws.com

    有关更多信息,请参阅《Amazon ECR 用户指南》中的对您的默认注册表进行身份验证

  3. 标记镜像并将其发布到您创建的 Amazon ECR 存储库。

    标记镜像。

    docker tag emr6.6_custom aws_account_id.dkr.ecr.us-west-2.amazonaws.com/emr6.6_custom_repo

    推送镜像。

    docker push aws_account_id.dkr.ecr.us-west-2.amazonaws.com/emr6.6_custom_repo

    有关更多信息,请参阅《Amazon ECR 用户指南》中的将镜像推送到 Amazon ECR

步骤 5:使用自定义镜像在 Amazon EMR 中提交 Spark 工作负载

构建和发布自定义镜像后,您可以使用自定义镜像提交 Amazon EMR on EKS 任务。

首先,创建 start-job-run-request.json 文件并指定 spark.kubernetes.container.image 参数来引用自定义镜像,如下面的 JSON 文件示例所示。

注意

您可以使用 local:// 方案来引用自定义镜像中的可用文件,如下面所示的 JSON 片段中的 entryPoint 参数。您也可以使用 local:// 方案来引用应用程序依赖项。使用 local:// 方案引用的所有文件和依赖项必须已存在于自定义镜像的指定路径。

{ "name": "spark-custom-image", "virtualClusterId": "virtual-cluster-id", "executionRoleArn": "execution-role-arn", "releaseLabel": "emr-6.6.0-latest", "jobDriver": { "sparkSubmitJobDriver": { "entryPoint": "local:///usr/lib/spark/examples/jars/spark-examples.jar", "entryPointArguments": [ "10" ], "sparkSubmitParameters": "--class org.apache.spark.examples.SparkPi --conf spark.kubernetes.container.image=123456789012.dkr.ecr.us-west-2.amazonaws.com/emr6.6_custom_repo" } } }

您还可以使用 applicationConfiguration 属性来引用自定义映像,如以下示例所示。

{ "name": "spark-custom-image", "virtualClusterId": "virtual-cluster-id", "executionRoleArn": "execution-role-arn", "releaseLabel": "emr-6.6.0-latest", "jobDriver": { "sparkSubmitJobDriver": { "entryPoint": "local:///usr/lib/spark/examples/jars/spark-examples.jar", "entryPointArguments": [ "10" ], "sparkSubmitParameters": "--class org.apache.spark.examples.SparkPi" } }, "configurationOverrides": { "applicationConfiguration": [ { "classification": "spark-defaults", "properties": { "spark.kubernetes.container.image": "123456789012.dkr.ecr.us-west-2.amazonaws.com/emr6.6_custom_repo" } } ] } }

然后运行 start-job-run 命令提交任务。

aws emr-containers start-job-run --cli-input-json file://./start-job-run-request.json

将上面 JSON 示例中的 emr-6.6.0-latest 替换为您的 Amazon EMR 发行版的版本。我们强烈建议您使用 -latest 发布版本,以确保所选版本包含最新的安全更新。有关 Amazon EMR 发行版本和相应映像标签的更多信息,请参阅 如何选择基础镜像 URI

注意

您可以使用 spark.kubernetes.driver.container.imagespark.kubernetes.executor.container.image 为驱动程序和执行程序 Pod 指定不同的镜像。

为交互式端点自定义 Docker 映像

您还可以为交互式端点自定义 Docker 映像,以便运行自定义的基础内核映像。这有助于确保在从 EMR Studio 运行交互式工作负载时拥有所需的依赖项。

  1. 按照上述第 1-4 步进行操作,以自定义 Docker 镜像。对于 Amazon EMR 6.9.0 版本及更高版本,您可以从 Amazon ECR Public Gallery 获取基础映像 URI。对于 Amazon EMR 6.9.0 之前的版本,您可以在每个 Amazon Web Services 区域 的 Amazon ECR 注册账户中获取映像,唯一的区别是 Dockerfile 中的基础映像 URI。基础映像 URI 遵循以下格式:

    ECR-registry-account.dkr.ecr.Region.amazonaws.com/notebook-spark/container-image-tag

    您需要在基本镜像 URI 中使用 notebook-spark,而不是 spark。基本镜像包含 Spark 运行时,以及随之运行的笔记本内核。有关选择区域和容器镜像标签的更多信息,请参阅 如何选择基础镜像 URI

    注意

    目前仅支持覆盖基础镜像,除 Amazon 提供的基础镜像之外,不支持引入其他类型的全新内核。

  2. 创建可与自定义映像配合使用的交互式端点。

    首先,使用以下内容创建名为 custom-image-managed-endpoint.json 的 JSON 文件。

    { "name": "endpoint-name", "virtualClusterId": "virtual-cluster-id", "type": "JUPYTER_ENTERPRISE_GATEWAY", "releaseLabel": "emr-6.6.0-latest", "executionRoleArn": "execution-role-arn", "certificateArn": "certificate-arn", "configurationOverrides": { "applicationConfiguration": [ { "classification": "jupyter-kernel-overrides", "configurations": [ { "classification": "python3", "properties": { "container-image": "123456789012.dkr.ecr.us-west-2.amazonaws.com/custom-notebook-python:latest" } }, { "classification": "spark-python-kubernetes", "properties": { "container-image": "123456789012.dkr.ecr.us-west-2.amazonaws.com/custom-notebook-spark:latest" } } ] } ] } }

    然后,使用该 JSON 文件中指定的配置创建交互式端点,如以下示例所示。

    aws emr-containers create-managed-endpoint --cli-input-json custom-image-managed-endpoint.json

    有关更多信息,请参阅为虚拟集群创建交互式端点

  3. 通过 EMR Studio 连接到交互式端点。有关更多信息,请参阅从 Studio 连接

使用多架构镜像

Amazon EMR on EKS 支持适用于 Amazon Elastic Container Registry (Amazon ECR) 的多架构容器镜像。有关更多信息,请参阅适用于 Amazon ECR 的多架构容器镜像简介

Amazon EMR on EKS 自定义映像既支持基于 Amazon Graviton 的 EC2 实例,也支持非基于 Graviton 的 EC2 实例。基于 Graviton 的镜像与非基于 Graviton 的镜像存储在 Amazon ECR 中的相同镜像存储库中。

例如,要检查 Docker 清单列表中是否有 6.6.0 镜像,请运行下面的命令。

docker manifest inspect 895885662937.dkr.ecr.us-west-2.amazonaws.com/spark/emr-6.6.0:latest

下面是输出。arm64 架构适用于 Graviton 实例。amd64 适用于非 Graviton 实例。

{ "schemaVersion": 2, "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json", "manifests": [ { "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "size": 1805, "digest": "xxx123:6b971cb47d11011ab3d45fff925e9442914b4977ae0f9fbcdcf5cfa99a7593f0", "platform": { "architecture": "arm64", "os": "linux" } }, { "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "size": 1805, "digest": "xxx123:6f2375582c9c57fa9838c1d3a626f1b4fc281e287d2963a72dfe0bd81117e52f", "platform": { "architecture": "amd64", "os": "linux" } } ] }

请执行以下步骤以创建多架构镜像:

  1. 创建包含以下内容的 Dockerfile,以便您能拉取 arm64 映像。

    FROM --platform=arm64 895885662937.dkr.ecr.us-west-2.amazonaws.com/spark/emr-6.6.0:latest USER root RUN pip3 install boto3 // install customizations here USER hadoop:hadoop
  2. 按照适用于 Amazon ECR 的多架构容器镜像简介中的说明操作,构建一个多架构镜像。

    注意

    您必须在 arm64 实例上创建 arm64 映像。同样,您必须在 amd64 实例上构建 amd64 映像。

    您还可以使用 Docker buildx 命令构建多架构映像,而无需基于每种特定实例类型上进行构建。有关更多信息,请参阅利用多 CPU 架构支持

  3. 构建多架构镜像后,您可以使用相同的 spark.kubernetes.container.image 参数并指向该映像来提交任务。在同时包括基于 Amazon Graviton 和非基于 Graviton 的 EC2 实例的异构集群中,实例将根据拉取该映像的实例架构确定正确的架构映像。