YARN 在字节跳动的优化与实践( 二 )


我们为提升单集群规模做了一系列的优化 。

  • 首先 , 通过对 YARN 内部事件梳理调整 , 精准的修改了一些事件处理逻辑 。
  • 然后 , 将 NodeManager 节点的心跳机制改为根据 ResourceManager 的压力动态调整 。
  • 之后 , 修改内存单位(int->long)突破单个集群 21 亿 MB 的限制
  • 再之后 , 通过对切主过程进行深度优化, 将切主时间控制在秒级
当然还有很多其它的细节优化不再一一列举 , 最终的效果是让单个生产集群达到了 2 万节点的规模 。
2.1.4 与流式&在线服务混部 
YARN 在字节跳动的优化与实践

文章插图
 
公司内离线的资源全天都比较紧张 , 而流式作业和在线服务的资源使用量随着用户的行为 , 在时间上有明显的波峰波谷 , 在凌晨时通过混部的方式将流式和在线富余的资源提供给离线可以全面的提升利用率 。
我们通过将 NodeManager 改造为可以根据宿主机的富余资源动态的调整的 NM' , 来达到与流式作业和在线服务的混部 , 为离线提供更多资源的目的 。
目前生产环境中已有数万台节点进行了混部 , 混部后将原机器的 CPU 利用率绝对值提升了 20%以上 。
2.1.5 Smart Resource : 在运行时/重启时调整资源
YARN 在字节跳动的优化与实践

文章插图
 
原生的 YARN 中 , 用户申请的资源和实际使用的资源经常会出现比较大的偏差, 导致出现大量的资源浪费的情况 , 为此我们开发了一整套的资源动态调整方案 , 可以将申请的资源调整到接近于实际使用资源的数值 。
并且 , 在实际使用中发现 , 如果资源调整必须以一个核为最小粒度的话 , 还是会出现很严重的浪费 , 比如用户真实的需求可能是 0.001 个核*1000 , 原生的 YARN 只能分配 1000 个核 , 就白白浪费了 999 个核 。我们开发了以千分之一核为最小粒度的功能 , 可以有效的减少资源的浪费 。并且千分之一核与资源动态调整结合 , 可以更加精细化的调整资源 。
2.2 多种负载场景优化字节跳动的 YARN 承载了公司内的 批处理 / 流式 / 模型训练 三大场景 , 由于 YARN 天生是为批处理而设计的 , 很多地方与流式 / 模型训练场景并不匹配 , 为了给这些场景更好的体验 , 需要做一些定制工作 。
2.2.1 YARN Gang Scheduler 调度器
YARN 在字节跳动的优化与实践

文章插图
 
流式作业和训练作业的调度需求与批处理有很大的不同:批处理强调的是高吞吐 , 而流式/训练类型的作业更加强调低延迟和全局视角 。为了弥补原生 YARN 在低延迟和全局视角上的缺陷 , 我们开发了一个全新的调度器 Gang Scheduler 。
Gang Scheduler 提供了一个 All-or-Nothing (一次全交付或不交付)的语义 , 如作业申请 1000 个 container , 那么要么直接返回 1000 个 container , 要么就返回失败 , 并提示失败的原因 。这样可以有效的避免两个作业都只拿到一半的资源 , 谁也无法启动的互锁局面 。
除此之外 , Gang Scheduler 还有个特性是超低延迟 ,  它可以在毫秒级给出 All-or-Nothing 的结论 , 这样可以大大缓解流式作业在重启时的 lag 积压问题 。
最重要的是 , Gang Scheduler 为流式作业和训练作业提供了全局视角 , 每个作业可以通过配置自己定制的强约束和弱约束来达到全局最优的放置策略 。其中 , 强约束是指必须要满足的条件;弱约束是指尽量满足 , 但确实无法满足时可以接受降级的约束 。目前支持的强约束包括节点属性, 高负载等;支持的弱约束包括:节点属性 , 高负载 , Container 打散 , Quota 平均 , GPU 亲和性等 。
2.2.2 更加精细化的 CPU 使用策略
YARN 在字节跳动的优化与实践

文章插图
 
除了开启 YANR 原生默认支持的 CGroup 限制之外 , 我们还配置了更加丰富的 CGroup 管理策略 , 比如在 share 模式下支持自定义的最大值限制 , 支持绑核 , 支持绑 NUMA 节点等. 通过这些措施 , 给流式作业和训练作业更加灵活的管控策略 , 满足不同场景下的隔离或共享需求 。


推荐阅读