1、组件版本
调度系统:DolphinScheduler1.2.1java
spark版本:2.3.2python
2、提交方式
spark在submit脚本里提交job的时候,常常会有这样的警告web
Warning: Master yarn-cluster is deprecated since 2.0. Please use master "yarn" with specified deploy mode instead.
这是由于你用了yarn-cluster的方式:sql
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
类中源代码以下:shell
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
,源代码以下:apache
(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模式oop
设为yarn-cluster时:yarn-cluster模式大数据
3、运行原理
yarn/yarn-client模式以下:ui
yarn-cluster模式以下:
很明显,明面上惟一的区别就体如今driver在调度机器上仍是在yarn
4、分析过程
我用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
参数分别设置为yarn
或yarn-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 Properties和System Properties的全部参数配置拷贝出来放文件里面,我这里把两种模式下的全部配置项拷出来以后去掉了全部相同配置对比图以下:
能够看到区别比较大的是spark.submit.deployMode
分别为cluster
和client
,关键部分在下面的System Properties,里面包含了运行spark-submit脚本的路径和用户,还有实际执行java程序的调用类都不一样!
5、致命区别
-
yarn(yarn-client):
-
带宽角度
这种模式因为driver在你的调度机器上,若是调度机器不在yarn集群机器上部署,driver与executor通讯会致使大量的带宽流量产生,spark streaming实时程序或者程序比较多的状况下,网络带宽会打满撑爆,带宽打满的状况下,连锁反应的后果是集群上全部任务都会拖慢,线上事故妥妥的!若是调度机器跟yarn同一集群,推荐这种方式!也方便在调度系统上查看driver的日志。
-
权限控制角度
在上图中能够看到System Properties的
user.name
是lijf,上面的代码最后会有写表的操做,写hdfs的用户也就是lijf,由于最后实际执行spark程序executor端的用户就是lijf,控制hdfs读写权限只须要控制lijf用户的读写权限就好了,这里使用的是ranger作权限控制,很是方便。
-
-
yarn-cluster
-
带宽角度
这种方式提交spark任务后,启动driver的节点是yarn上的随机节点,由AppMaster启动,无需关注调度机器是否与yarn集群部署在一块。
-
权限控制角度
这种方式致命的缺点,能够看到System Properties的
user.name
是yarn,意思是不管哪一个用户提交spark任务,最后executor端读写hdfs都是以yarn的身份,因此集群的权限管理根本无法控制!权限控制很差,删库跑路,完了别告诉我你是干大数据的,线上事故妥妥的!固然,你也能够想办法去设置executor端的用户,须要想办法指定系统变量,基于DolphinScheduler本人目前还没找到很好的方法去配置,可是基于与hadoop关系较好的oozie是能够配置的,由于oozie调度任务自然的优点自己就是在yarn上运行,指定oozie的调度用户即指定了运行时的系统用户,从而把系统用户传给了executor。这里控制的是hdfs文件的权限,不要与hive表权限混为一谈,hive表的权限是在drive端去操做catlog控制ddl操做。
-
6、总结
综上所述,调度与yarn集群共同机器部署,spark的–master参数置为yarn是最佳配置,既不产生带宽问题,也没有权限控制问题。