这是一个很难解决的问题,但我能够使用以下命令解决它:
curl -X POST --data '{"proxyUser": "hadoop","file": "s3://MYBUCKETLOCATION/recurring_job_automation/sample-pyspark-app/hello.py", "jars": ["s3://MYBUCKETLOCATION/recurring_job_automation/sample-pyspark-app/NQjc.jar"], "pyFiles": ["s3://MYBUCKETLOCATION/recurring_job_automation/sample-pyspark-app/application.zip"], "archives": ["s3://MYBUCKETLOCATION/recurring_job_automation/sample-pyspark-app/venv.zip#venv"], "driverMemory": "10g", "executorMemory": "10g", "name": "Name of Import Job here", "conf":{
"spark.yarn.appMasterEnv.SPARK_HOME": "/usr/lib/spark",
"spark.yarn.appMasterEnv.PYSPARK_PYTHON": "./venv/bin/python",
"livy.spark.yarn.appMasterEnv.PYSPARK_PYTHON": "./venv/bin/python",
"spark.yarn.executorEnv.PYSPARK_PYTHON": "./venv/bin/python",
"spark.pyspark.virtualenv.enabled": "true",
"spark.pyspark.virtualenv.type": "native",
"spark.pyspark.virtualenv.requirements":"requirements.pip",
"spark.pyspark.virtualenv.bin.path": "virtualenv",
"spark.master": "yarn",
"spark.submit.deployMode": "cluster"}}' -H "Content-Type: application/json" http://MY-PATH--TO-MY--EMRCLUSTER:8998/batches
在我克隆包含应用程序文件的存储库后,在 EMR 集群的主节点上运行此脚本以设置我的依赖项后:
set -e
set -x
export HADOOP_CONF_DIR="/etc/hadoop/conf"
export PYTHON="/usr/bin/python3"
export SPARK_HOME="/usr/lib/spark"
export PATH="$SPARK_HOME/bin:$PATH"
# Set $PYTHON to the Python executable you want to create
# your virtual environment with. It could just be something
# like `python3`, if that's already on your $PATH, or it could
# be a /fully/qualified/path/to/python.
test -n "$PYTHON"
# Make sure $SPARK_HOME is on your $PATH so that `spark-submit`
# runs from the correct location.
test -n "$SPARK_HOME"
"$PYTHON" -m venv venv --copies
source venv/bin/activate
pip install -U pip
pip install -r requirements.pip
deactivate
# Here we package up an isolated environment that we'll ship to YARN.
# The awkward zip invocation for venv just creates nicer relative
# paths.
pushd venv/
zip -rq ../venv.zip *
popd
# Here it's important that application/ be zipped in this way so that
# Python knows how to load the module inside.
zip -rq application.zip application/
按照我在此处提供的说明:Bundling Python3 packages for PySpark results in missing imports
如果您遇到任何问题,请在此处查看 Livy 日志:
/var/log/livy/livy-livy-server.out
以及显示在 Hadoop 资源管理器 UI 中的日志,一旦您通过隧道进入 EMR 主节点并设置 Web 浏览器代理,您就可以从 EMR 控制台中的链接访问这些日志。
此解决方案的一个关键方面是,由于此处提到的问题,Livy 无法通过文件、jar、pyFiles 或存档参数从本地主节点上传文件:https://issues.apache.org/jira/browse/LIVY-222
因此,我可以通过引用我利用 EMRFS 上传到 S3 的文件来解决该问题。此外,对于 virtualenv(如果您使用的是 PySpark),使用 --copies 参数非常重要,否则您最终会得到无法从 HDFS 使用的符号链接。
这里也报告了使用 virtualenv 的问题:https://issues.apache.org/jira/browse/SPARK-13587
与 PySpark 相关联的(可能不适用于您),因此我需要通过添加其他参数来解决它们。其中一些也在这里提到:https://community.hortonworks.com/articles/104947/using-virtualenv-with-pyspark.html
无论如何,由于 Livy 在上传本地文件时遇到问题,直到我通过 EMRFS 从 S3 引用文件解决了该问题,Livy 将失败,因为它无法将文件上传到暂存目录。此外,当我尝试在 HDFS 中提供绝对路径而不是使用 S3 时,因为 HDFS 资源由 hadoop 用户拥有,而不是 livy 用户,livy 无法访问它们并将它们复制到暂存目录以执行作业。因此,有必要通过 EMRFS 从 S3 引用文件。