一、我们为什么要升级
360之前YARN版本是基于2.7版本修改的内部版本,主要有几个问题:
与社区脱节:目前社区已经发展到3.2的版本,落后社区多个大版本,很多新特性都不能使用,比如预定系统,Opportunistic Containers等
降本增效:在Yarn层面,支持多集群Federation,可以有效利用多YARN集群空闲资源,达到降本增效的目标。
定制化功能太多:由于YARN在我司发展时间比较长,有很多定制化的功能
调度性能瓶颈
二、挑战和目标
挑战
版本跨度大:版本从2.7到3.2,版本跨度比较大
客户端包多:mr,hive,hbase,flink,spark,hbox等作业都调度在YARN上
用户复杂度比较高:YARN的集群服务于360公司所有业务线如360搜索,手机卫士,360金融等
作业问题:classpath和配置依赖;MR,hive,ditcp作业高低版本共存导致作业失败,hbox作业接口不兼容,用户自己上传jar包
历史包袱:集群中还有很多corona用户,所以要兼容conrona参数、一些自定义的功能
集群环境复杂:系统版本,python版本,php版本,LANG编码问题等
图1- YARN升级面临的挑战
目标
对于业务完全透明,不影响现在正在跑的作业,同时不影响用户提交新的作业
兼容mr,hive,hbase,flink,spark等计算框架
支持滚动升级/回滚,让服务能够在3.2和2.7之间无差别回滚
YARN 的简单架构如下图所示
图2- YARN架构
三、升级梳理
重点功能梳理
我们前期从下图对YARN进行了重点功能的梳理,涉及134个功能,371个patch,进而来保证YARN升级工作的全面性和准确性,进而降低升级的风险,熟悉代码,预备升级出现的突发故障。
图3- YARN重点功能梳理
升级测试
测试主要过程
图4- YARN升级测试步骤
测试框架梳理
图5- YARN升级测试设计
主要功能测试
ResourceManager
重点功能梳理和测试,例如CapacitySchedule
调度器的使用:2.7.2的yarn使用的是FairScheduler,社区目前主要方向都在CapacityScheduler 。
我们也对CapacitySchedule重点功能做了梳理和针对性测试
表1- Cap和Fair重点功能对比
重点功能测试后续修改和注意
为了平滑使用新的调度器,针对我们的梳理的结果和我司使用调度器的一些习惯,我们做了以下工作:
自动化转换脚本:写了队列转换脚本,可以一键让FairScheduler转换成CapacityScheduler
标签调度问题:①:兼容问题:2.7x的label是我司自己加的,我们对此3.0做了平滑升级的兼容工作。
②:独占和非独占之间转换的问题:比如YARN3.0的调度器不支持把独占标签改成非独占,2.7 的DEFAULT_LABEL和3.2的空标签等
③:标签堵塞:指定标签的时候容易触发
* 队列映射:2.7如果用户不指定队列就会提到default队列,但是3.0如果不指定,%user:%user没有的话就会作业就会提交失败
回滚测试:升级可以平滑从2.7升到3.2,也可以从3.2升到2.7,社区自己做了处理
CapacityScheduler新增限制:用户AM限制和userLimit的限制,最大资源限制的计算,我们对这块都做了修改
resultful接口展示的数据问题
GPU等其它资源计算存在问题
队列最大资源保证:我司的情况是默认标签一般是空标签,它可以使用非独占标签的资源,对于集群比较紧张的队列,队列最大资源保障就不合理
RM日志过大
ResourceManager回归测试
性能测试
用SSL对FairScheduler和CapacityScheduler做了性能测试。
测试用例:
①:不开多线程+开multAsigned
②:测试用例多线程+线程数5
③: 不开多线程+不开多次分配
测试结果:
①:不开多线程调度, Hadoop3.2 capacity调度container的吞吐能力 要比 hadoop2.7-fair scahduler要好
②:开多线程调度, Hadoop3.2 capacity调度container的吞吐能力 要比 hadoop2.7-fair scahduler要好
NM的测试
①:支持灰度升级(升级测试的时候就按照5%,10%,50%,100%)
②:升级可以平滑从2.7升到3.2,也可以从3.2降到2.7,修改了2.7recover逻辑
③:我司加的一些旧功能:使用客户端的配置下载资源、动态控制作业并发、inode清理等功能合并到NM3.0上
④:NM压测
客户端测试
客户端这次保持版本2.7x,原因如下
①:由于TaskUmbilicalProtocol协议接口存在兼容性问题,该接口是Map/Reduce子任务和MRAppMaster进程的通信接口,该通信接口的协议基于Writable实现,在滚动升级NM期间,MR的任务在3.2.1版本和27.x版本之间通信时存在兼容性问题。如果从服务端做兼容需要进行一次集群升级,而且存在不可控风险,我们最终通过修改Hadoop 2.7.x客户端来保证MR任务classpath在集群中的一致性来解决该问题。
②:hive作业在我们占的比重也比较大,因为我司的hive还在1.2的版本,不支持hadoop3.x,spark sql又会访问hive的metastore
各大计算框架测试
①:建立升级测试用例库(ps:感谢各大计算组建的支持和配合)
②:在上图2- YARN升级测试设计集群环境下分别测试
四、升级方案
升级架构
集群选择的升级架构如下图所示,客户端为低版本,集群版本为高版本
图6- YARN升级测试设计
升级步骤
升级方案经历过我们团队反复实验和验证,得到以下比较合理的升级方案:
图7- YARN升级步骤
详细步骤:
升级前都会按照线上集群搭建测试集群,跑我们准备的测试脚本
升级前准备好:集群队列监控,集群资源监控,重点作业监控,对2.7和3.2的接口做好测试,备份日志,对每分钟Failed作业加报警
升级客户端配置
备份Hadoop2.7的标签到临时目录
升级Hadoop3.2的ResourceManager,同时保存Hadoop2.7,在升级出现问题的时候可以马上切回2.7
升级hadoop3.2history,兼容2.7的history
观察集群一周(根据升级集群数量决定,我们升级第一个集群等待时间比较长),同时观察集群container的吞吐率和作业运行快慢。
在升级RM的一周内,同时建立一个测试标签,让重点用户可以测试,可以发现一些我们在测试用例库中没有测试到的地方
升级计算节点,我们是灰度升级NM。
按照5%->10%->30%->70%->100%对NM
升级的时候按照标签升,如果确实有作业在3.0上确实有问题,但是问题涉及用户数不多,这个时候 可以让用户指定没有升级的标签跑,这样可以给开发人员预留一些时间去排查问题
升级完成之后观察集群,统计集群升级前后的效率
五、升级遇到的问题和解决
1. ResourceManager升级遇到的问题
ResourceManager由两个关键组件Scheduler和ApplicationsManager组成。这次升级主要是把调度器FairScheduler转换到CapacityScheduler,平滑过度,需要考虑的一些比较主要的问题
图8- ResourceManager升级
问题1:RM由于ParentQueue TimSort排序异常异常挂掉
具体报错
java.lang.IllegalArgumentException: Comparison method violates its general contract!
问题解决
①:社区目前还没有出解决思路,不过可以参考patch:YARN-8737和YARN-10058
②:目前的解决方案:-Djava.util.Arrays.useLegacyMergeSort=true把这个参数加在RM的启动参数,测试了一些性能,对RM性能没有产生比较大的影响,所以我们先用此方案解决
问题2:用户指定标签并且持续调度资源造成标签堵塞问题
具体表现
夜间标签调度资源的时候就会一直优先给指定标签的,该标签下其它队列调度不到,资源闲置
问题解决
修改代码逻辑,用户指定标签跳出选择队列的逻辑,具体的patch整里好会提交到社区
问题3:最大资源资源保证
具体表现
CapacityScheduler最大资源控制和FairScheduler最大资源控制不一样,造成高峰期资源紧张。
原因:CapacityScheduler的最大资源保证分为:
①:在进行RESPECTPARTITIONEXCLUSIVITY分配时,我们将尊重队列的最大容量。
②:在进行IGNOREPARTITIONEXCLUSIVITY分配时,我们将不遵守队列的最大容量,该分区上队列的最大容量将被视为100%。哪个队列可以使用分区中的所有资源。
设计的缺点
对于集群资源比较紧张的集群就会出现重要作业的资源被抢占,任务不能正常跑出来
设计的优点
对于非排他性分配,我们确保分区上有空闲资源,以避免浪费,这种资源将得到最大程度的利用,抢占策略将在partitoned-resource-request返回时将其取回
问题解决
修改代码逻辑,增加队列最大资源上限的控制,同时增加开关,对于资源不紧张的集群可以放开,这样可以增加集群的资源利用率。
问题4:RM作业调度优先级的问题
具体表现
如果不配,集群最大priority默认是0,用户作业指定优先级无效
问题解决
<property>
<name>yarn.cluster.max‐application‐priority</name>
<value>5</value>
</property>
2. NM升级遇到的问题
NodeManager管理YARN集群中的每个节点。NodeManager提供针对集群中的每个节点的服务,从监督一个容器的一生和节点健康,在升级的时候,遇到下面几个需要提前注意的的问题
图9- ResourceManager升级
问题1:NM回滚2.7版本异常
具体报错
NM中的状态数据以ProtocolBuffer的形式存储到本地的LevelDB中的,3.2.1新增了很多信息,但是在ProtocolBuffer层面也做了兼容。不过由于3.2.1版本NM新增的状态信息,在回滚到2.7.x时会出现NM不识别的key
问题解决
方案一:修改hadoop2.7的代码,让它增加3.2.1版本NM新增的状态信息,升级hadoop2.7.x
方案二:修改hadoop2.7的代码,使3.2.1版本NM新增的状态信息加开关先关闭,等NM全部升级完在打开
我们选择了方案一,一是尽量不再3.2的代码上反复的修改,二我们使用的是我们经过大量的测试和灰度升级,出现问题解决不了必须要回滚的概率尽量已经控制到最低
问题2:MR RPC协议修改导致作业执行异常
具体报错
图9- RPC协议修改导致作业执行异常
问题解决
在客户端控制MR单个作业的class path保持一致
问题3:distcp 作业在2.7和3.2版本报错
ditcp必须要保持版一致
具体报错
图10- RPC协议修改导致作业执行异常
问题解决
和mr的解决办法一样客户端控制ditcp单个作业的class path保持一致
问题4:recover恢复异常
具体原因
新版本的recvoer在NM注销的时候多加了一个参数,默认yarn.nodemanager.recovery.supervised=false,NM停止注销的同时,NM本地的进程任务也被停掉,recover恢复失败
问题解决
在升级的时候需要增加参数
<property>
<name>yarn.nodemanager.recovery.supervised</name>
<value>true<value>
</property>
问题5:Cgroup计算NM核数和2.7有区别,会造成作业变慢
具体原因
NM 会按照机器总的 CPU num* limit-percent 来计算 NM 总体可用的实际 CPU 资源,然后根据 NM 配置的 Vcore 数量来计算每个 Vcore 对应的实际 CPU 资源,再乘以 container 申请的 Vcore 数量计算 container 的实际可用的 CPU 资源。这里需要注意的是,在计算总体可用的 CPU 核数时,NM 默认使用的实际的物理核数,而一个物理核通常会对应多个逻辑核(单核多线程),而且我们默认的 CPU 核数通常都是逻辑核
问题解决
修改配置
<property>
<name>yarn.nodemanager.resource.count-logical-processors-as-cores</name>
<value>true<value>
</property>
3. history升级遇到的问题
具体问题
升级之后history log路径问题,会让我们在滚动升级中看不到日志
问题解决
在3.0的基础上做了兼容,加了开关,等全部升上去之后再把开关置成false
六:升级的喜
Resource Manager升级:
目前我司的大大小小的集群主节点基本都已经升级YARN3.0,升级之后的调度调度效率比之前提升30%左右,资源利用率提高15%左右
NodeManager升级阶段:
目前我们已经完成一个4000节点,一个5000节点集群的NM的升级,还有数10个小集群的升级
MR 更快的执行速度,shuffle类的作业,性能大概提升15%到30%
跟进社区新版本,新功能可以陆陆续续投入使用
评论区