如何在AWS EMR无服务器上运行Python项目(包)



我有一个Python项目,其中包含几个模块、类和依赖文件(一个requirements.txt文件(。我想把它打包成一个包含所有依赖项的文件,并将文件路径提供给AWS EMR serverless,后者将运行它

问题是,我不明白如何将Python项目与所有依赖项打包,EMR可以使用哪个文件,等等。我发现的所有示例都使用了一个Python文件。

简单地说,如果我的Python项目不是单个文件,而是更复杂的文件,我该怎么办?

使用EMR Serverless有几种方法可以做到这一点。无论选择哪种方式,都需要为EMR Serverless StartJobRun命令提供一个主入口点Python脚本。

假设您有这样的作业结构,其中main.py是创建Spark会话并运行作业的入口点,job1job2是本地模块。

├── jobs
│   └── job1.py
│   └── job2.py
├── main.py
├── requirements.txt

选项1。将--py-files与压缩的本地模块一起使用,将--archives与用于外部依赖项的打包虚拟环境一起使用

  • 压缩你的工作文件
zip -r job_files.zip jobs
  • 使用具有依赖项的venv-pack创建一个虚拟环境

注意:这必须使用与EMR Serverless类似的操作系统和Python版本来完成,所以我更喜欢使用具有自定义输出的多级Dockerfile。

FROM --platform=linux/amd64 amazonlinux:2 AS base
RUN yum install -y python3
ENV VIRTUAL_ENV=/opt/venv
RUN python3 -m venv $VIRTUAL_ENV
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
COPY requirements.txt .
RUN python3 -m pip install --upgrade pip && 
python3 -m pip install venv-pack==0.2.0 && 
python3 -m pip install -r requirements.txt
RUN mkdir /output && venv-pack -o /output/pyspark_deps.tar.gz
FROM scratch AS export
COPY --from=base /output/pyspark_deps.tar.gz /

如果运行DOCKER_BUILDKIT=1 docker build --output . .,那么现在本地系统上应该有一个pyspark_deps.tar.gz文件。

  • main.pyjob_files.zippyspark_deps.tar.gz上载到S3上的某个位置。

  • 使用以下命令运行EMR无服务器作业(替换APPLICATION_IDJOB_ROLE_ARNYOUR_BUCKET(:

aws emr-serverless start-job-run 
--application-id $APPLICATION_ID 
--execution-role-arn $JOB_ROLE_ARN 
--job-driver '{
"sparkSubmit": {
"entryPoint": "s3://<YOUR_BUCKET>/main.py",
"sparkSubmitParameters": "--py-files s3://<YOUR_BUCKET>/job_files.zip --conf spark.archives=s3://<YOUR_BUCKET>/pyspark_deps.tar.gz#environment --conf spark.emr-serverless.driverEnv.PYSPARK_DRIVER_PYTHON=./environment/bin/python --conf spark.emr-serverless.driverEnv.PYSPARK_PYTHON=./environment/bin/python --conf spark.executorEnv.PYSPARK_PYTHON=./environment/bin/python"
}
}'

选项2。将本地模块打包为Python库,并在打包的虚拟环境中使用--archives

这可能是最可靠的方法,但需要使用setuptools。您可以将一个简单的pyproject.toml文件与现有的requirements.txt一起使用

[project]
name = "mysparkjobs"
version = "0.0.1"
dynamic = ["dependencies"]
[tool.setuptools.dynamic]
dependencies = {file = ["requirements.txt"]}

然后,您可以使用多阶段Dockerfile和自定义构建输出将模块和依赖项打包到虚拟环境中。

注意:这需要启用Docker Buildkit

FROM --platform=linux/amd64 amazonlinux:2 AS base
RUN yum install -y python3
ENV VIRTUAL_ENV=/opt/venv
RUN python3 -m venv $VIRTUAL_ENV
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
WORKDIR /app
COPY . .
RUN python3 -m pip install --upgrade pip && 
python3 -m pip install venv-pack==0.2.0 && 
python3 -m pip install .
RUN mkdir /output && venv-pack -o /output/pyspark_deps.tar.gz
FROM scratch AS export
COPY --from=base /output/pyspark_deps.tar.gz /

现在您可以运行DOCKER_BUILDKIT=1 docker build --output . .,并且会生成一个包含所有依赖项的pyspark_deps.tar.gz文件。将此文件和main.py脚本上载到S3。

假设您将两个文件都上载到了s3://<YOUR_BUCKET>/code/pyspark/myjob/,则运行EMR Serverless作业,如下所示(替换APPLICATION_IDJOB_ROLE_ARNYOUR_BUCKET:

aws emr-serverless start-job-run 
--application-id <APPLICATION_ID> 
--execution-role-arn <JOB_ROLE_ARN> 
--job-driver '{
"sparkSubmit": {
"entryPoint": "s3://<YOUR_BUCKET>/code/pyspark/myjob/main.py",
"sparkSubmitParameters": "--conf spark.archives=s3://<YOUR_BUCKET>/code/pyspark/myjob/pyspark_deps.tar.gz#environment --conf spark.emr-serverless.driverEnv.PYSPARK_DRIVER_PYTHON=./environment/bin/python --conf spark.emr-serverless.driverEnv.PYSPARK_PYTHON=./environment/bin/python --conf spark.executorEnv.PYSPARK_PYTHON=./environment/bin/python"
}
}'

请注意额外的sparkSubmitParameters,它指定了您的依赖项,并为python的正确路径配置了驱动程序和执行程序环境变量。

最新更新