Spark On YARN内存和CPU分配
问题描述:
在使用Spark On YARN时(不管是Client模式或者是Cluster模式,固然下面会有这种模式的对比区别),能够添加诸如:
--executor-memory 8G --executor-cores 5 --num-executors 20
等等这样的参数,可是这个和咱们日常理解的感受有误,或者说不直观,怎么说呢?
好比一个6节点(NodeManager)的集群,每一个节点配置为:16 CPU核,64G内存,那么通常很容易提交代码的时候写成以下配置:
可是这样配置后,你会发现,在8088端口的YARN监控上获得的不是你想获得的资源分配,那正确的配置应该是怎样的呢?
前备知识:
1. YARN NodeManager资源
NodeManager所在的机器若是是16核、64G,那么设置以下参数(这两个参数是NodeManager能分配的最大内存和最大cpu):
yarn.nodemanager.resource.memory-mb
yarn.nodemanager.resource.cpu-vcores
最好是小一点,好比设置内存为63G,核心为15,由于须要分配一些资源给系统以及后台Hadoop进程。固然,若是每一个机器是6核,6G内存,那能够分配到5核以及5.5G内存左右;在原文中,说CDH机器能够自动的分配,不过我看到CDH集群设置这两个参数只是其能最大的值,也就是机器自身的资源。好比个人6核,6G内存,其配置以下:
(固然,默认是8G内存,8核CPU的)
2. Spark On YARN Client 和Cluster
Spark提交任务首先由客户端(CLient)生成一个Spark Driver,Spark Driver在YARN的NOdeManager中生成一个ApplicationMaster,ApplicationMaster向YARN Resourcemanager申请资源(这些资源就是NodeManager封装的Container,其中包含内存和cpu),接着Spark Driver调度并运行任务;那么Client和CLuster过程以下:
其中,左边是CLient模式,右边是Cluster模式,也就是说其实CLuster模式下,提交任务后,CLient能够离开了,而Client模式下,Client不能够离开;
另外,无论CLient或CLuster模式下,ApplicationMaster都会占用一个Container来运行;而Client模式下的Container默认有1G内存,1个cpu核,Cluster模式下则使用driver-memory和driver-cpu来指定;
可是这里有个问题,在Client模式下,这里的默认配置:
是512M的,可是参考博客里面说CDH里面这个默认是1G的(这里应该是1G的,否则的话,后面实验对应不到)
3. Spark On YARN资源申请
1. 用户经过executor-memory设置内存;
2. 通过spark.yarn.exeuctor.memoryOverhead的加持,申请的内存变为 executor-memory + max (384 , 0.1 * executor-memory) ;这里的384 和0.1(原文中这个值是0.07,这个须要注意)是参考下面的参数来的:
3. NodeManager在向上申请资源的时候会通过参数:
yarn.scheduler.minimum-allocation-mb // defalut 1G
yarn.scheduler.increment-allocation-mb // default 512M
的加持,向上取整为2中的倍数,而且最接近2中的数值。好比说--executor-memory是3G,那么2中的值就是3G+ max(384 , 0.1 *3 *1024) = 3G + 384m ~ 3.5G ,因此NodeManager申请的资源应该就是3.5G(3584m),而不是3456m(3*1024+384)。
另外:
executor-cores实际上是设置并行的个数的,因为HDFS的bug,executor-cores建议设置为5或如下;
实验及如何设置资源分配:
1. 问题解答:
那么,回到最开始的问题,6个节点(NodeManager),每一个64G内存,16核若是要使用尽量多的集群资源,怎么分配:
1. 首先,去掉节点系统使用1G内存1核cpu,那么还剩63G内存,15核cpu;
2. 加入executor-cpus设置为5,也就是建议值的最大,那么每一个节点能够分配3个Container ,即 15 /5= 3 个Executor;
3. 哪每一个executor内存呢? 63/3 = 21G 内存,21G - max(384 ,0.1 *21G) = 18.9G ; 那么executor-memory应该设置为多少呢?这个值应该是18.5G,为何是这个呢?
a. 第一,这个值须要是512M的倍数;
b,第二,xG + max(384m,0.1 * xG) < 21 G, 这个x 最大就是18.5G;
说道这里,须要说明一点,在参考的连接中参数0.1不是0.1,而是0.07,因此算的的executor-memory是19G,这个须要注意;
4. 那有多少个executor呢? 有人说这还很差算:6个节点 ,每一个节点3executor,因此一共是18个;这个不对;
由于须要有一个container来部署ApplicationMaster,因此有个节点其资源就会减小,这也就是说在ApplicationMaster所在的节点上最多只能有2个executor,因此最终的参数是:
由于这个参数不能识别小数点,因此不能写成18.5G(注意这个值和原文中是不同的,若是0.1参数在CDH集群中的默认值是0.07,那么就是原文的答案);
2. 5节点,6核cpu,6G内存怎么分配1
1. 去掉节点系统内存512M,1核cpu;还剩5核cpu,5.5G内存;
2. 若是每一个executor的executor-cpus设置为5,那么也就是说每一个节点有1个executor;
3. 这样子的话,executor-memory就应该设置为5G , 5G + max(384, 0.1 * 5G ) = 5.5G ~ 5.5G ,这样子分配刚恰好;
4. executor就应该设置为4 ,由于其中一个NodeManager分配了ApplicationMaster,那么其就不能生成一个executor了;
启动参数为:
spark-shell --master yarn --deploy-mode client --executor-memory 5G --executor-cores 4 --num-executors 4
5. 验证:
a. 首先看资源分配:
container个数5个?
这个怎么来的,明明申请了4个executor,每一个executor对应一个container,那就是4个container,怎么会多一个呢?其实这个就是启动ApplicationMaster的container;
cpu核有17个?
4*4 = 16 ,另一个固然就是启动ApplicationMaster的资源了;
内存23552m ?
4 *5 *1024 = 20480,这不对呀,还差好多呢,那实际是怎么计算的呢?实际的计算方式应该是:
4* (5G + max(384m , 0.1 * 5G )) * 1024 + 1024 = 23552 ; 其中,最后一个加的就是启动ApplicationMaster默认的1G内存;
b. 看日志:
看日志其实这个过程就更加清晰了;
首先,能够看到4个container;其次内存是5632m = (5G + 0.1 *5G )* 1024。
3. 5节点,6核cpu,6G内存怎么分配2
除了2中的分配方式,有没有其余分配方式呢?若是每一个executor-cpus是1呢?
1. executor-cpus=1 ; 那么每一个节点就能够分5个executor;
2. 因此每一个节点能够分 5.5G/ 5 = 1.1G ,因此最大只能1.1G,内存,并且NodeManager申请的资源只能是512M的整数倍,因此最大是1024M,那么executor-memory + max( 384, 0.1 * executor-memory) = 1024M ,那么executor-memory就等于640;
3. 有多少个executor呢? 4 * 5 = 20 ,运行ApplicationMaster节点的有多少个呢,去掉ApplicationMaster的资源1G内存,1cpu还剩4.5G内存,4cpu核,申请4个executor是能够的,因此一共就有 4* 5 + 4 = 24个container;
参数:
4. 验证:
4. 5节点,6核cpu,6G内存怎么分配3
除了二、3中的分配方式,有没有其余分配方式呢?若是每一个executor-cpus是2呢?
1. executor-cpus=2 ; 那么每一个节点就能够分2个executor(5/2 ~ 2 ,只能往低约等于);
2. 因此每一个节点能够分 5.5G/ 2 = 2.75G ,因此最大只能2.75G,内存,并且NodeManager申请的资源只能是512M的整数倍,因此最大是2.5G,那么executor-memory + max( 384, 0.1 * executor-memory) ~ 2.5G ,那么executor-memory就等于2176;
3. 有多少个executor呢? 4 * 2 = 8 ,运行ApplicationMaster节点的有多少个呢,去掉ApplicationMaster的资源1G内存,1cpu还剩4.5G内存,4cpu核,只能申请1个executor是能够的,因此一共就有 4* 2 + 1 = 9个container;
参数:
4. 验证:
5. 5节点,6核cpu,6G内存怎么分配4
可是,若是上一个分配中的第2中分配的内存是executor-memory + max( 384, 0.1 * executor-memory) ~ 2G, 那么executor-memory= 1664m;这个时候有多少个container呢?
运行ApplicationMaster的这时就能够运行2个executor了,因此一共有10个executor;
参数:
spark-shell --master yarn --deploy-mode client --executor-memory 1664m --executor-cores 2 --num-executors 10
验证: