摘要:

hadoop yarn调度pyspark在使用过程中,使用场景不一致,需要安装一些三方依赖,尤其在机器学习算法方面依赖许多科学包如numpy、pandas 、matlib等等,安装这些依赖是一个非常痛苦的过程,本章结合ti产品在私有化过程中依赖包及版本升级等为题进行简单介绍。

Spark on yarn分为client模式和cluster模式,在client模式下driver 会运行在提交节点上,该节点也可能不是yarn集群内部节点,这种方式可以根据自己的需要安装软件和依赖,以支撑spark application正常运行。而在cluster模式下,spark application运行的所有进程都在yarn集群的nodemanager上,具体那些节点不确定,这时候就需要集群中所有nodemanager都有运行python程序所需要的依赖包。 在智能钛私有化过程中是通过:anaconda进行包管理和初始环境安装。

初始安装:安装初始ancoda-》安装所需要的依赖包-》编写rpm编译脚本-》打包成rpm包:之所以采用rpm进行管理,是因为rpm包进行安装、升级、回退。维护相对比较方便,大数据平台ambari可以很好的完成rpm包的自动化安装部署升级。

Name: anaconda2
Version: 4.4.0
Release: 0
License: Restricted
Group: Apache/Hue
BuildRoot: %{_builddir}/%{name}-anaconda2
URL: http://gethue.com/
Vendor: Tencent
Packager: test
BuildArchitectures: x86_64
Requires: jdk >= 1.6 
%description
Anaconda2
%prep
%build
pwd
%install
pwd
rm -rf $RPM_BUILD_ROOT
mkdir -p $RPM_BUILD_ROOT/data/anaconda2-4.4.0
cp -arf %{_sourcedir}/anaconda2-4.4.0.zip $RPM_BUILD_ROOT/data/anaconda2-4.4.0
pwd
%post
cd /data/anaconda2-4.4.0
unzip -qq anaconda2-4.4.0.zip && rm -rf anaconda2-4.4.0.zip
%postun
rm -rf /data/anaconda2-4.4.0
%files
%defattr(-,root,root)
%attr(755,root,root) /data/anaconda2-4.4.0

%clean
rm -rf $RPM_BUILD_ROOT
#!/bin/bash
curdir=$(dirname $(readlink -f $0))
echo $curdir
cd $curdir
last_changed_version=$1
if [[ -d $curdir ]]; then
	rpmbase=$(rpm --showrc | grep _topdir | grep -v % | awk '{print $3}')
	rpmsrc=$rpmbase/SOURCES
	rpmspec=$rpmbase/SPECS

    rm -rf $rpmsrc/anaconda2-4.4.0.zip
	cp anaconda2-4.4.0.zip $rpmsrc
	cp anaconda2.spec $rpmspec/anaconda2.spec
    sed -i "s/Release:.*/Release:${last_changed_version}/g" $rpmspec/anaconda2.spec
	
	rpmbuild -bb $rpmspec/anaconda2.spec
fi

包更新升级,如果有python包更新,可以重新打rpm 然后yum update 更新操作

java pom spark 依赖 spark依赖包_人工智能

java pom spark 依赖 spark依赖包_python_02

java pom spark 依赖 spark依赖包_人工智能_03

使用客户端 spark-submit 在配置pyspark算法,如模型评估、可视化算法时,通常会依赖许多包和升级问题,如上图安装升级相关包,然后再重新打包rpm,在环境中进行yum update 进行升级。还是挺方便的。

对接用户的cdh集群情况:

当对接cdh时候, 这时候肯定不能往hadoop 集群所有机器安装python环境,这个时候pyspark程序默认提交节点采用client模式,每台执行机器机器上自带anaconda python环境,就对用户环境产生较小的影响,同时也能保证功能的正常使用。如果要用cluster模式就最好使用spark spark.yarn.archive 等方式

其他包依赖方案:

files to be distributed with your application. If you depend on multiple Python files we recommend
packaging them into a .zip or .egg.

另外还有一种:

当有某些特别依赖看,比如tensorflow、cafe、xgboost:可以把python整个环境打包成zip包,提交脚本可以使用

spark.yarn.dist.archives | spark.pyspark.python 来指定python依赖包

操作步骤:

  • 将带有python环境的打包(这里暂时使用anaconda),也可以其它python环境。
  • java pom spark 依赖 spark依赖包_java pom spark 依赖_04

  • hadoop fs -put anaconda2.zip /data 上传到hdfs目录

java pom spark 依赖 spark依赖包_java pom spark 依赖_05

spark-conf中配置
spark.yarn.dist.archives=hdfs://hdfsCluster/data/anaconda2.zip#anaconda2
spark.pyspark.python=./anaconda2/anaconda2/bin/python2
注:此时应特别注意解压路径,在anaconda2.zip在本地解压后,python的可执行路径为anaconda2/bin/python2,但在服务器上面会多一层。

测试脚本:

from __future__ import print_function
import sys
from operator import add

from pyspark import SparkContext


if __name__ == "__main__":
    if len(sys.argv) != 2:
        print("Usage: wordcount <file>", file=sys.stderr)
        exit(-1)
    import numpy
    import pandas
    print("------------teslatest---------")
    print(numpy.__version__)
    print(pandas.__version__)
    sc = SparkContext(appName="PythonWordCount")
    lines = sc.textFile(sys.argv[1], 1)
    counts = lines.flatMap(lambda x: x.split(' ')) \
                  .map(lambda x: (x, 1)) \
                  .reduceByKey(add)
    output = counts.collect()
    for (word, count) in output:
        print("%s: %i" % (word, count))

    sc.stop()

执行结果:打印了pandas 及numpy版本。

java pom spark 依赖 spark依赖包_python_06

java pom spark 依赖 spark依赖包_人工智能_07

/data/hadoop/yarn/local/usercache/admin/appcache/application_1554879337971_3182/container_1554879337971_3182_01_000001/anaconda2/anaconda2

同时我们可以看到anaconda2 的python环境 同步到了nodemanager 本机

java pom spark 依赖 spark依赖包_spark_08

再来看下本机器上的python包版本情况

java pom spark 依赖 spark依赖包_spark_09

验证spark运行pyspark对应的numpy版本以及pandas版本,可以得知确实是使用的hdfs中的包。

so如果大家在有包依赖的问题,可以使用后面的终极大招。