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