YARN 资源利用率低本质是 “资源分配的灵活性” 和 “实际需求的多样性” 不匹配 —— 要么是 Container 太 “死板”要么是调度太 “保守”要么是应用太 “浪费”一、7 个核心原因拆解按影响程度排序1、资源分配粒度问题Container 是 “固定大小的盒子”容易浪费YARN 以 Container 为最小资源分配单位默认 1 核 CPU 2GB 内存且资源申请必须是「最小粒度的整数倍」无法按需精准分配只要申请的资源和实际需求不匹配必然产生浪费① 应用只需要 0.5 核 1GB 内存 → 必须申请 1 个 Container浪费 0.5 核 1GB② 应用需要 1.5 核 3GB 内存 → 必须申请 2 个 Container浪费 0.5 核 1GB。2、调度器策略的局限性“保守分配” 导致资源闲置YARN 有 3 种常用调度器各有各的 “浪费点”1Capacity Scheduler容量调度器生产最常用问题按队列 “硬隔离” 资源比如队列 A 分 50%队列 B 分 50%如果队列 A 空闲队列 B 即使资源不够也不能用例子队列 A 今天没任务50% 资源闲置队列 B 任务排队但只能用自己的 50%。2Fair Scheduler公平调度器问题为了 “公平”会给小应用预留资源导致大资源需求的应用等不到资源中间状态的资源闲置例子集群有 100 核10 个小应用各占 2 核共 20 核剩下 80 核但调度器为了 “公平”不给大应用分配导致 80 核闲置。3FIFO Scheduler先进先出问题大作业先跑占满所有资源小作业只能等资源利用率 “前高后低”例子一个大作业占满 100 核跑 1 小时后面 10 个小作业只能等 1 小时期间资源全被大作业占着但大作业可能没充分利用。3、应用资源请求不合理“多报少用” 是重灾区原因用户提交应用Spark/Flink/MapReduce时为了 “保险”盲目申请远超实际需求的资源导致资源被分配出去但完全没被使用这是生产环境最常见的浪费明明只需要 1GB 内存偏要申请 4GB明明只需要 10 个 Container偏要申请 50 个。4、节点资源碎片化“剩的资源用不上”原因YARN 的调度是「节点级调度」Container 的资源必须来自同一个节点不能跨节点凑资源随着 Container 的分配和释放再加上最小粒度的限制节点上的资源会变得 “碎片化”① 节点有 2 核 CPU 空闲但只有 1GB 内存不够 1 个 Container 的 2GB 要求② 或者有 3GB 内存空闲但只有 0.5 核 CPU不够 1 个 Container 的 1 核要求。结果这些 “碎片化” 的资源既分配不出去也无法被利用导致节点利用率低。5、静态资源配置“节点资源定死了不会动态调整”原因YARN 的 NodeManager 资源配置比如 yarn.nodemanager.resource.memory-mb、yarn.nodemanager.resource.cpu-vcores通常是静态的安装时配好之后不改节点实际有 16 核 CPU但只给 YARN 配了 8 核剩下 8 核闲置或者节点上还有 HDFS DataNode、HBase RegionServer 等服务和 YARN 抢资源导致 YARN 实际可用资源比配置的少。6、应用并行度不够“Task 太少Container 用不满”原因应用比如 Spark的并行度Task 数量太低导致无法充分利用集群的 Container集群有 100 个 Container 可用但 Spark 应用只有 10 个 Task只能用 10 个 Container剩下 90 个 Container 闲置。7、资源预留与调度开销“为了等大资源小资源也不用”原因YARN 调度器为了满足 “大资源需求的 Container”比如需要 8 核 16GB会预留部分资源导致这些资源在等待期间无法被小应用使用集群有 10 核空闲调度器为了等一个 8 核的 Container预留了 8 核剩下 2 核小应用也用不了结果 10 核全闲置。另外Container 的启动、销毁、调度也有开销短任务比如运行 10 秒的调度开销甚至比运行时间还长导致资源利用率低。