目 录CONTENT

文章目录

小米Hadoop YARN平滑升级3.1实践

醉酒的行者
2025-10-11 / 0 评论 / 0 点赞 / 19 阅读 / 0 字

1 背景

小米之前生产环境的 Hadoop YARN 是基于社区 2.6 版本修改的内部版本,我们最大规模集群已经数千台,而且还在不断增长。在目前 2.6 版本,我们主要面临两个问题:

  • 滞后社区多个大版本, 很多新特性以及 bug 修复没法使用或者需要重新开发;

  • 集群规模增长很快,经历了多次机房迁移,当前版本不能很好地支持跨机房部署方案来实现作业透明迁移;

我们调研 3.1 过程中发现,基于 YARN Federation(YARN-2915) 的跨机房部署方案已经很成熟。同时,为了和社区保持同步,减少代码的维护成本。我们决定升级到 Hadoop 3.1(注:在我们开始调研的时候 3.2 还没 release)。

在升级到 Hadoop 3.1 之后,我们会基于 YARN Federation 这个特性来落地跨机房部署方案。同时,在 3.1 版本我们会和社区一起推进落地基于公有云的 Auto Scaling 方案。

2 目标与挑战

小米 Hadoop YARN 在生产环境有数十个集群(包括国内和海外),服务于小米所有业务线,包含大量的批处理和流式计算作业(>10w/ 天)。本次升级到 Hadoop 3.1 希望能做到对业务透明,尽量减少对业务的影响:

  • 升级期间,不需要停服;

  • 升级期间历史作业不失败;

  • 升级期间可以持续提交新作业;

  • 升级期间,作业日志能够正常查看;

Hadoop YARN 的架构组成包括 ResourceManager(简写 RM)、NodeManager(简写 NM)、HistoryServer、ProxyServer 等多个组件,这些组件之间需要进行 RPC 通信,如下图所示:

图 1-Hadoop YARN 各个组件通信

由于 Hadoop YARN 组件很多,集群规模也很大,为了控制风险,不能一次性把所有组件都升级到 3.1 版本。我们面临的挑战是在多个模块不同版本共存的时候,如何保障上层各类计算框架(Spark、Flink、MapReduce 等)调度的作业不受影响。

3 升级过程

>>>>patch合并/重构

之前我们内部一直维护的是基于社区 2.6 修改的内部版本,我们实现了很多 patch 来满足业务场景。为了升级到 3.1 版本,我们首先要做的就是把内部 patch 合并到社区的 3.1 版本。由于版本跨度很大,这一步我们做了大量的重构工作,这期间主要通过单元测试来保障代码质量。

我们内部的工作主要集中在以下几个方面:

  • 稳定性优化,如基于 ZK 的 client 配置管理,实现了 RM 等服务的平滑迁移 (YARN-9605),NM 隔离优化(YARN-9977),HistoryServer 稳定性优化(YARN-9973) 等;

  • 调度优化,如延时调度,缓存 resource usage 提升排序效率,事件处理优化 (YARN-9979) 等;

  • 易用性优化,如支持 MR 作业查看实时 jstack 信息 (YARN-10069),支持 ui kill app,支持 MySQL 的 StateStore 等;

  • 多集群管理和多租户管理,我们主要进行了资源管理服务产品化,提供统一的 infra-client 和 web 化的资源管理(支持计量计费等);

目前,这些工作已经陆续往社区提交,为我们后续升级版本减轻工作量,同时也希望我们的解决方案能给社区其他成员提供帮助。

>>>>兼容性/回归测试

前面提到,我们 patch 合并重构期间主要是通过单元测试来保证代码质量。但是大量 patch 合并之后,我们必须对整体功能进行完整的回归测试。

同时,在图 1 中我们看到 Hadoop YARN 涉及的 RPC 通信模块很多,版本升级过程中,需要保证各个模块之间通信协议的兼容性。这里,重点讲一下我们如何进行兼容性测试的。

兼容性测试第一块是 Hadoop 本身各个服务模块之间的通信兼容,主要设计的 case 如图 2 所示:

图 2-Hadoop YARN 组件兼容性测试

当然,兼容性相关还有一个比较重要的测试就是针对计算框架的测试。这里我们主要针对内部使用的如下框架进行了测试:

  • Hive 1.2;

  • Hadoop MapReduce 2.6/3.1;

  • Spark 1.6/2.1/2.3;

  • Flink 1.8;

在测试过程,也需要考虑不同版本和不同部署模式的 HDFS,比如我们内部有 2.6 的 Federation 集群和非 Federation 集群。另外,考虑到我们目前访问 HBase 的作业大部分是通过 Spark 实现,我们主要测试了 Spark 作业访问 HBase 的场景。

>>>>调度器测试

小米之前使用的调度器是基于社区 2.6 版本修改的 FairScheduler。在和社区交流过程发现,社区后续的发展方向主要在 CapacityScheduler (YARN-5864),并且在 Hadoop 3.x 中 CapacityScheduler 对调度性能、资源利用率等方面进行了很多优化。所以在升级 3.1 之后我们有一个比较大的改动是从 FairScheduler 切换到 CapacityScheduler。这里主要面临两个问题:

  • 线上生产集群的 FairScheduler 相关队列配置已经使用了很长一段时间,需要平滑切换到 CapacityScheduler;

  • 我们的资源管理服务之前是针对 FairScheduler 设计的,需要对 CapacityScheduler 进行适配;

其中比较重要的是问题 1,这个问题在社区会议的时候提出来了,之后社区也有相关 issue 跟进 (YARN-9698)。我们内部的解决办法是把重要配置进行了梳理,实现一个工具基于 FairScheduler 的配置自动化地生成对应的 CapacityScheduler 配置。这里几个比较重要的配置提一下:

maximum-am-resource-percent
user-limit-factor
intra-queue-preemption.disable_preemption
disable_preemption
maximum-capacity

其中 user-limit-factor 和 maximum-am-resource-percent 在 FairScheduler 语义不太一样或者是没有实现。我们针对调度器的测试主要是通过线上 FairScheduler 配置生成 CapacityScheduler 配置来启动测试 RM,然后进行验证。目前,针对调度器的性能测试我们也探索了 SLS 工具。

针对 CapacityScheduler 我们提交了一些 patch 给社区:YARN-7621,YARN-9748,YARN-9709 等。

>>>>升级/回滚方案

经过上面的单元测试、兼容性测试、调度器测试之后,我们设计和演练了升级方案。最后确定的主要步骤如下:

  1. 准备好回归测试作业(包括 Hive/MR/Spark 等),作业类型包含基本的 TeraSort、WordCount 以及一些用户的作业

  2. 升级资源管理服务

    1. 支持同时更新 FairScheduler 和 CapacityScheduler 的配置,当 CapacityScheduler 出现问题的时候可以直接回滚到 FairScheduler

  3. 升级控制节点(RM/HistoryServer/ProxyServer)

    1. RM 主节点使用 3.1 版本的 CapacityScheduler,备节点使用 2.6 版本的 FairScheduler,当调度出现问题的时候,可以做主备切换进行恢复

    2. 基于回归测试作业进行验证,同时确认日志查看、主备跳转是否正常

  4. 升级 Hadoop 客户端配置和包

    1. 升级测试机器,验证回归测试作业是否正常运行

    2. 升级监控机器,验证监控作业是否正常运行

    3. 分批逐步升级作业调度机器,观察用户作业是否正常运行

  5. 升级 Hive 到兼容 3.1 的版本

    1. 部署一个兼容 3.1 版本的 Hive 实例,然后验证回归作业和线上部分历史作业

    2. 分批逐步升级其他 Hive 实例,观察用户查询是否正常运行

  6. 分批升级 NM(注:我们修改了 2.6 版本 NM 的 recovery 模块,支持直接从 3.1 回滚到 2.6)

    1. 我们会按照 5%->25%->50%->75%->100% 的灰度策略对 NM 进行操作

    2. 每步更新都会对回归测试作业进行验证

在升级过程中,我们主要通过作业级别、队列级别、集群级别的监控报警来帮助我们及时发现问题。

4 问题及解决

在升级测试、演练和执行落地过程中,我们遇到一些问题:

>>>>NM回滚2.6版本异常

测试回滚 NM 的时候,发现如下异常,主要是 3.1 版本的 recovery 相关状态多了很多字段

2019-xx-xx,17:06:12,797 FATAL org.apache.hadoop.yarn.server.nodemanager.NodeManager: Error starting NodeManager
org.apache.hadoop.service.ServiceStateException: java.io.IOException: Unexpected container state key:
ContainerManager/containers/container_e36_1558337587778_0027_01_000002/starttime

修复办法就是在 2.6 版本实现类似逻辑或者是直接兼容一下。

>>>>MR RPC协议修改导致作业执行异常

Hadoop Mapreduce 在 3.1 版本针对 TaskUmbilicalProtocol 做了一些改动,如果是 2.6 和 3.1 进行通信,会出现下面问题。这里解决办法是通过在 client 指定 classpath 保证单个作业依赖的版本是一致的。

2019-xx-xx 16:49:49,306 WARN [main] org.apache.hadoop.mapred.YarnChild:
 Exception running child : org.apache.hadoop.ipc.RemoteException(org.apache.hadoop.ipc.RPC$VersionMismatch):
 Protocol org.apache.hadoop.mapred.TaskUmbilicalProtocol version mismatch. (client = 19, server = 21)

>>>>FileOutputCommitter版本改变导致数据丢失

FileOutputCommitter 在 3.1 版本增加了新的 commit 算法,并且默认是不写临时目录了。而在 2.6 版本,默认的 commit 算法是先写临时目录最后原子的 move 到最终输出目录。当 NM 版本是 2.6 和 3.1 共存的时候,我们遇到了 Spark 作业结果数据比预期少很多的问题。

解决办法很简单,先调整代码的默认算法:

mapred-default.xml:


<name>mapreduce.fileoutputcommitter.algorithm.version</name>
<value>1</value>

FileOutputCommitter:

public static final String FILEOUTPUTCOMMITTER_ALGORITHM_VERSION =
      "mapreduce.fileoutputcommitter.algorithm.version";
public static final int FILEOUTPUTCOMMITTER_ALGORITHM_VERSION_DEFAULT = 1;

>>>>日志配置文件不存在

3.1 和 2.6 在生成 launch container 脚本的时候对于 log 目录的设置存在差异。

log4j:ERROR setFile(null,true) call failed.
java.io.FileNotFoundException: /home/work/hdd3/yarn/c4prc-preview/nodemanager/application_1559618566050_0070/container_e18_1559618566050_0070_01_000001 (Is a directory)

>>>>容量调度器配置不对

容量调度器对于 <0,0> 的配置是不识别的,并且会直接抛异常导致 RM 启动失败。

2019-06-25,16:07:19,266 FATAL org.apache.hadoop.yarn.server.resourcemanager.ResourceManager: Error starting ResourceManager
java.lang.IllegalArgumentException: Parent queue 'root.production' and child queue 'root.production.xiaoqiang_group' should use either percentage based capacityconfiguration or absolute resource together for label

当然,还有很多其他问题这里没有展示。部分修复我们已经提交社区比如:(YARN-9693)、(YARN-9689),后续其他修复我们也会提交社区。

5 后续计划

2019 年我们已经完成了国内外数十个集群的升级,2020 年 Q1 我们会完成最后一个公共集群的升级。从成本和扩展性考虑,我们下一步会在如下几个方向继续探索:

  • 落地 Yarn Federation 支持超大规模联邦集群,支持同城跨机房部署 (>1w 台);

  • 在海外落地基于公有云的 Auto Scaling 方案 (YARN-9548),系统化地优化公有云集群成本;

  • 探索落地离在线混部的方案,打通在线 / 离线计算资源;

6 致谢

感谢计算平台 SRE 组同学以及存储团队 HDFS 同学在升级期间的给力支持!(目前我们存储团队也已经推进多个 HDFS 集群升级到了 Hadoop 3.1,期待他们的分享)

7 关于我们

小米云平台计算平台团队,负责为小米集团各业务线提供高品质的弹性调度和计算服务。包括离线平台(Spark,Hadoop Yarn,Kylin,Doris 等),流式平台(Kafka,Flink 及自研 Talos 等),弹性平台(Docker,Kubernetes 等)。 武汉团队主要负责 Kylin、Druid 等 OLAP 引擎开发。北京武汉均有职位,欢迎感兴趣的小伙伴加入 ~ 联系方式:computing-hr@xiaomi.com

8 参考

[1] FS Migration CS

https://issues.apache.org/jira/secure/attachment/12979377/FS-CS%20Migration.pdf

[2] YARN Federation

https://issues.apache.org/jira/browse/YARN-2915

[3] Migrating Hulu’s Hadoop Clusters to a New Data Center

https://medium.com/hulu-tech-blog/migrating-hulus-hadoop-clusters-to-a-new-data-center-part-one-extending-our-hadoop-instance-b88c4bda61bc

[4] Hydra: a federated resource manager for data-center scale analytics

https://www.microsoft.com/en-us/research/uploads/prod/2018/12/NSDI19_paper159_CR.pdf

[5] Make YARN work well in elastic cloud environments

https://issues.apache.org/jira/browse/YARN-9548

0

评论区