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

如何自定义 Docker 镜像

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

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

Prerequisites

  • 请完成 Amazon EMR on EKS 的设置步骤。

  • 在您的环境中安装 Docker。有关更多信息,请参阅获取 Docker

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

请按照以下步骤从 Amazon ECR 检索 Amazon EMR on EKS 基础镜像。基础镜像包含运行时的 Amazon EMR 和用于访问其它Amazon服务的连接器。

  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-5.32.0-20210129

    要选择您所在区域的基础镜像,请参阅如何选择基础镜像 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. 将基础镜像拉入本地工作区。用所选的容器镜像标签替换 emr-6.2.0-20210129

    docker pull 895885662937.dkr.ecr.us-west-2.amazonaws.com/spark/emr-6.2.0-20210129

步骤 2:自定义基础镜像

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

  1. 在您的本地工作区上创建新的 Dockerfile

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

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

    docker build -t emr6.2_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-5.32.0

    • -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.2_custom_repo。将 us-west-2 替换为您的区域。

    aws ecr create-repository \ --repository-name emr6.2_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.2_custom aws_account_id.dkr.ecr.us-west-2.amazonaws.com/emr6.2_custom_repo

    推送镜像。

    docker push aws_account_id.dkr.ecr.us-west-2.amazonaws.com/emr6.2_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.2.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.2_custom_repo" } } }

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

{ "name": "spark-custom-image", "virtualClusterId": "virtual-cluster-id", "executionRoleArn": "execution-role-arn", "releaseLabel": "emr-6.2.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.2_custom_repo" } } ] } }

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

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

在上面的 JSON 示例中,将 emr-6.2.0-latest 替换为您的 Amazon EMR 发行版。在步骤 1:从 Amazon Elastic Container Registry(Amazon ECR)中检索基础镜像中所选的基础镜像标签为 emr-6.2.0-20210129,因此相应的 Amazon EMR 发行版是 emr-6.2.0-latest 或者 emr-6.2.0-20210129。强烈建议您使用 -latest 发行版,以确保所选版本包含最新的安全更新。有关 Amazon EMR 发行版和相应镜像标签的更多信息,请参阅如何选择基础镜像 URI

注意

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

为托管式终端节点自定义 Docker 镜像

您还可以为托管式终端节点自定义 Docker 镜像,以便您能运行自定义内核,并确保您拥有在从 EMR Studio 运行交互式工作负载时所需的依赖项。

  1. 如上所述,按照步骤 1-4 进行操作,以自定义 Docker 镜像。唯一的区别是 Dockerfile 中的基本镜像 URI。基本镜像 URI 遵循此格式:ECR-registry-account.dkr.ecr.Region.amazonaws.com/notebook-spark/container-image-tag。您需要在基本镜像 URI 中使用 notebook-spark,而不是 spark。基本镜像包含 Spark 运行时,以及随之运行的笔记本内核。有关选择区域和容器镜像标签的更多信息,请参阅 如何选择基础镜像 URI

  2. 创建可与自定义镜像配合使用的托管式终端节点。

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

    { "name": "endpoint-name", "virtualClusterId": "virtual-cluster-id", "type": "JUPYTER_ENTERPRISE_GATEWAY", "releaseLabel": "emr-6.2.0-latest", "executionRoleArn": "execution-role-arn", "certificateArn": "certificate-arn", "configurationOverrides": { "applicationConfiguration": [ { "classification": "jupyter-kernel-overrides", "configurations": [ { "classification": "python-kubernetes", "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 自定义镜像既支持基于 Graviton 的 EC2 实例,也支持非基于 Graviton 的 EC2 实例。基于 Graviton 的镜像与非基于 Graviton 的镜像存储在 Amazon ECR 中的相同镜像存储库中。

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

docker manifest inspect 895885662937.dkr.ecr.us-west-2.amazonaws.com/spark/emr-6.3.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.3.0:latest USER root RUN pip3 install boto3 // install customizations here USER hadoop:hadoop
  2. 按照适用于 Amazon ECR 的多架构容器镜像简介中的说明操作,构建一个多架构镜像。

    注意

    需要在 arm64 实例上创建 arm64 镜像。同样,需要在 arm64 实例上创建 amd64 镜像。

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

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