基於DolphinScheduler提交spark yarn-cluster與yarn-client模式的致命區別

一、組件版本

調度系統:DolphinScheduler1.2.1

spark版本:2.3.2

二、提交方式

spark在submit腳本里提交job的時候,經常會有這樣的警告

 Warning: Master yarn-cluster is deprecated since 2.0. Please use master "yarn" with specified deploy mode instead.

這是因爲你用了yarn-cluster的方式:

spark-submit \
--master yarn-cluster \
--executor-cores 2 \
--num-executors 3 \
--executor-memory 4g \
--driver-memory 1g \
test_spark.py

其實yarn-cluster與yarn-client分爲兩部分,分別對應spark內部的參數master-deployMode,不論你指定yarn-cluster還是yarn-client,master的值在源碼裏面都強制置爲了YARN,在org.apache.spark.deploy.SparkSubmit類中源代碼如下:

    val clusterManager: Int = args.master match {
      case "yarn" => YARN
      case "yarn-client" | "yarn-cluster" =>
        printWarning(s"Master ${args.master} is deprecated since 2.0." +
          " Please use master \"yarn\" with specified deploy mode instead.")
        YARN
      case m if m.startsWith("spark") => STANDALONE
      case m if m.startsWith("mesos") => MESOS
      case m if m.startsWith("k8s") => KUBERNETES
      case m if m.startsWith("local") => LOCAL
      case _ =>
        printErrorAndExit("Master must either be yarn or start with spark, mesos, k8s, or local")
        -1
    }

spark deployMode的默認值是client,但是在spark-submit腳本中,這個參數一般沒人會去指定,所以就用它的默認值了。當所有人都適應默認值的時候,問題來了,如果在spark-submit腳本中設置了--master yarn-clsuter,源碼裏面會把deployMode的值修改爲cluster,源代碼如下:

 (args.master, args.deployMode) match {
        case ("yarn-cluster", null) =>
           // 這裏把原本的默認值改成了CLUSTER
          deployMode = CLUSTER
          args.master = "yarn"
        case ("yarn-cluster", "client") =>
          printErrorAndExit("Client deploy mode is not compatible with master \"yarn-cluster\"")
        case ("yarn-client", "cluster") =>
          printErrorAndExit("Cluster deploy mode is not compatible with master \"yarn-client\"")
        case (_, mode) =>
          args.master = "yarn"
      }

簡言之,spark-submit腳本指定–master參數,實際決定了兩個值:

設爲yarn/yarn-client時:yarn-client模式

設爲yarn-cluster時:yarn-cluster模式

三、運行原理

yarn/yarn-client模式如下:

在這裏插入圖片描述

yarn-cluster模式如下:

在這裏插入圖片描述

很明顯,明面上唯一的區別就體現在driver在調度機器上還是在yarn

四、分析過程

我用py寫了個簡單的spark程序,基本就是讀表、存表的操作

#!/usr/bin/env python3
from pyspark.sql import SparkSession
spark = SparkSession.builder.master("yarn").enableHiveSupport().getOrCreate()
df = spark.sql("select item_type,count(*) as num from dw_db.dw_recessw_minipage_items_h group by item_type")
df.write.mode("overwrite").saveAsTable("dw_db.pyspark")

spark-submit腳本,--master參數分別設置爲yarnyarn-master

source /etc/profile
spark-submit \
--master yarn 或 yarn-master \
--executor-cores 2 \
--num-executors 3 \
--executor-memory 4g \
--driver-memory 1g \
test_pyspark.py

以兩種模式分別運行後打開spark的web ui界面點擊Environment導航欄

在這裏插入圖片描述

分別把上面的Spark PropertiesSystem Properties的所有參數配置拷貝出來放文件裏面,我這裏把兩種模式下的所有配置項拷出來之後去掉了所有相同配置對比圖如下:

在這裏插入圖片描述

可以看到區別比較大的是spark.submit.deployMode分別爲clusterclient,關鍵部分在下面的System Properties,裏面包含了運行spark-submit腳本的路徑用戶,還有實際執行java程序的調用類都不同!

五、致命區別

  • yarn(yarn-client):

    • 帶寬角度

      這種模式由於driver在你的調度機器上,如果調度機器不在yarn集羣機器上部署,driver與executor通信會導致大量的帶寬流量產生,spark streaming實時程序或者程序比較多的情況下,網絡帶寬會打滿撐爆,帶寬打滿的情況下,連鎖反應的後果是集羣上所有任務都會拖慢,線上事故妥妥的!如果調度機器跟yarn同一集羣,推薦這種方式!也方便在調度系統上查看driver的日誌。

    • 權限控制角度

      在上圖中可以看到System Propertiesuser.name是lijf,上面的代碼最後會有寫表的操作,寫hdfs的用戶也就是lijf,因爲最後實際執行spark程序executor端的用戶就是lijf,控制hdfs讀寫權限只需要控制lijf用戶的讀寫權限就行了,這裏使用的是ranger做權限控制,非常方便。

  • yarn-cluster

    • 帶寬角度

      這種方式提交spark任務後,啓動driver的節點是yarn上的隨機節點,由AppMaster啓動,無需關注調度機器是否與yarn集羣部署在一塊。

    • 權限控制角度

      這種方式致命的缺點,可以看到System Propertiesuser.nameyarn,意思是無論哪個用戶提交spark任務,最後executor端讀寫hdfs都是以yarn的身份,所以集羣的權限管理根本沒法控制!權限控制不好,刪庫跑路,完了別告訴我你是幹大數據的,線上事故妥妥的!當然,你也可以想辦法去設置executor端的用戶,需要想辦法指定系統變量,基於DolphinScheduler本人目前還沒找到很好的方法去配置,但是基於與hadoop關係較好的oozie是可以配置的,因爲oozie調度任務天然的優勢本身就是在yarn上運行,指定oozie的調度用戶即指定了運行時的系統用戶,從而把系統用戶傳給了executor。這裏控制的是hdfs文件的權限,不要與hive表權限混爲一談,hive表的權限是在drive端去操作catlog控制ddl操作。

六、總結

綜上所述,調度與yarn集羣共同機器部署,spark的–master參數置爲yarn是最佳配置,既不產生帶寬問題,也沒有權限控制問題。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章