Hadoop YARN Cgroups 資源隔離講解,你學(xué)會(huì)了嗎?
一、概述
Hadoop YARN (Yet Another Resource Negotiator)使用 Cgroups(Control Groups)來(lái)進(jìn)行資源管理和隔離。Cgroups 是 Linux 內(nèi)核提供的一種機(jī)制,用于限制、賬戶和隔離進(jìn)程組(process groups)的資源(例如 CPU、內(nèi)存、磁盤(pán) I/O 等)。
以下是 Hadoop YARN Cgroups 的主要講解:
- 資源隔離和管理:Cgroups 允許將進(jìn)程組織成層次結(jié)構(gòu),每個(gè)層次結(jié)構(gòu)都可以分配特定的資源配額。在 Hadoop YARN 中,每個(gè)應(yīng)用程序或容器都可以被放置在一個(gè)獨(dú)立的 Cgroup 中,以確保資源隔離和管理。
- 支持的資源:YARN Cgroups 主要用于限制和管理以下資源:
CPU: 限制每個(gè)容器可以使用的 CPU 資源。
內(nèi)存: 限制每個(gè)容器可以使用的內(nèi)存資源。
磁盤(pán) I/O: 限制每個(gè)容器可以使用的磁盤(pán) I/O 資源。
- Cgroups 配置:在 YARN 中,Cgroups 的配置信息通常在 yarn-site.xml 文件中指定。配置項(xiàng)包括:
yarn.nodemanager.linux-container-executor.cgroups.hierarchy: Cgroups 層次結(jié)構(gòu)的名稱。
yarn.nodemanager.linux-container-executor.cgroups.mount: 是否掛載 Cgroups。
Cgroups 的使用場(chǎng)景:
資源隔離: Cgroups 允許將任務(wù)或容器隔離在一個(gè)獨(dú)立的環(huán)境中,防止它們互相干擾。
資源配額: 可以為每個(gè)任務(wù)或容器設(shè)置資源配額,防止其使用過(guò)多的 CPU、內(nèi)存等資源。
任務(wù)優(yōu)先級(jí): 通過(guò)調(diào)整 Cgroups 中的資源限制,可以為不同的任務(wù)分配不同的優(yōu)先級(jí)。
YARN 中的 Cgroups 實(shí)現(xiàn):YARN 使用 Linux Container Executor(LCE)來(lái)實(shí)現(xiàn)容器的隔離和資源管理。LCE 負(fù)責(zé)為每個(gè)容器創(chuàng)建 Cgroup 并進(jìn)行資源的配置。
注意事項(xiàng)和配置建議:
配置 Cgroups 時(shí)需要確保系統(tǒng)啟用了 Cgroups 功能,且相應(yīng)的內(nèi)核模塊已加載。
可以根據(jù)實(shí)際需求配置 Cgroups 的層次結(jié)構(gòu)和資源限制。
官方文檔:https://hadoop.apache.org/docs/current/hadoop-yarn/hadoop-yarn-site/NodeManagerCgroups.html
圖片
二、Hadoop 環(huán)境準(zhǔn)備
可以選擇物理部署,如果只是測(cè)試的話,也可以選擇容器部署,這里為了快速測(cè)試就選擇容器部署了。物理部署和容器部署教程如下:
- 大數(shù)據(jù)Hadoop原理介紹+安裝+實(shí)戰(zhàn)操作(HDFS+YARN+MapReduce)
- 大數(shù)據(jù)Hadoop之——數(shù)據(jù)倉(cāng)庫(kù)Hive
- 大數(shù)據(jù)Hadoop之——計(jì)算引擎Spark
- 通過(guò) docker-compose 快速部署 Hive 詳細(xì)教程
三、內(nèi)存資源限制
Hadoop 3.x 里 YARN 的內(nèi)存限制策略有三種:
- 無(wú)限制:無(wú)限制模式不會(huì)限制 container 內(nèi)存的使用,該模式下集群的資源利用率高。但是遇到一些不太守規(guī)矩的用戶,會(huì)出現(xiàn)申請(qǐng)很少內(nèi)存但是占用很多的作業(yè),這種作業(yè)會(huì)嚴(yán)重影響到集群的穩(wěn)定性,如果沒(méi)有持續(xù)運(yùn)營(yíng),會(huì)導(dǎo)致集群在某些階段面臨很?chē)?yán)重的穩(wěn)定性風(fēng)險(xiǎn)。
- 嚴(yán)格限制:嚴(yán)格模式會(huì)限制進(jìn)程實(shí)際使用的內(nèi)存,并將實(shí)際使用內(nèi)存超過(guò)申請(qǐng)內(nèi)存的作業(yè)殺掉。在 Java 的計(jì)算任務(wù)中,其實(shí)存在大量非堆內(nèi)存使用,很難在作業(yè)提交前預(yù)測(cè)出作業(yè)實(shí)際的內(nèi)存占用情況。因此嚴(yán)格模式會(huì)導(dǎo)致很多任務(wù)出現(xiàn) OOM 被 kill 的情況,對(duì)于平臺(tái)方來(lái)說(shuō)會(huì)有比較高的 oncall 成本,對(duì)用戶需要了解底層的一些細(xì)節(jié),并且不斷調(diào)整作業(yè)的內(nèi)存配置。好處也比較明顯,整個(gè)集群作業(yè)的資源使用收到嚴(yán)格限制,作業(yè)和作業(yè)時(shí)間的隔離相對(duì)比較徹底,因此整個(gè)集群的穩(wěn)定性有非常好的保障。嚴(yán)格模式下有兩種實(shí)現(xiàn)方式:
基于 poll 模式, NodeManager 內(nèi)部會(huì)有一個(gè) MonitorThread 定時(shí)檢查每個(gè) container 的內(nèi)存使用(rss)是否超過(guò)了申請(qǐng)的內(nèi)存,并將超過(guò)內(nèi)存的 container 殺掉,在 ResourceManager 中能看到 Task 被 kill 的原因。這個(gè)策略有個(gè)小問(wèn)題是檢測(cè)有間隔,如果一個(gè) container 短時(shí)間內(nèi)大量申請(qǐng)內(nèi)存,還是會(huì)有一點(diǎn)風(fēng)險(xiǎn)。另外一個(gè)問(wèn)題就是,這個(gè)策略無(wú)法限制 CPU 的使用。
另外一種就是基于 Linux 的 CGroups 機(jī)制去限制每個(gè) Container 的內(nèi)存使用。CGroups 也是 Docker 限制進(jìn)程資源的核心機(jī)制,不過(guò)在 YARN 中,是由 NodeManager 來(lái)完成 CGroups 策略的創(chuàng)建和銷毀。Cgroups 的機(jī)制相比 MonitorThread 比,借助了操作系統(tǒng)原生的資源隔離機(jī)制,可以同時(shí)支持 CPU 和內(nèi)存、網(wǎng)絡(luò)的限制。
整個(gè)嚴(yán)格模式的通病就是:如果內(nèi)存限制太嚴(yán)格,會(huì)導(dǎo)致任務(wù)容易掛掉,會(huì)有大量的溝通成本;CPU 限制太嚴(yán)格,任務(wù)的計(jì)算性能不佳,同時(shí)集群的資源利用率會(huì)低。
- 彈性內(nèi)存控制:彈性模式的主要思路是將 NodeManager 和他管理的 container 看作一個(gè)整體,通過(guò) CGroups 進(jìn)行隔離。允許某些 container 使用超過(guò)自己申請(qǐng)的資源,同時(shí)如果整體資源超過(guò)了閾值,就啟動(dòng)嚴(yán)格的限制策略進(jìn)行驅(qū)逐。
【注意】Hadoop 2.x 時(shí)還不支持 CGroup,內(nèi)存限制主要基于 poll 的線程來(lái)限制,如果遇到 NodeManager 短時(shí)間分配大量?jī)?nèi)存,會(huì)導(dǎo)致內(nèi)存限制策略失效,進(jìn)而引發(fā)內(nèi)存問(wèn)題。
彈性模式的配置如下:
<!-- 關(guān)閉嚴(yán)格模式 -->
<property>
<name>yarn.nodemanager.resource.memory.enforced</name>
<value>false</value>
</property>
<!-- 開(kāi)啟 CGroup 內(nèi)存資源限制 -->
<property>
<name>yarn.nodemanager.resource.memory.enabled</name>
<value>true</value>
</property>
<!-- 彈性內(nèi)存 -->
<property>
<name>yarn.nodemanager.elastic-memory-control.enabled</name>
<value>true</value>
</property>
<!-- 開(kāi)啟物理內(nèi)存檢查 -->
<property>
<name>yarn.nodemanager.pmem-check-enabled</name>
<value>true</value>
</property>
<!--cancel check of physical and virtural memory allocation-->
<property>
<name>yarn.nodemanager.vmem-check-enabled</name>
<value>false</value>
</property>
<!-- Using Cgroup -->
<property>
<name>yarn.nodemanager.linux-container-executor.resources-handler.class</name>
<value>org.apache.hadoop.yarn.server.nodemanager.util.CgroupsLCEResourcesHandler</value>
</property>
<!-- CPU 資源限制 -->
<property>
<name>yarn.nodemanager.resource.percentage-physical-cpu-limit</name>
<value>90</value>
</property>
但是內(nèi)存一般通過(guò)設(shè)置yarn.nodemanager.resource.memory-mb 參數(shù)即可控制NM節(jié)點(diǎn)的內(nèi)存使用上限。主要是CPU的限制,接下來(lái)就細(xì)講CPU資源限制。
四、CPU 資源限制
CGroups 是一種將任務(wù)及其子任務(wù)聚集和劃分進(jìn)一個(gè)垂直的分組的策略,并提供在此結(jié)構(gòu)上的特別的操作。CGroups 是 Linux 內(nèi)核功能,自內(nèi)核版本 2.6.24 被引入。從 Yarn 角度,該功能使得限額容器的資源使用成為可能。一個(gè)示例是 CPU 使用,如果沒(méi)有 CGroups,限制容器的 CPU 使用非常困難。
官方文檔:https://hadoop.apache.org/docs/current/hadoop-yarn/hadoop-yarn-site/NodeManagerCgroups.html
前期準(zhǔn)備工作:
###1、 分配可執(zhí)行文件權(quán)限
chown root:hadoop /opt/apache/hadoop/bin/container-executor
# 該配置文件權(quán)限特殊,得設(shè)置6050權(quán)限
chmod 6050 /opt/apache/hadoop/bin/container-executor
### 2、配置 container-executor.cfg
vi /opt/apache/hadoop/etc/hadoop/container-executor.cfg
yarn.nodemanager.local-dirs=/hadoop/yarn/local
yarn.nodemanager.log-dirs=/hadoop/yarn/log
yarn.nodemanager.linux-container-executor.group=hadoop
banned.users=hdfs,yarn,mapred,bin
min.user.id=1000
1)啟用 LCE
在 Nodemanager 中, CGroup 功能集成在 LinuxContainerExecutor中,所以要使用 CGroup 功能,必須設(shè)置 container-executor 為 LinuxContainerExecutor. 同時(shí)需要配置 NM 的 Unix Group,這個(gè)是可執(zhí)行的二進(jìn)制文件 container-executor 用來(lái)做安全驗(yàn)證的,需要與 container-executor.cfg 里面配置的一致。
<property>
<name>yarn.nodemanager.container-executor.class</name>
<value>org.apache.hadoop.yarn.server.nodemanager.LinuxContainerExecutor<value>
</property>
<property>
<name>yarn.nodemanager.linux-container-executor.group</name>
<value>hadoop<value>
</property>
2)啟用 CGroup
LinuxContainerExecutor 并不會(huì)強(qiáng)制開(kāi)啟 CGroup 功能, 如果想要開(kāi)啟 CGroup 功能,必須設(shè)置 resource-handler-class 為 CGroupsLCEResourceHandler.
<property>
<name>yarn.nodemanager.linux-container-executor.resources-handler.class</name>
<value>org.apache.hadoop.yarn.server.nodemanager.util.CgroupsLCEResourcesHandler<value>
</property>
3)配置 Yarn CGroup 目錄
NM 通過(guò) yarn.nodemanager.linux-container-executor.cgroups.hierarchy 配置所有 Yarn Containers 進(jìn)程放置的 CGroup 目錄。
- 如果系統(tǒng)的 CGroup 未掛載和配置,可以在系統(tǒng)上手動(dòng)掛載和配置和啟用 CGroup 功能,也可以通過(guò)設(shè)置yarn.nodemanager.linux-container-executor.cgroups.mount 為 true,同時(shí)設(shè)置 CGroup 掛載路徑 yarn.nodemanager.linux-container-executor.cgroups.mount-path 來(lái)實(shí)現(xiàn) NM 自動(dòng)掛載 CGroup (不建議這樣用,問(wèn)題挺多)。
- 如果系統(tǒng)的 CGroup 已經(jīng)掛載且配置完成,而且 Yarn 用戶有 CGroup cpu 子目錄的寫(xiě)入權(quán)限,NM 會(huì)在 cpu 目錄下創(chuàng)建 hadoop-yarn 目錄 ,如果該目錄已經(jīng)存在,保證 yarn 用戶有寫(xiě)入權(quán)限即可。
<property>
<name>yarn.nodemanager.linux-container-executor.cgroups.hierarchy</name>
<value>/hadoop-yarn<value>
</property>
<property>
<name>yarn.nodemanager.linux-container-executor.cgroups.mount</name>
<value>false<value>
</property>
<property>
<name>yarn.nodemanager.linux-container-executor.cgroups.mount-path</name>
<value>/sys/fs/cgroup<value>
</property>
提前創(chuàng)建目錄
mkdir /sys/fs/cgroup/hadoop-yarn
# 需要給hadoop用戶有執(zhí)行權(quán)限即可
chown -R hadoop:haodop /sys/fs/cgroup/hadoop-yarn
3)CPU 資源限制
NM 主要使用兩個(gè)參數(shù)來(lái)限制 containers CPU 資源使用。
- 首先,使用 yarn.nodemanager.resource.percentage-physical-cpu-limit 來(lái)設(shè)置所有 containers 的總的 CPU 使用率占用總的 CPU 資源的百分比。比如設(shè)置為 60,則所有的 containers 的 CPU 使用總和在任何情況下都不會(huì)超過(guò)機(jī)器總體 CPU 資源的 60 %。
- 然后,使用 yarn.nodemanager.linux-container-executor.cgroups.strict-resource-usage 設(shè)置是否對(duì) container 的 CPU 使用進(jìn)行嚴(yán)格限制。
如果設(shè)置為 true ,即便 NM 的 CPU 資源比較空閑, containers CPU 使用率也不能超過(guò)限制,這種配置下,可以嚴(yán)格限制 CPU 使用,保證每個(gè) container 只能使用自己分配到的 CPU 資源。
但是如果設(shè)置為 false ,container 可以在 NM 有空閑 CPU 資源時(shí),超額使用 CPU,這種模式下,可以保證 NM 總體 CPU 使用率比較高,提升集群的計(jì)算性能和吞吐量,所以建議使用非嚴(yán)格的限制方式(實(shí)際通過(guò) CGroup 的 cpu share 功能實(shí)現(xiàn))。不論這個(gè)值怎么設(shè)置,所有 containers 總的 CPU 使用率都不會(huì)超過(guò) cpu-limit 設(shè)置的值。
- NM 會(huì)按照機(jī)器總的 CPU num* limit-percent 來(lái)計(jì)算 NM 總體可用的實(shí)際 CPU 資源,然后根據(jù) NM 配置的 Vcore 數(shù)量來(lái)計(jì)算每個(gè) Vcore 對(duì)應(yīng)的實(shí)際 CPU 資源,再乘以 container 申請(qǐng)的 Vcore 數(shù)量計(jì)算 container 的實(shí)際可用的 CPU 資源。這里需要注意的是,在計(jì)算總體可用的 CPU 核數(shù)時(shí),NM 默認(rèn)使用的實(shí)際的物理核數(shù),而一個(gè)物理核通常會(huì)對(duì)應(yīng)多個(gè)邏輯核(單核多線程),而且我們默認(rèn)的 CPU 核數(shù)通常都是邏輯核,所以我們需要設(shè)置 yarn.nodemanager.resource.count-logical-processors-as-cores 為 true 來(lái)指定使用邏輯核來(lái)計(jì)算 CPU 資源。
<property>
<name>yarn.nodemanager.resource.percentage-physical-cpu-limit</name>
<value>80<value>
</property>
<property>
<name>yarn.nodemanager.linux-container-executor.cgroups.strict-resource-usage</name>
<value>false<value>
</property>
<property>
<name>yarn.nodemanager.resource.count-logical-processors-as-cores</name>
<value>true<value>
</property>
【注意】Linux 內(nèi)核版本 3.10.0-327.el7.x86_64 上 Yarn 啟用 CGroup 功能后,會(huì)觸發(fā)內(nèi)核 BUG,導(dǎo)致內(nèi)核卡死,重啟,NM 掛掉,所有運(yùn)行的任務(wù)失敗。所以如果需要啟用 CGroup 功能,絕對(duì)不能使用 3.10.0-327.el7.x86_64 版本內(nèi)核。親測(cè)升級(jí)內(nèi)核版本可解決該問(wèn)題。