PySpark on Yarn的相关依赖的解决方式

问题

Spark on Yarn是将yarn作为ClusterManager的运行模式,Spark会将资源(container)的管理与协调统一交给yarn去处理。

Spark on Yarn分为client/cluster模式:
对于client模式,Spark程序的Driver/SparkContext实例用户提交机上,该机器可以位于yarn集群之内或之外,只需要起能正常与ResourceManager通信及正确配置HADOOP_CONF_DIR或YARN_CONF_DIR环境变量指向yarn集群。生产环境中,通常提交机不会是yarn集群内部的节点,手握配置权限的情况下,可以按需配置支撑Spark程序需要的软件、环境、文件等。
对于cluster模式,Spark程序的Driver/SparkContext实例位于ApplicationMaster(am)中,am作为一个container可以起在yarn集群中任何一个NodeManager上,默认情况下,我们就需要为所有的节点机器准备好Spark程序需要的所有运行环境。

Python提供了非常丰富的数学运算、机器学习处理库——如numpypandasscipy等等。越来越多的同事希望利用这些高效的库开发各种算法然后以PySpark程序跑到我们的Spark上。

对于scala/java写的Spark程序,我们可以将我们所依赖的jar一起与我们的main函数所在的主程序打成一个fat jar,通过spark-submit提交后,这些依赖就会通过Yarn的Distribute Cache分发到所有节点支撑运行。
对于python写的Spark程序如果有外部依赖就很尴尬了,python本身就是两种语言,在所有NodeManager节点上安装你所有需要的依赖对于IT运维人员也是一个非常痛苦的事情。

参考官方文档

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.

--py-files,可以解决部分依赖的问题,但对于有些场景就可能不是很方便,或者不可能实现。

  • 依赖太多,包括传递依赖
  • python包在deploy前需要依赖的C代码提前编译
  • 基于不同版本的python的pyspark跑在同一个yarn集群上

对于这些问题 ,社区也有相关的讨论,详细可以看下 这个ticket https://issues.apache.org/jira/browse/SPARK-13587

原理

pyspark原理的资料比较少,可以看下wiki

https://cwiki.apache.org/confluence/display/SPARK/PySpark+Internals

可以看下上面链接中的图,图中左右分为driver/executor, 图白色和绿色分python和java,可以看到不管PySpark适宜client还是cluster模式跑在yarn上,driver和executor端都有python的进程起着,这就需要集群中的所有节点都有相应的python依赖环境。

方案

从灵活性的角度来讲,这里从前辈的讨论中总结一下,提供一种在运行时创建python运行及相关依赖的办法

1、下载并安装anaconda
https://www.anaconda.com/download/#linux

2、安装anaconda

sh Anaconda2-5.0.1-Linux-x86_64.sh

2、创建需要的依赖环境conda create

conda create --name py2env_take1 --quiet  --copy --yes python=2 numpy scipy pandas

打印如下消息

Package plan for installation in environment /home/hadoop/anaconda2/envs/py2env_take1:

The following NEW packages will be INSTALLED:

    ca-certificates: 2017.08.26-h1d4fec5_0
    certifi:         2017.11.5-py27h71e7faf_0
    intel-openmp:    2018.0.0-hc7b2577_8
    libedit:         3.1-heed3624_0
    libffi:          3.2.1-hd88cf55_4
    libgcc-ng:       7.2.0-h7cc24e2_2
    libgfortran-ng:  7.2.0-h9f7466a_2
    libstdcxx-ng:    7.2.0-h7a57d05_2
    mkl:             2018.0.1-h19d6760_4
    ncurses:         6.0-h9df7e31_2
    numpy:           1.13.3-py27hbcc08e0_0
    openssl:         1.0.2m-h26d622b_1
    pandas:          0.21.0-py27he307072_1
    pip:             9.0.1-py27ha730c48_4
    python:          2.7.14-hdd48546_24
    python-dateutil: 2.6.1-py27h4ca5741_1
    pytz:            2017.3-py27h001bace_0
    readline:        7.0-ha6073c6_4
    scipy:           1.0.0-py27hf5f0f52_0
    setuptools:      36.5.0-py27h68b189e_0
    six:             1.11.0-py27h5f960f1_1
    sqlite:          3.20.1-hb898158_2
    tk:              8.6.7-hc745277_3
    wheel:           0.30.0-py27h2bc6bb2_1
    zlib:            1.2.11-ha838bed_2

第一次根据网络情况下载上述这些依赖,可能会比较久,以后就会快很多。

du -sh ~/anaconda2/envs/py2env_take1/
965M    /home/hadoop/anaconda2/envs/py2env_take1/

可以看到依赖包整个大小还是挺大的,对于一些实时性比较高的场景这种方式其实不太有利,有些不需要的依赖在创建的时候可以不打进去。当然我们还需要zip压缩一下,可以减小部分网络开销。当然如果我们把这个环境直接提前put到hdfs,也就没有这个问题了。

zip -r -9 -q py2env_take1.zip ./py2env_take1/
du -sh py2env_take1.zip
345M    py2env_take1.zip

这样我们就可以通过--archives path/to/py2env_take1.zip#py2env的方式将python环境上传并分发到spark各个进程的working dir。

测试

不会写python,从spark示例代码里拷一个出来玩玩

from __future__ import print_function

import numpy as np

from pyspark import SparkContext
# $example on$
from pyspark.mllib.stat import Statistics
# $example off$

if __name__ == "__main__":
    sc = SparkContext(appName="CorrelationsExample")  # SparkContext

    # $example on$
    seriesX = sc.parallelize([1.0, 2.0, 3.0, 3.0, 5.0])  # a series
    # seriesY must have the same number of partitions and cardinality as seriesX
    seriesY = sc.parallelize([11.0, 22.0, 33.0, 33.0, 555.0])

    # Compute the correlation using Pearson's method. Enter "spearman" for Spearman's method.
    # If a method is not specified, Pearson's method will be used by default.
    print("Correlation is: " + str(Statistics.corr(seriesX, seriesY, method="pearson")))

    data = sc.parallelize(
        [np.array([1.0, 10.0, 100.0]), np.array([2.0, 20.0, 200.0]), np.array([5.0, 33.0, 366.0])]
    )  # an RDD of Vectors

    # calculate the correlation matrix using Pearson's method. Use "spearman" for Spearman's method.
    # If a method is not specified, Pearson's method will be used by default.
    print(Statistics.corr(data, method="pearson"))
    # $example off$

    sc.stop()

take1

bin/spark-submit --master yarn --deploy-mode client --proxy-user hzyaoqin  /home/hadoop/data/apache-spark/spark-2.1.2-bin-hadoop2.7/examples/src/main/python/mllib/correlations_example.py
17/11/24 23:51:29 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
Traceback (most recent call last):
  File "/home/hadoop/data/apache-spark/spark-2.1.2-bin-hadoop2.7/examples/src/main/python/mllib/correlations_example.py", line 20, in <module>
    import numpy as np
ImportError: No module named numpy

client模式,提示未安装numpy,失败

take2

bin/spark-submit --master yarn --deploy-mode cluster --proxy-user hzyaoqin  /home/hadoop/data/apache-spark/spark-2.1.2-bin-hadoop2.7/examples/src/main/python/mllib/correlations_example.py

cluster 模式,失败
查看am日志

Log Type: stdout
Log Upload Time: Fri Nov 24 23:49:11 +0800 2017
Log Length: 148
Traceback (most recent call last):
  File "correlations_example.py", line 20, in <module>
    import numpy as np
ImportError: No module named numpy

take3

bin/spark-submit --master yarn --deploy-mode cluster --proxy-user hzyaoqin --archives ~/anaconda2/envs/py2env_take2.zip#python2env  --conf spark.yarn.appMasterEnv.PYSPARK_PYTHON=python2env/py2env_take2/bin/python /home/hadoop/data/apache-spark/spark-2.1.2-bin-hadoop2.7/examples/src/main/python/mllib/correlations_example.py

输出结果,成功

Log Type: stdout
Log Upload Time: Fri Nov 24 23:47:45 +0800 2017
Log Length: 149
Correlation is: 0.850028676877
[[ 1.          0.97888347  0.99038957]
 [ 0.97888347  1.          0.99774832]
 [ 0.99038957  0.99774832  1.        ]]

测试版本

https://www.apache.org/dyn/closer.lua/spark/spark-2.2.0/spark-2.2.0-bin-hadoop2.7.tgz
https://www.apache.org/dyn/closer.lua/spark/spark-2.1.2/spark-2.1.2-bin-hadoop2.7.tgz
https://www.apache.org/dyn/closer.lua/spark/spark-2.0.2/spark-2.0.2-bin-hadoop2.7.tgz

其他版本未测试

结论

1、依靠anaconda 创建python依赖环境
2、通过--archives 上传该环境
3、通过spark.yarn.appMasterEnv.PYSPARK_PYTHON指定python执行目录
4、cluster模式可以,client模式显式指定PYSPARK_PYTHON,会导致PYSPARK_PYTHON环境变量不能被spark.yarn.appMasterEnv.PYSPARK_PYTHON overwrite
5、如果executor端也有numpy等依赖,应该要指定spark.executorEnv.PYSPARK_PYTHON(I guess)
6、改日试下anaconda3 创建python3的隔离环境试下。

参考

https://github.com/massmutual/sample-pyspark-application

其他

关于Client模式下的问题,提了个PR,欢迎讨论
https://github.com/apache/spark/pull/19840

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容