03
Yarn扩展性与其他优化
接下来介绍 Hadoop Yarn 扩展性方面的一些实践,以及使用过程中的其他一些优化。
1. 扩展性
目前小米 Yarn 集群存在两个隐患:
- 如何适配新的机房,如何对外屏蔽新机房的存在以及减少两个机房之间的专线带宽;
- 单集群因规模较大面临稳定性及扩展性的问题,急需扩展性的方案。
通过对社区实现方式以及业界常见的一些优化手段的调研,以及小米内部更倾向于更靠近社区,所以决定落地 Yarn Federation 架构。
Yarn Federation在小米内部的架构如上图所示,小米内部有一个资源运维平台叫做资源管理服务,通过资源管理服务去做 Federation 规则的管理。目前落地模式是单队列单集群的模式。GPG模块的引入主要是做 zk 中大量 app 数据的清理工作,因为Router在进行app转发的时候要记录app对应的subcluster信息,会导致zookeeper中存在大量的数据,但目前Router是不具备清理功能的,所以需要一个外部的组件去进行清理,所以从社区中引入 GPG 模块实现该需求,当然 GPG 还有更丰富的功能,不过当前内部还未采用。
Federation 架构引入之初的一个目标是对外屏蔽子集群的概念,该需求在 federation 基于 router 转发已经默认支持,另一个需求是如何减少多机房之间的流量带宽,尽可能降低跨机房的数据访问要求。当前内部会基于数据血缘分析,将分析出数据孤岛所对应的链路扔到扩展的 subcluster 去进行运行,达到流量收敛的目的。
接下来介绍一下上面刚刚提到的资源运维平台,即资源管理服务。
资源管理服务是小米内部Yarn运维管理平台,用户可以自助进行队列的增删该查,权限以及队列属性修改等等功能。因为有些队列可能申请过后使用率比较低,所以资源管理服务也会定时的对队列资源进行治理。对于Federation,资源管理服务提供了一个规则配置页面,提交之后会生成一个规则,由管理员进行审批,审批过后,整个规则会写入到zookeeper当中,Router加载zookeeper中的配置,最终这条规则就落地生效了。
在落地Federation架构的过程中,我们遇到了如下问题:
下面介绍一下其中的AM Invalid Token问题。
在内部通过原地升级到Federation架构时遇到一个Invalid Token的问题,造成该问题的原因是因为ResourceManager去NodeManger拉起ApplicationMaster的时候,如果AMRMProxy开启的状态下,会将ApplicationMaster的token换成一个local token,然后ApplicationMaster通过local token与AMRMProxy进行通信,然后AMRMProxy去代理ApplicatonMaster原来的token去和ResourceManger进行通信。由于滚动部署NodeManager与灰度Client不能同时生效,就会造成ApplicationMaster拿着local token直接与ResourceManger进行通信,最终导致Invalid Token,进而导致作业的失败。
针对这种情况,目前内部的解决方案是在拉起ApplicaitonMaster的时候通过环境变量决定AMRMProxy是否替换Token,如果环境变量开启,AMRMProxy才会进行token的替换,如果环境变量未开启,即使AMRMProxy开启,也不会进行token的替换,这样ApplicationMaster会直接通过原来token与ResourceManager进行通信。之后等NodeManager更新完成并开启 AMRMProxy之后,通过将Client的 scheduler.address配置以及环境变量打开完成请求的转发。
2. 其他优化 - RM App State To MySQL
ResouceManger内部会缓存很多已经结束的app,主要是为了提供给业务通过访问Yarn Web UI去获取已结束作业的执行数据,进行问题定位。但是如果ResourceManger缓存大量的已结束的app,会导致内存压力特别大,特别在进行高可用切换时耗时非常长。另外即使ResourceManager缓存大量的已结束的app的数据,也解决不了结束时间较久的作业的数据的访问。
针对这种情况,目前小米内部在app finish时通过state store去写zookeeper的时候同时也会全量写一份数据到mysql,这样当用户通过Yarn UI去访问已经结束的app 数据,如果内存中没有,就会去mysql加载该app的数据,并且内部会模拟recover的流程去恢复当时app的数据,这样业务无论访问过期多久的app都可以访问到,同时也解决了ResourceManager内存的压力问题 。
3. 其他优化
在运维集群的过程中,会遇到用户希望知道container中作业运行慢的原因,如果经常去线上进行排查会是一个耗时耗力的过程,所以基于这一背景,内部在Yarn UI上扩展了一个功能,业务可以直接通过Yarn UI上jstack的一个链接直接 dump下来container对应的thread信息,极大地提升了运维的效率。
同时还有一个优化就是在container执行前注入了一个hook机制,这个机制会在 container 拉起来时进行container的一些必要的校验,如果业务提的container不满足需求,就会直接拒绝该请求。比如前阶段的log4j的漏洞问题,就可以通过该hook机制,在container执行之前直接扫描初有问题的container并且进行实时拦截。
还有一个问题就是NodeManager日志上报比较慢的问题,因为目前NodeManager上报日志是在app进行初始化的时候,就将该app的信息放入线程池中,当单机的流式作业过多时就会占满线程池。此时如果有批处理的app finish的话,由于该app拿不到线程,就导致外部长时间看不到日志。目前的解决方案是不在app init的时候进行日志监控上报,改为只在app finish的时候进行日志上报。
另外在维护Yarn的过程中,肯定想对离线资源的使用数据做一个观测,比如当前运行了哪些app,是哪种类型的,资源占比是多少,运行了多久等等信息,所以基于这个需求背景建立了Yarn元仓。
04
Yarn元仓建设
Yarn元仓中包含了几大类型的数据,包括占比、趋势、成本,以及队列的满载率和空闲率。基于元仓的数据可以为弹性调度提供数据支撑,并且可以通过不同的占比和趋势掌控集群的变动,产出的元仓数据表还可以提供给外部进行数据分析。
目前的数据基于app event change log,内部在进行app事件转换的时候,会同步记录一份日志,同时会将这部分的数据写入内部的消息队列Talos,然后通过数据同步工具将数据写入到iceberg表中,之后通过flinksql将数据进行处理。同时针对正在运行的任务会通过定时任务从ResourceMananger API中获取,之后将app table和app running table 采用 T+1生成一张大宽表供分析使用。
上面就是目前小米内部Yarn元仓的部分看板,通过其可以很快分析出某个时间段内提交的作业的数量,作业的类型,以及作业的运行时长,同时也能获取到某个时间段内内存及CPU的使用情况。
05
未来规划
在未来的发展中,我们将通过离在线混部的方式在提高在线集群资源利用率的同时充分利用内部闲置资源;同时引入动态超卖去解决静态超卖所存在的问题;将作业调度和资源调度进行通盘探讨,以实现小米离线集群资源的高效利用。
今天的分享就到这里,谢谢大家。