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

相關文章
相關標籤/搜索