大家是否经历过突然被用户告知系统出现问题,然后一脸懵逼的惶惶然排查修复。或者等到自己发现系统出现故障时,实际已经对用户造成了严重的恶劣影响。
所谓千里之堤,溃于蚁穴。用户信任的建立是长期而艰难的,然而要摧毁这种信任却很简单。一旦出现上述问题,不仅极大的影响用户使用体验,同时会给用户留下一个这个产品/团队不可靠的印象,丧失用户对产品/团队长期好不容易积累下来的信用资本,失信于用户。未来再想建立这样的信任关系就很难了,这也就是为什么快速发现问题的能力如此重要的原因。
1分钟快速发现问题的能力是1-5-10快恢体系的基石,只有先做到快速发现问题,才能谈怎样排查问题,如何解决问题。
那么怎样才能在复杂的大规模场景中,做到真正先于用户发现问题呢?下面我会带来我们在管理大规模 ASI 集群过程中对于快速发现问题的一些经验和实践,希望能对大家有所启发。
我们所管理的大规模 ASI 集群场景非常复杂,这为我们的工作带来了极大挑战,任何一个场景处理不慎就有可能导致意料之外的伤害扩大化。
基于长期的集群管理经验,我们有如下预设:
1 . 数据监控作为正向链路,无法无死角覆盖所有场景。即使链路中各个节点的监控数据正常,也不能 100% 保证链路可用。
2 . 大规模场景下,数据无法达到 100% 的完全一致性。
只有弥补上述两类风险点,才能有底气真正做到先于用户发现问题。我们解决上述两类风险的思路分别是:
1 . 黑盒探测
2 . 定向巡检
基于以上思路,我们设计并实现了kubeprobe探测/巡检中心,用于弥补复杂系统的正向监控的不足,帮助我们更好,更快的发现系统风险和线上问题;
不知道你是否也经历过一条链路上各个系统监控数据都正常,但是实际链路流程就是跑不通。或者因为系统变化快,监控覆盖不到 100% 的场景总是会有遗漏,导致影响到了用户却没有报警,对用户没有实质影响却报警频发从而疲于奔命。
如果一个系统开发者自己都不使用自己的系统,那么怎么可能先于用户发现系统问题呢?所以要先于用户发现系统问题,首先我们自己就得先成为用户,而且一定是使用最多,了解最深,无时无刻不在使用和感知系统状况的用户。
所谓黑盒探测,就是让自己成为自己的用户,模拟广义"用户"的行为去对集群/组件/链路等待待测对象做探测。注意,这里的"用户"并不仅仅是狭义上使用系统的同学,而是广义用户。比如,etcd 的"用户"是 APIServer,而 ASI 的"用户"可能是某个通过 APIServer 操作集群的同学,也可能是 Normandy 发起的发布/扩容/缩容操作。
我们希望 KubeProbe 能在 变更时(监听到集群状态发生变化/组件变更/组件发布/系统升级等等事件)/运行时(周期,高频)/故障恢复时(手动),通过周期/事件触发/手动触发,执行各种不同类型的黑盒探测,第一时间感知组件/集群/链路的可用性。
以 etcd 集群的可用性来举例,我们可以实现一个探测用例,逻辑是对 etcd 做 create/get/delete/txn 等等操作,并记录每个操作的成功率/消耗时间,当成功率低于 100% 或消耗时间超过容忍阈值后,触发报警。我们将周期高频运行这个 etcd 的探测用例,同时对于 etcd 集群的任何变更都会发出一个事件 event 触发这个 etcd 探测立即运行,这样就能尽量确保第一时间发现 etcd 可用性故障了。同时,当 etcd 集群因为某些原因不可用了,我们也可以通过手动触发等其他方式做探活,也能第一时间得到是否恢复的信息。
在大规模集集群/系统场景下,数据一致性是一定会面临的难题。数据不一致,将导致一些隐患,可能会在未来引发某些确定性的故障。
相比于黑盒探测面对的未知故障场景,定向巡检的目标是对集群的已知风险点做扫描。
我们希望 KubeProbe 能够定期对整个集群/链路做定向的巡检,找出这些数据不一致的点,判断数据不一致是否可能引发风险,从而能够防患于未然,治未病。
比如 etcd 冷热备多集群覆盖不全,可能导致集群遇到故障无法快速恢复。那么我们就定期对 etcd 的冷热备覆盖情况做定向巡检,找出没有覆盖推平的集群,并告警。比如 集群风控系统没有全集群链路覆盖,限流配置没有全集群链路推平,可能导致某些故障场景引发集群全面崩溃,我们定期对风控配置全网扫描,判断是否可能导致故障,找出这些隐藏的已知风险点并告警。
KubeProbe 的基本实现架构大致如下图,KubeProbe 中心端配置集群/集群组与巡检/探测用例/用例集之间的关联关系,负责对集群做具体某次探测实例下发。某个具体的巡检/探测用例下发到具体某个集群将使用用例的镜像创建一个 pod,这个 pod 里会执行若干巡检/探测逻辑,当执行完成后会回调中心端回写本次巡检/探测结果。其具体结果在中心端统一展示/告警,并提供给其他消费者消费(如支持 ASIOps 平台的发布阻断)。
除了上述的基本架构之外,我们对于高频探测用例(既探测周期短,触发频率需要非常频繁,甚至保持无缝探测的场景)设计了一套集群内的分布式常驻探测架构,该架构通过集群内的 ProbeOperator 组件 watch 自定义对象 probeConfig 的变化,在集群内创建一个常驻的探测 pod,将持续无间断的运行探测逻辑,实现接近无缝的持续探测,并将结果通过去噪/令牌桶限流等处理后,上报中心端,共给其他消费者消费。
所有的探测/巡检用例都使用统一的 git 仓库管理,由我们提供一个统一的 client 库,client 库最核心提供的方法主要有两个。
KPclient "gitlab.alibaba-inc.com/{sigma-inf}/{kubeProbe}/client"
// 报告成功
// 此方法会向KubeProbe报告本次巡检结果为成功
KPclient.ReportSuccess()
os.Exit(0)
// 报告失败
// 报告方法会向KubeProbe报告本次巡检结果为失败,并且失败信息为 `我失败啦`
KPclient.ReportFailure([]string{"我失败啦!"})
os.Exit(1)
我们可以通过提供好的 Makefile 将这个用例打包成镜像,录入 KubeProbe 中心端就可以对集群做配置和下发了。将具体巡检/探测逻辑和 KubeProbe 中心管控端解耦,可以灵活而又简便的让更多的二方用户接入自己的特殊巡检/探测逻辑。
目前已经使用的探测/巡检用例包括:
编写完成探测/巡检用例,并打包上传好镜像后,就需要在 KubeProbe 中心端注册这个用例模版,即将镜像注册进 KubeProbe 中心端的数据库中。
我们可以通过"渲染配置"参数传入一些指定的 env 环境变量到巡检/探测 pod 中,用于执行不同的业务逻辑,实现同一个用例模版生成多个用例。
最后通过统一的配置管控将用例和集群做绑定,配置对应的参数,执行各种下发逻辑。
同时,我们还在 KubeProbe 中心端做了大量权限安全管控,脏数据资源清理以及提效增速的工作(比如采用完全以 ownerreferences 的巡检/探测用例资源自动清理能力等等),这里不再赘述。
我们打通了 KubeProbe 探测与发布变更的关联,当对应集群中有任何变更发生时(如某组件在做发布),我们会自动通过相应的事件触发此集群绑定的所有巡检/探测用例,检查集群状态是否正常。如果探测失败,则会将变更阻断,降低爆炸半径,提升集群变更时稳定性。
社区有一个 Operator 叫 Kuberhealthy 也可以做类似的事情,我们曾经也考虑采用,并且深度使用过 Kuberhealthy 和参与 kuberhealthy 的社区贡献,最终得出不适合的结论,主要原因是对大规模集群的支持较弱,同时高频调用时主流程卡死问题比较严重,不支持事件/手动单次触发特性,不支持统一上报数据中心等等,最终选择了自研自建的方式,目前来看是一个比较正确的选择。
KubeProbe 上线以来,实现探测/巡检用例几十个,在集团数百个 ASI 集群中运行千万余次,主动发现集群故障和问题百余次,其中某些小故障一旦没有发觉很有可能升级成为大故障,有效降低了系统风险。同时打通了变更/发布系统,提升了变更稳定性。并且在特殊故障时,多次先于业务方提前发现问题,更早地推动解决问题,客观降低了故障损失。
下面是一个具体例子:
我们会接收到每个集群中各个组件的发布事件,由发布事件触发我们会在对应集群中运行相关的巡检/探测,比如调度一个定向的 pod 到某个节点组件发布的节点上去。我们发现 kube-proxy 的发布会导致节点的短暂不可用,调度上去的 pod 无法创建成功,从简单的返回/日志/集群事件上看不出具体的问题,并且持续复现。经过深入排查,得知是 kube-proxy 的问题,存在 netns 泄露。运行久了会泄露,当 kube-proxy 重启的时候,内核要清理 netns,会卡一段时间来清理,导致节点一段时间链路不通,pod 可以调度上去但是运行不起来,从而后续推进了 kube-proxy 的问题修复。
发现问题之后
KubeProbe和数据监控告警区别
KubeProbe所面对的场景和数据监控不同,更多偏向于链路探测;
比如,监控告警一般的告警可能如下:
这些告警,往往内容中就包含了具体的故障点,而KubeProbe的链路探测告警就有很多不一样,比如:
这些KubeProbe的告警往往比较难从字面看出到底这次巡检/探测是为什么失败了,我们往往需要根据相关的用例返回日志,巡检/探测pod日志,KubeProbe相关集群事件综合排查,定位失败原因
根因定位
我们以比较浑沌的KubeProbe探测失败告警作为线索,构建了一套KubeProbe自闭环的根因定位系统,将问题排查的专家经验下沉进系统中,实现了快速和自动的问题定位功能,一个简单的定位规则如下:
我们会通过普通的根因分析树以及对失败巡检探测事件/日志的机器学习分类算法(持续开发投入中),为每一个KubeProbe的探测失败Case做根因定位,并通过KubeProbe内统一实现的问题严重性评估系统(目前这里的规则仍比较简单),为告警的严重性做评估,从而判断应该如何做后续的处理适宜,比如是否自愈,是否电话告警等等。
Oncall和ChatOps
有了上面提到的根因定位以及告警严重性评估系统,我们使用了nlp告警机器人,实现了一套自动化的Oncall系统以及ChatOps,展示一些使用的case如下,通过ChatOps和Oncall机器人,极大的降低了问题处理的复杂度,尽量用技术的手段解决重复的问题;
以上是我们在管理大规模Kubernetes集群中的一点点微小的经验,也解决了一些普通的问题,希望能对大家有所帮助。在阿里云如此海量规模的场景下,我们还需要持续打磨,我们仍在路上,并且将持续在路上。
来源阿里巴巴云原生
作者: 彭南光(光南)
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有