Yarn平滑下线节点(Graceful Decommission)
一、背景
接手部门 Hadoop 和 Flink 集群半年了,一直忙着上云的事儿,很少有时间去琢磨运维的事儿。上完云之后,老板着重强调要稳定,尤其是 Flink 集群,稳定性是实时任务最重要的指标。因为我们是 Flink on Yarn 的模式,Yarn 的节点上线和下线其实就是两行命令的事儿,但是 Flink 集群就不能这么做了。
我们的机器配置比较高,一台机器上可能跑着上百个 Flink 任务的 Taskmanager 或 JobManager,直接把 NodeManager 节点摘掉,影响的任务太多,风险就比较大,所以老板让我调研一下如何把下线节点做到对业务方的影响无感,把风险降到最低。
在查阅了一番的资料之后,找到了相对好一点的办法:先把机器从 Yarn 上 Graceful Decommisson,然后逐个 kill 这台机器上任务的 task。这种做法的好处在于:第一,下线期间,不会有新的 Container 分配到这台机器上;第二,逐个 kill 让风险可控,有一个 Buffer。
二、概述
Yarn 集群的扩容非常简单,只需要在新的机器节点上,运行 NodeManager 服务,Yarn 会自动完成节点注册,资源检测等操作,然后在该节点上运行任务。除了易于扩容,Yarn 还支持通过下线 (Decommission)节点的方式实现弹性缩容。Yarn节点有两种下线方式:
一个是正常的 DECOMMISSIOIN 方式,直接在节点上关闭 NodeManager 服务,这种方式会导致运行在该节点上的所有 container 全部 failover。
另一种更优雅的方式 GRACEFUL_DECOMMISSION,不会直接关闭 NodeManager 服务,而是会尽可能地降低对运行中的任务的影响。节点处于下线流程期间,ResourceManager 不会向这些节点调度新的 container,并等待正在运行的 container 都结束(或者达到指定的超时时间),才会将节点标记为 Decommission 状态,将其从集群中删除。
三、下线流程与原理
#节点下线命令
yarn rmadmin -refreshNodes [-g [timeout in seconds] -client|server]
1.读取待下线节点列表
首先需要在集群配置文件中指定需要下线的节点列表,如果每个节点下线的超时时间不同,还需要额外对每个节点配置单独的超时时间,然后使用上述节点下线命令。
使用上述命令后,ResourceManager 中的 NodeListManager 组件会读取待下线节点列表文件(目前该文件只支持文本或者xml格式),具体来说,如果想要实现每个节点单独配置下线超时时间,那么该文件必须是 xml 格式。
2.判断节点下线模式
读取到需要下线的所有节点Host之后,Yarn 会按照命令中指定的模式处理下线:client 或 server 模式。
这两种模式的区别在于,超时时间配置生效的优先级和超时时间处理的对象。
- 在 server 模式下,优先级是 待下线列表文件 > 下线命令 > yarn配置;在 client 模式下,只有下线命令中指定的超时时间会生效。
- 在 client 模式下, client 会处于阻塞状态来追踪是否达到超时时间;而 server 模式下,该工作由 ResourceManager 完成。
3.设置超时时间
读取到有效的超时时间后,NodeListManager 会给每个 RMNode 设置单独的超时时间。这个超时时间也可以通过再次使用上述命令的方式进行动态调整,重复使用上述命令并不会重置超时时间,只会影响节点是否超时的判断。
比如说,在 1:00 设置了某个节点2小时后(即3:00)下线,如果在 2:00 的时候,再次使用该命令设置该节点的超时时间为3小时,那么此时该节点的下线时间会是 4:00 而不是 5:00,过去的这1个小时的时间并不会被重置。如果这个时候再将超时时间设置为1小时,下线时间就会是2:00,那么该节点将立即下线。
4.RMNode 处理下线事件
在收到 GRACEFUL_DECOMMISSION 指令后,RMNode 会保存指定的超时时间,并更新节点指标,保留其总的资源容量信息,并切换到待下线(DECOMMISSIONING)状态。处于该状态的 RMNode 会定期动态地更新资源情况,防止因为集群可用资源不足,scheduler 将新的 container 分配到将下线节点上。
5.监控节点的状态、下线节点
在收到 GRACEFUL_DECOMMISSION 指令后,Yarn 会启动一个组件 DecommissioningNodeWatcher 来自动地异步监控待下线(DECOMMISSIONING)节点的状态。待下线节点的 NodeManager 进程会定期发送心跳,来报告其上所有运行的 container 的最新运行状态,DecommissioningNodeWatcher 会监控这些 container 的状态,并在所有的 container 运行完成后,通知 NodeManager 关闭,并将该节点切换为已下线(DECOMMISSIONED)状态。
由于在 MapReduce 任务中,即使一个节点上所有的 container 都运行完了,它仍然会为 reducer 提供 map 的输出数据,在这种情况下,Yarn 的 GRACEFUL_DECOMMISSION 机制会保留这些待下线节点(即使该节点上所有 container 都运行完了),直到所有涉及的任务都运行结束。
但是某些任务可能会长时间运行,这就会导致待下线节点上的 container 一直无法运行完成,或者即使运行完了也需要读取数据而无法下线节点。而超时时间的作用就是,只要达到超时时间,不管 container 或者任务有没有运行完成,DecommissioningNodeWatcher 都会将节点下线,没有完成的任务会 failover。
所有待下线节点的状态,都会定期(默认每20s)记录在 ResourceManager 的日志中,以下是待下线节点的所有状态:
NONE – Node状态正常,并不是待下线节点
WAIT_CONTAINER – 等待所有 container 运行完成
WAIT_APP – 等待所有涉及的 application 运行完成(在所有container完成后)
TIMEOUT – 超时
READY – 准备下线
DECOMMISSIONED – 已下线
四、相关的Yarn集群配置
yarn.resourcemanager.nodes.exclude-path
需要下线的节点 Host 文件路径。
yarn.resourcemanager.nodemanager-graceful-decommission-timeout-secs
GRACEFUL_DECOMMISSION 下线节点的超时时间。默认值为 3600s,即1小时。
如果将该值设为负数,则节点会等到所有任务完成,永远不会强制下线节点。视具体情况,可以在执行下线命令前修改该值。或者直接通过命令指定。
yarn.resourcemanager.decommissioning-nodes-watcher.poll-interval-secs
DecommissioningNodesWatcher 内的轮询计时器任务的周期(以秒为单位),用于识别和处理心跳信息缺失的待下线节点。默认值为 20s。 私有云使用默认值。
热门相关:帝少的专属:小甜心,太缠人 寂静王冠 天启预报 人间欢喜 霸皇纪