Spark On YARN內存和CPU分配

 

Spark On YARN內存和CPU分配

問題描述:

在使用Spark On YARN時(不管是Client模式或者是Cluster模式,固然下面會有這種模式的對比區別),能夠添加諸如:
--executor-memory 8G --executor-cores 5 --num-executors 20
等等這樣的參數,可是這個和咱們日常理解的感受有誤,或者說不直觀,怎麼說呢?
好比一個6節點(NodeManager)的集羣,每一個節點配置爲:16 CPU核,64G內存,那麼通常很容易提交代碼的時候寫成以下配置:
 
--num-executors 6 --executor-cores 15 --executor-memory 63G
可是這樣配置後,你會發現,在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,因此最終的參數是:
--num-executors 17 --executor-cores 5 --executor-memory 18944m
由於這個參數不能識別小數點,因此不能寫成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;
參數:
spark-shell --master yarn  --deploy-mode client --executor-memory 640m --executor-cores 2 --num-executors 24   

 

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;
參數:
spark-shell --master yarn  --deploy-mode client --executor-memory 2176m --executor-cores 2 --num-executors 9

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

  

驗證:
 
 
 
 
相關文章
相關標籤/搜索