转载

深度剖析 360 命令执行系统 Qcmd

深度剖析 360 命令执行系统 Qcmd

女主宣言

“天下武功,无坚不摧,唯快不破”。今天小编妹妹要带大家看看“运维攻城狮”是如何玩转自动化,轻松管理上万台服务器的。

PS:丰富的一线技术、多元化的表现形式,尽在“ HULK一线技术杂谈 ”,点关注哦!

自动化运维工作在360私有云 HULK 云平台(后面简称为 HULK 云平台)中被称为命令执行系统,在 HULK 云平台运行的4年中,命令执行系统的技术和需求也在发生着变化,可以这么说,命令系统是 HULK 云平台服务和模块的运行根本。

早期的私有云平台模块规划中,将整个命令执行系统包括调度模块和执行模块统称为 Qcmd。

本文会对 Qcmd 的设计、原理、应用和线上使用做下说明。

背景 

HULK 云平台对于命令执行系统的要求比较简单,只需要批量对主机执行脚本,并将返回结果进行呈现。之前线上一直在使用 SaltStack 作为自动化的工具,之所以使用 SaltStack 就是看中可以对批量主机执行命令,并且性能也不错。

但是随着网络的复杂性、机器数量增多以及 HULK 云平台对命令执行需求的变化,渐渐的 SaltStack 的缺点就突显出来了:

  • SaltStack 使用的 Pub/Sub 方式,对网络和执行的主机数量要求“非常高”,如果任务超时没有返回,基本上只能重新执行,非常耽误时间

  • 当 Minions 数量超过一定程度,管理和维护起来非常麻烦,轻易不敢重启 Master

  • 线上 SaltStack 的版本不统一,对新功能兼容很差(例如zmq_filtering )

  • Minions 维护成本较高,最重要的体现就是升级比较困难

当初我们对 SaltStack 也采用了一些优化方案,但是大都无法真正解决问题,当遇到任务超时,还是需要手动登陆主机去查看该命令执行的情况, 针对任务超时的情况,思考许久,发现如果不改变 SaltStack 底层的通讯方式,那么任务超时的情况还是无法避免。

SaltStack 执行命令的过程其实就是下发消息到 Minions,那么我们是否可以用更稳定的消息传递方式来解决消息丢失的问题呢?

最终,我们决定采用异步通讯的方式去代替 Pub/Sub,开发语言我们选择 Golang 来代替 Python。

目标

当然在做一个项目之前我们都会明确一些目标,Qcmd 也不例外:

  1. 消息传递成功率:解决消息传递丢失率高的问题是 Qcmd 的第一目标

  2. 性能:能支持大批量主机执行命令

  3. 集群高可用:高可用我们还是采用了 Multi-Master 方式

  4. 消息加密:采用 AES-CBC

  5. 常用接口:Master 常用接口

  6. 维护成本:是否支持自升级

  7. 分布式:分布式我们已经在上层兼容,后面会具体说明

整体设计

深度剖析 360 命令执行系统 Qcmd

上面是 Qcmd 多机房命令下发的流程:

  1. 任务分发模块由 HULK 命令系统控制

  2. 通过从 Redis 中读取数据,各个机房完成自身的工作,互相不关联

  3. Master 从 Task 到 Minions 都是采用了异步,上图中 Master 到 Minion异步下发,是指 Minion 主动 Subscribe Master 中的消息

Qcmd设计

Master内部消息传递设计:

深度剖析 360 命令执行系统 Qcmd

之前也提到了,Master 下发执行命令的过程其实就是消息传递。

上图是 Master 内部消息的传递流程,Pub 是指 Master 提供给外部调用发布消息的接口,每一个 Topic 和 Channel 对应一个 Minion,Topic 和 Channel 是一对一的关系。

当调用 Pub 接口的时候,首先 Master 会进行数据校验和过滤,然后将合法的信息进行序列化、加密等动作,最后会将处理后的消息发送到相应的 Topic 和 Channel。

Master Subscribe设计:

深度剖析 360 命令执行系统 Qcmd

上图中是 Master 内部 Subscribe 的逻辑设计,当有消息通过 Pub 接口进入,会先对消息进行处理,将处理后的消息根据匹配的 Minons Id 去获取对应的Topic,然后使用 PutMessage,将消息写入 Topic 的 MsgChan,每个 Topic 在创建的时候都会产生一个叫 MessageDump 的 Goroutine,MessageDump 的作用就是将 MsgChan 中的消息及时发送到 Channel 中。

当 Channel 的 PutMessage 被调用时,会将消息写入MsgCha(不是 Topic 的MsgChan),当然 Channel 也有一个 MessageDump 去消费其中的消息,并将一条待发的消息写入 MinionMsgChan。

当 Minion 发起 Subscribe 动作的时候,会使用配置的 ID 做为条件去查询其所在的 MinionMsgChan,如果有消息,Subscribe 动作会返回数据给 Minion,同时 Minion 会立即发起下一次 Subscribe 请求;如果没有消息或者消息不合法,会在到达 SubscribeTimeout 后,给 Minion 发送一条空消息,然后进行下一次 Subscribe 动作。

关于消息的合法性,我们需要满足两种情况:

第一种:Subscribe 到消息的时间已经超过消息的超时时间设置,判断为不合法;

第二种:Subscribe 到消息的时间已经超过了 SubscribeTimeout( SubscribeTimeout 最大值由MaxSubscribeTimeout 限制),也会判断为不合法,这种是为了避免任务超时时间设置过大的情况。

Minion Subscribe设计

深度剖析 360 命令执行系统 Qcmd

上图是 Minion Subscribe 的流程,当调用 Subscribe 有返回,会将受到的消息丢入 CmdChan 中,同时会进行下一次 Subscribe,CmdDump 从 CmdChan中拿到消息,会对消息进行解密等操作,然后根据不同的 Function 去执行相应的操作。

如果执行的操作在预先设置的超时时间之前返回,那么会直接调用 Return,将结果发送到 Master;如果在规定的时间内没有执行完,那么会在到达超时时间后触发 CallBack,将命令执行的状态返回 Master,等到命令真正执行完毕,会再将结果发送到 Master。

Minion Heartbeat设计:

深度剖析 360 命令执行系统 Qcmd

Minion Heartbeat 的作用是定期向 Master 发送心跳,同时查看 Master 中Minion Key 的状态。

在 Heartbeat 之前会检查 Master 当前域名对应的 IP,如果检测到 IP 发生变化,则触发 RetryDns 操作:

第一步:断开与旧的 Master 的连接;

第二步:和新 Master 建立连接,开启认证等。

如果从 Master 返回的操作是需要重新认证(例如在 Master 将 Minion 的 Key 删除),会将 Minion 的 Key 发送到 Master。

性能

我们这里找的是线上的 Master(16U32G)做 test.ping 测试,该 Master 有超过 7000 台 minions,执行 20 次任务,所有 Minions 全部返回,平均耗时 21s左右,下面是执行任务中的 Master 监控图(取自 Wonder)。

深度剖析 360 命令执行系统 Qcmd

从上图的数据看出,在全量执行任务的时候,网卡流量并不高,但是 CPU 使用比较高这里 CPU 主要使用对数据进行加密解密操作(每个 Minion 都需要加密和解密操作)。

总结

从 Qcmd 的设计到开发出 Alpha 版只用了2周时间,我们也对自动化运维有了一些自己的看法:

  1. 首先选择自动化运维工具一定要符合自身的需求,比如HULK云平台大部分执行的任务主机数量其实不到全部主机的1%,属于大规模集群下的小批量主机执行场景。如果使用的还是之前使用的 SaltStack,那么每执行一次任务就相当于同时给所有在线的 Minions 发送一次消息。

  2. 在HULK云平台中对自动化运维工具最大的要求就是执行任务要完全可靠,不能因为网络和执行的主机数量造成消息丢失,导致任务超时。大家不要小看消息丢失的情况,一旦丢失,那么就需要人为判断、然后手动处理等等。

从16年10月开始,已经有超过 2 万台主机部署了 Qcmd,最大的 Master 节点超过 7 千台主机,每天执行任务上千次,任务超时的情况已经基本不存在。Qcmd 在下一个版本会将通讯的方式封装成一个协议,并加重对任务的可控度。

扫描下方

二维码

了解更多内容

深度剖析 360 命令执行系统 Qcmd

原文  http://mp.weixin.qq.com/s/R_6E1t6X3wU3UP-jDTXgow
正文到此结束
Loading...