Pyspark spark-submit 集群提交任务以及引入虚拟环境依赖包攻略

 

网上提交 scala spark 任务的攻略很是多,官方文档其实也很是详细仔细的介绍了 spark-submit 的用法。可是对于 python 的提交说起得很是少,能查阅到的资料很是少致使是有很是多的坑须要踩。html

官方文档对于任务提交有这么一段介绍,可是初次使用者依然会很是疑惑:java

Bundling Your Application’s Dependencies

If your code depends on other projects, you will need to package them alongside your application in order to distribute the code to a Spark cluster. To do this, create an assembly jar (or “uber” jar) containing your code and its dependencies. Both sbt and Maven have assembly plugins. When creating assembly jars, list Spark and Hadoop as provided dependencies; these need not be bundled since they are provided by the cluster manager at runtime. Once you have an assembled jar you can call the bin/spark-submit script as shown here while passing your jar.python

For Python, you can use the --py-files argument of spark-submit to add .py.zip or .egg files to be distributed with your application. If you depend on multiple Python files we recommend packaging them into a .zip or .egg.git

能够看到若是咱们使用 java 系语言,例如 java scala 咱们能够轻松的将相关的依赖环境打包成 .jar,而后在提交的时候使用官方建议使用在的姿式进行集群提交。例如使用:github

sudo -u hdfs spark-submit \
  --class "Excellent" \
  --master yarn \
  --deploy-mode cluster \
  --driver-memory 2g \
  --executor-memory 2g \
  --executor-cores 1 \
  /home/zhizhizhi/sparktry_2.11-0.1.jar

主要程序是 Excellent, 使用 yarn 进行调度,使用集群模式运行。须要分配的执行和 driver 的内存,以及执行的时候指定的核数。apache

 

其实对 python 的 submit 使用 yarn 也和这个命令差很少,咱们可使用服务器

/etc/alternatives/spark-submit \
--master yarn \
--deploy-mode cluster \
--name md_day_dump_user \
--conf "spark.pyspark.driver.python=/home/uther/miniconda2/envs/uther/bin/python2.7" \
--conf "spark.pyspark.python=/home/uther/miniconda2/envs/uther/bin/python2.7" \
--py-files /home/uther/uther/uther.zip \
/home/uther/uther/spark_run/md_day_dump_users.py

好了让咱们来谈下这里面的坑。app

首先注意一下我这里显示申明了使用 /etc/alternatives/spark-submit 若是咱们不使用这个申明咱们会默认使用安装 pyspark 的时候给咱们带的 spark-submit。python2.7

这一点很是重要,由于咱们的集群使用的 CDH 部署的,因此其实不少环境变量依赖什么的 CDH 都已经给咱们配置好了,使用本身的 spark-submit 就须要本身配置这些东西,可能会致使不少问题,好比你没法直接链接到目标 hive  等等等。maven

默认会使用 

(uther) [uther@zed-2 ~]$ which spark-submit
~/miniconda2/envs/uther/bin/spark-submit

这一点要很是难发现。。。。。。得很是当心。

 

使用集群进行运行这一点感受也有坑,按照我查阅的一些资料来看,若是使用集群调度,颇有可能在分配 application master 的时候被分配到别的机器上去,这就须要别的机器也有这一套环境,不然可能会致使失败。可能会报出相似下面的问题,可是也不太肯定,由于最近跑彷佛每次都分配给了提交任务的节点进行执行的,以后再观察一下。

thread "main" java.io.FileNotFoundException: File

通过一段时间的观察,若是使用 yarrn 进行任务调度,的确须要在每一个能够分配的节点上一样的路径下有相同的运行环境才能够保证程序的正常运行这一点要 注意。

我使用的是 miniconda 的环境,因此直接将 miniconda 的包拷贝到相同的路径下而后将权限设置成 777 就能够了。 

 

另外最关键的一步指定虚拟环境可使用相似命令:

--conf "spark.pyspark.driver.python=/home/uther/miniconda2/envs/uther/bin/python2.7" \
--conf "spark.pyspark.python=/home/uther/miniconda2/envs/uther/bin/python2.7" \

这个两条命令指定了集群使用哪里的环境来运行你的程序。明显咱们可能会关联很是多的依赖包,使用这种方法会比较优雅。

另外 spark 提供了另一条命令给咱们引入包

--py-files /home/uther/uther/uther.zip

这条命令的意思相似于个人程序里有 import uther.xxxx.xxx  or from uther.xx.xx import xxx 相似语句,我须要将 uther 当错一个 egg or zip 包来 import 。像第三方包的行为同样。

指定以后 spark 就能在执行你的代码的时候找到对应的环境了。这对在使用 pyspark 的代码结构有必定的要求,尽可能将你的逻辑打包成一个 python 包来方便引用。

 

另外还值得一提的是,当咱们操做提交代码的时候还会报出各类奇奇怪怪的错误,可是基本上分为 权限问题 | 和环境变量问题。

例如没有在 hdfs 上操做读写的权限,就须要你耐心的去 hdfs 上面把相关权限加上,这里列举一个我遇到的比较典型的问题,因为咱们须要将环境部署到每一台可能生成 application master 的机器上去,因此咱们全部的机器都须要部署相关的 python_env 环境。

咱们能够把 miniconda 包打包好而后分别传到各个服务器上的目标路径去。

我在一切都弄好了以后仍是收到以下报错:

19/03/06 21:23:36 INFO yarn.ApplicationMaster: Unregistering ApplicationMaster with FAILED (diag message: User class threw exception: java.io.IOException: 
Cannot run program "/home/uther/miniconda2/envs/uther/bin/python2.7": error=13, Permission denied)

这毫无疑问是一个权限问题,可是我当时检查了个人目标文件夹包括整个 miniconda 包都已经所有 777 了究竟为啥仍是没有权限?

最后我发现原来是 /home/uther 这个个人 /home 目录下的用户目录尚未设置权限,当设置完毕以后 it works! 

ps:spark-6358 的一个同窗和我遇到了相同的问题。

要用 yarn 调用相关的程序也记得把 yarn 加入被调用方的组,而后仔细检查相关的权限。

 

 

Reference:

https://zhuanlan.zhihu.com/p/43434216  spark-python版本依赖与三方模块方案

https://spark.apache.org/docs/2.2.0/submitting-applications.html  官方 Submitting Applications 文档

https://issues.apache.org/jira/browse/SPARK-6358

相关文章
相关标签/搜索