使用开源 EMR CLI 工具在亚马逊 EMR 上构建、部署和运行 Spark 作业

今天,我们很高兴地推出 亚马逊 EMR CLI ,这是一款新的命令行工具,用于在不同的 亚马逊 EM R 环境中打包和部署 PySpark 项目。随着 EMR CLI 的推出,您现在有了一种简单的方法,不仅可以将各种 PySpark 项目部署到远程 EMR 环境,还可以与您选择的 CI/CD 解决方案集成。

在这篇文章中,我们将介绍如何使用 EMR CLI 从头开始创建一个新的 PySpark 项目,并通过一条命令将其部署到 Amazon EMR Serverle ss。

解决方案概述

EMR CLI 是一款开源工具,可帮助改善开发人员在 Amazon EMR 上开发和部署任务的体验。当你刚开始使用 Apache Spark 时,在如何打包、部署和运行作业方面有多种选择,这些选项可能会让人不知所措或需要深厚的领域专业知识。EMR CLI 为这些操作提供了简单的命令,从而消除了部署 Spark 作业时的猜测。您可以使用它来创建新项目或与现有的 PySpark 项目一起使用。

在这篇文章中,我们将介绍如何创建一个新的 PySpark 项目,该项目分析来自 NOAA 全球表面摘要每日 开放数据集的 天气数据。我们将使用 EMR CLI 执行以下操作:

  1. 初始化项目。
  2. 打包依赖关系。
  3. 将代码和依赖项部署到 亚马逊 Simple Storage Servic e (Amazon S3)。
  4. 在 EMR 无服务器上运行作业。

先决条件

在本演练中,您应该具备以下先决条件:

  • 一个 亚马逊云科技 账户
  • 美国东部 1 地区的 EMR 无服务器应用程序
  • 一个 S3 存储桶,用于存放您在 us-east- 1 区域中的代码和日志
  • 一个 亚马逊云科技 身份和访问管理 (IAM) 任务角色,可以运行 EMR 无服务器任务和访问 S3 存储桶
  • Python 版本 >= 3.7
  • Docker

如果您还没有 EMR 无服务器应用程序,则可以在安装 CLI 后使用以下 亚马逊云科技 CloudFormation 模板或使用 emr bootstrap 命令。

BDB-2063-launch-cloudformation-stack

安装 EMR 命令行界面

你可以在 GitHub 存储库中找到 EMR CLI 的源代码 ,但它也是通过 P yPI 分发的。它需要 Python 版本 >= 3.7 才能运行,并已在 macOS、Linux 和 Windows 上进行了测试。要安装最新版本,请使用以下命令:

pip3 install emr-cli

现在,您应该能够运行 emr-- help 命令并查看可以使用的不同子命令:

❯ emr --help                                                                                                
Usage: emr [OPTIONS] COMMAND [ARGS]...                                                                      
                                                                                                            
  Package, deploy, and run PySpark projects on EMR.                                                         
                                                                                                            
Options:                                                                                                    
  --help  Show this message and exit.                                                                       
                                                                                                            
Commands:                                                                                                   
  bootstrap  Bootstrap an EMR Serverless environment.                                                       
  deploy     Copy a local project to S3.                                                                    
  init       Initialize a local PySpark project.                                                            
  package    Package a project and dependencies into dist/                                                  
  run        Run a project on EMR, optionally build and deploy                                              
  status 

如果您尚未创建 EMR Serverless 应用程序,则 引导 命令可以为您创建示例环境和包含相关设置的配置文件。假设您使用了提供的 CloudFormation 堆栈,请使用堆栈的 “ 输出” 选项卡上的信息设置以下环境变量。将终端中的区域设置为 us-east-1, 并设置我们在此过程中需要的其他一些环境变量:

export AWS_REGION=us-east-1
export APPLICATION_ID=<YOUR_EMR_SERVERLESS_APPLICATION_ID>
export JOB_ROLE_ARN=<YOUR_EMR_SERVERLESS_JOB_ROLE_ARN>
export S3_BUCKET=<YOUR_S3_BUCKET_NAME>

我们之所以使用 us-east-1, 是因为那是 NOAA GSOD 数据存储桶所在的地方。默认情况下,EMR 无服务器可以访问同一区域中的 S3 存储桶和其他 亚马逊云科技 资源。要访问其他服务, 请将 EMR 无服务器配置为 VPC 访问权限。

初始化项目

接下来,我们使用 emr init 命令在提供的目录中为我们初始化一个默认 PySpark 项目。默认模板创建了一个标准 Python 项目,该项目使用 p yproject.toml 来定义其依赖关系。在这种情况下,我们在脚本中使用了 Pandas 和 PyArrow,因此它们已经预先填充好了。

❯ emr init my-project
[emr-cli]: Initializing project in my-project
[emr-cli]: Project initialized.

项目初始化后,你可以运行 cd my-pro ject 或在你选择的代码编辑器中打开 my- project 目录。你应该看到以下一组文件:

my-project  
├── Dockerfile  
├── entrypoint.py  
├── jobs  
│ └── extreme_weather.py  
└── pyproject.toml

请注意,我们这里还有一个 Dockerfile。pack ag e 命令使用它来确保我们的项目依赖关系建立在 Amazon EMR 的正确架构和操作系统上。

如果你使用 P oetry 来管理你的 Python 依赖关系,你还可以在 emr in it 命令中添加 --project-type 诗歌 标志来创建诗歌项目。

如果你已经有一个 PySpark 项目,你可以使用 emr init--dockerfile 来创建打包东西所需的 Dockerfile

运行该项目

现在我们已经创建了示例项目,我们需要打包依赖关系,将代码部署到 Amazon S3,然后在 EMR Serverless 上启动任务。使用 EMR CLI,您可以在一条命令中完成所有这些操作。确保从 my-projec t 目录运行命令:

emr run \
--entry-point entrypoint.py \
--application-id ${APPLICATION_ID} \
--job-role ${JOB_ROLE_ARN} \
--s3-code-uri s3://${S3_BUCKET}/tmp/emr-cli-demo/ \
--build \
--wait

此命令执行多项操作:

  1. 自动检测当前目录中 Spark 项目的类型。
  2. 为您的项目启动编译以打包依赖关系。
  3. 将您的入口点和生成的构建文件复制到 Amazon S3。
  4. 启动 EMR 无服务器作业。
  5. 等待作业完成,如果失败则以错误状态退出。

现在,当作业开始在 EMR Serverless 中运行时,你应该会在终端中看到以下输出:

[emr-cli]: Job submitted to EMR Serverless (Job Run ID: 00f8uf1gpdb12r0l)
[emr-cli]: Waiting for job to complete...
[emr-cli]: Job state is now: SCHEDULED
[emr-cli]: Job state is now: RUNNING
[emr-cli]: Job state is now: SUCCESS
[emr-cli]: Job completed successfully!

仅此而已!如果你想在亚马逊 弹性计算云 (亚马逊 EC2)上的亚马逊 EMR 上运行相同的代码,你可以将 --application-id 替换为--cluster-id j-11111111 CLI 将负责向您的 EMR 集群发送正确的 s park- sub mit 命令。

现在让我们来看一下其他一些命令。

emr 软件包

PySpark 项目可以通过多种方式打包,从单个.py 文件到具有各种依赖关系的复杂 Poetry 项目。EMR CLI 可以帮助您持续打包项目,而不必担心细节。

例如,如果您的项目目录中只有一个.py 文件,则 pack ag e 命令无需执行任何操作。但是,如果您有多个采用典型的 Python 项目风格的.py 文件, emr package 命令会将这些文件压缩成一个包,以后可以将其上传到 Amazon S3 并使用--py-files 选项提供给您的 PySpark 作业。 如果您在 pyproject.toml 中定义了第三方依赖关系 ,则 emr 包 将创建一个虚拟环境存档并使用 spark.archive 选项启动您的 EMR 作业。

EMR CLI 还支持 P oetry 进行依赖关系管理和打包。如果你有一个带有相应的 poet ry.lock 文件的诗歌项目,那么你无需做任何其他事情。 emr packag e 命令将检测你的 p oetry.lock 文件,并使用 Poetry Bundle 插件自动生成项目。你可以通过两种方式使用诗歌项目:

  • 使用 emr init 命令创建项目。这些命令采用 --project-type 诗歌选项,为你创建诗歌项目:
    
    ❯ emr init--project-type 诗歌 emr-poetry [emr-cli]:在 emr-poetry 中初始化项目 [emr-cli]:项目已初始化。❯ cd emr-poetry ❯ 诗歌
    安装
  • 如果你有一个预先存在的项目,你可以使用 emr init--dockerfile 选项,它会创建一个在运行 emr 包时自动使用的 Dockerfile。

最后,如前所述,EMR CLI 为您提供了一个基于 Amazon Linux 2 的默认 Dockerfile,您可以使用它来可靠地构建与不同 EMR 环境兼容的软件包工件。

emr 部署

emr deploy 命令负责将项目所需的工件复制到 Amazon S3,因此您不必担心。无论项目如何打包, emr deploy 都会将生成的文件复制到您选择的 Amazon S3 位置。

其中一个用例是 CI/CD 管道。有时您想将特定版本的代码部署到 Amazon S3 以用于您的数据管道。使用 emr 部署 ,这就像更改 --s 3-code-uri 参数一样简单。

例如,假设你已经使用 emr package 命令打包了项目。大多数 CI/CD 管道都允许您访问 git 标签。你可以将其用作 emr deploy 命令的一部分来部署新版本的工件。在 GitHub 操作中,这是 github.ref_name ,你可以在操作中使用它来将受版本控制的工件部署到亚马逊 S3。参见以下代码:

emr deploy \
    --entry-point entrypoint.py \
    --s3-code-uri s3://<BUCKET_NAME>/<PREFIX>/${{github.ref_name}}/

在下游作业中,当你准备就绪时,你可以更新入口点文件的位置以指向这个新位置,也可以使用下一节中讨论的 emr run 命令。

emr run

让我们快速看一下 emr run 命令。我们之前曾使用它来打包、部署和运行一条命令,但你也可以用它在已经部署的工件上运行。让我们来看看具体的选项:

❯ emr run --help                                                                                            
Usage: emr run [OPTIONS]                                                                                    
                                                                                                            
  Run a project on EMR, optionally build and deploy                                                         
                                                                                                            
Options:                                                                                                    
  --application-id TEXT     EMR Serverless Application ID                                                   
  --cluster-id TEXT         EMR on EC2 Cluster ID                                                           
  --entry-point FILE        Python or Jar file for the main entrypoint                                      
  --job-role TEXT           IAM Role ARN to use for the job execution                                       
  --wait                    Wait for job to finish                                                          
  --s3-code-uri TEXT        Where to copy/run code artifacts to/from                                        
  --job-name TEXT           The name of the job                                                             
  --job-args TEXT           Comma-delimited string of arguments to be passed                                
                            to Spark job                                                                    
                                                                                                            
  --spark-submit-opts TEXT  String of spark-submit options                                                  
  --build                   Package and deploy job artifacts                                                
  --show-stdout             Show the stdout of the job after it's finished                                  
  --help                    Show this message and exit.

如果你想在 EMR Serverless 上运行代码,emr run 命令会使用--applic ation-id 和 --job-role 参数。 如果您想在 EC2 上的 EMR 上运行,则只需要使用 --cl uster-id 选项即可。

这两个选项都需要 --入口点和--s3-code-uri --entry-point 是亚马逊 EMR 将调用的主脚本。如果你有任何依赖关系, --s3-code-uri 就是使用 emr deploy 命令将其上传到的地方,EMR CLI 将构建指向这些工件的相关 spark-submit 属性。

有几种不同的方法可以自定义作业:

  • —job-name — 允许您指定作业或步骤名称
  • —job-args — 允许您为脚本提供命令行参数
  • —spark-submit-opts — 允许您添加其他 spark-submit-opts 选项 ,例如--conf spark.jars 或其他 选项
  • —show-stdout — 目前仅适用于 EC2 上的 EMR 上的单文件.py 作业,但在任务完成后将在您的终端中显示 标准 输出

正如我们之前所见, --build 会同时调用和 部署命令。 当您的代码仍需要远程运行时,这样可以更轻松地迭代本地开发。你可以简单地一遍又一遍地使用相同的 emr run 命令在你选择的环境中构建、部署和运行代码。

未来的更新

EMR 命令行界面正在积极开发中。目前正在进行更新,以支持 E KS 上的 Amazon EMR , 并允许创建本地开发环境,从而使 Spark 作业的本地迭代更加容易。请随时在 GitHub 存储库 中为该项目做出贡献 。

清理

为避免将来产生费用,请停止或删除您的 EMR 无服务器应用程序。如果您使用了 CloudFormation 模板,请务必删除您的堆栈。

结论

随着 EMR CLI 的发布,我们使您可以更轻松地在 EMR 无服务器上部署和运行 Spark 作业。该实用程序在 GitHub 上以开源形式提供 。我们正在计划一系列新功能;如果你有具体的要求,请随时提交问题或打开拉取请求!


作者简介

Damon 是 亚马逊云科技 EMR 团队的首席开发者倡导者。他在数据和分析管道方面工作了 10 多年,他的团队分散了服务日志和堆放柴火。