在阿里巴巴,我们如何先于用户发现和定位 Kubernetes 集群问题? Posted 2022-03-02 阿里巴巴云原生
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在阿里巴巴,我们如何先于用户发现和定位 Kubernetes 集群问题?相关的知识,希望对你有一定的参考价值。
目前,整个阿里巴巴的业务都跑在 Kubernetes 集群上并实现了云原生和容器化,例如:天猫/淘宝/高德/考拉/饿了么等等。容器服务作为阿里云的管控底座,各种云服务也运行在这些集群之上,例如视频云/dataworks /MSE 微服务引擎/MQ 消息队列等等。我们需要对这些基础设施的稳定性负责。现在,云原生的架构越来越流行,越来越多的产品和应用开始选择云原生架构,这里有一张图,大致示意了现代的云原生应用架构,应用生于云上,长于云上,各级提供分层的服务,这种分层的服务能够让业务和应用专注于业务层,屏蔽平台和基础设施层的复杂概念。
从稳定性的角度来讲,这种应用的架构分层,上层应用的稳定性就会开始依赖底层基础设施的支持;另外,大一统的基座既为大规模的资源调度优化和在离线混部提供场景,也对基础设施团队维护大规模集群的稳定性问题提出极大的挑战。 这里有两张形象的图示可以展现出云原生应用架构下的业务应用和平台层基础设施的关系,Kubernetes 集群是非常复杂的,一个单集群的链路组件就有数十个甚至上百个之多,何况是大规模的多 集群管理呢? 但运行在上层 的业务同学 并不会感知到 复杂,因为我们已经把复杂包掉了,留给用户的是一个简单的统一接口 。 就像 淘宝这 样的应用其实是非常复杂的,但在 用户看 来只 是一个简单的提交订单而已,按键背后蕴含着 极其复杂的内容。 为什么做到这样? 因为我们把复杂留给了自己,把简单交给了用 户。 很多时候,好的应用开发者不一定是基础设施专家,云原生让业务专注业务,基础设施专注基础设施。同时,业务很多时候也只能关心业务自身的稳定性,业务大多数时候没有能力关心,或者是不希望投入大量的人力关心基础设施和平台层的稳定性,所以,关于平台层和基础设施的稳定性问题上,我们需要把复杂留给自己,把简单留给用户,为用户提供稳定的平台层服务。同时,更加关心全局稳定性和全局的可用性,而不是单点可用性。 容器服务是阿里巴巴集团业务以及阿里云管控/云服务的底座,上面跑着各种各样的业务,如电商业务/中间件/二方业务/搜索/阿里云云服务等等。此外还有数百个自研和开源的组件,每年数十万次的组件变更/数千个集群/数十万台节点,甚至大的集群单集群节点规模已过万。业务架构更是纷繁复杂,有单租集群、多租集群、vc 集群、联邦集群等等,同时还有各种在离线混布、统一调度、大促活动。在运行时也存在多种形态,如 runC,runD 等等。 因此组件的繁杂、变更频繁、用户场景各异、集群规模庞大、业务架构复杂……都给业务带来了挑战: 挑战一:如何降低系统风险。 场景复杂,业务形态各异,任何一个不起眼细节的遗漏或环节的处置不慎都有可能导致伤害的扩大化; 挑战二:如何对用户集群的稳定性负责。 如何先于用户发现和定位问题成为容器服务生产稳定性建设的重中之重,也是全局高可用体系的基石。 系统是如此的复杂,任何一个不起眼的细节遗漏或处理不慎都有可能导致非预期的伤害,我们要怎样才能降低系统风险呢?另外我们又是如何对形态各异的用户集群运行时全局稳定性负责的呢?如何才能先于用户发现和定位这些集群中已经存在或即将发生的问题,是保障集群的稳定性建设的重中之重,也是 Kubernetes 全局高可用体系的基石。 基于这些挑战,我们做了一些思考和预设。下图是一个极度简化的用户发布扩容链路,虽说极度简化,但实际我们仍可以看出,链路还是比较复杂的。 为了保障这次用户的扩容/发布链路畅通,我们首先带来几个预设:
预设 1: 链路复杂组件众多,各组件分别升级迭代,数据监控无法无死角覆盖全部场景; 预设 2: 即使链路中各组件/节点监控数据正常,也不能保证集群整体链路 100% 可用,只有经过实际业务全链路探测才能确定实际可用的结论; 预设 3: 反证法在证明集群不可用场景一定优于举证法,即使 100% 监控数据正常,但只要发布失败则证明链路不通。 另外,在单集群之外,我们还要关注多集群的管理,下面是一些多集群管控中的不稳定性因素示例,可以看到,多集群场景下,稳定性管控的复杂度会被放大,我们继续带来几个预设: 预设 4: 在大规模集群场景下数据一致性的问题会愈加显现,并且可能引发严重故障,成为一个显著的不稳定因素; 预设 5: 集群内的监控告警链路存在自依赖风险,如果集群故障,则监控告警也有可能同时故障。
链路探测即模拟广义上的用户行为,探测链路是否畅通,流程是否无异常。 想要做到先于用户发现系统问题,我们自己首先要成为系统用户,并且是使用最多、了解最深、无时无刻不在使用和感知系统状态的用户。
所谓链路探测,就是模拟广义上的用户行为,去对集群组件链路中的各种等待探测的对象去做探测。此处要特别说明的是,这里的用户并不仅仅指的是狭义上使用系统的同学,而是更广义的用户,或者可以理解和引申成为依赖下游。 另外,在实现全链路探测的同时,拆解电路,实现全电路中的短路探测也是非常必要的,也是对全链路探测的一个补充。 定向巡检是指检查和分析大规模集群的异常指标,找到已有或将来可能存在的风险点,就像检修管道一样。
例如有若干个集群,它分为很多集群组,不同集群组之间的 etcd 冷/热备是否配置齐备,风控限流配置是否正常,webhook 版本是否正常,混部参数是否一致,包括它的证书有效期是不是快要到期了等等。不同的集群组之间可能有所差别,但同类型集群之间是有一个转衡的,因此我们可以定向做一些巡检。
就像一个游戏策划,如果他连自己制作的游戏都不玩,他可能发现游戏机制的问题,把这个游戏越做越好吗?我们要做到先于用户发现系统问题,那我们自己首先就要先成为系统的用户,并且一定是使用最多的,了解最深的,无时无刻不在使用和感知系统状态的用户。 另外,所谓链路探测,就是让自己成为自己系统的用户,模拟广义上的“用户”行为去对集群/组件/链路里的各种等待探测的对象去做探测。 一定要注意,这里的“用户”并不仅仅指的是狭义上使用系统的同学,而是更广义的用户,或者可以理解引申为依赖下游。 例如业务同学要发布业务,就必然要经过 git 系统,再到发布系统,再到我们底层的基础设施平台,也就是我们的 ASI,这就是一次全链路探测流程。在这里业务同学就是用户,探测对象可以是全链路。 但如果我们把 etcd 看作一个系统服务,那么 APIServer 就是它广义上的用户,我们模拟 APIServer 请求 etcd 这条链路的探测也就有了意义。 另外像 MSE 操作 zookeeper,外部用户通过阿里云控制台创建 ACK 集群,PaaS 平台操作联邦集群,甚至视频云业务方发起一次转码任务,都是一样的道理。 还有一点要关注的就是,虽然全链路探测看起来很美,但很多时候,全链路探测同时还很长,可能等到失败的时候问题已经很大了。所以,在实现全链路探测的同时,拆解链路,实现全链路中的短链路探测也是非常必要的,也是对全链路探测的一个补充。 上图是定向巡检的场景,相比链路探测关注于链路可用性,定向巡检的核心还是在大规模的集群场景下,数据一致性是非常困难的问题,数据不一致,将导致一些隐患,可能会在未来引发某些不确定性的故障。 所谓定向巡检就是对整个集群或链路中的各项数据、指标做已知原因的检查,找出不一致或数据偏离的点,判断是否可能引发风险,从而做到防患于未然,治未病。
比如我们这个里边有同一种类型的集群组,A 集群发现它的证书有效期不到三年,而其他集群的证书有效期都有三年;B 集群的 webhook 版本可能是 v2,而其他集群的 webhook 版本是 v3;C 集群的风控限流配置并没有配一个驱逐 Pod 的限流,但其他集群都配配置了驱逐 Pod 的限流,这肯定是不符合预期的;再比如 D 集群的 etcd 的冷/热备没有配置或者是运行不正常,我们也可以先把它检查出来。 基于上面许许多多的背景预设以及方案,我们设计并实现了一套巡检/探测平台,我们取名为 KubeProbe (并未开源,和现在社区上有类似命名的项目没有任何联系)。 我们早期也曾考虑使用社区项目 Kuberhealthy,并为 Kuberhealthy 做过一些代码贡献,修复过一些严重的代码 Bug,最终因为功能上不太适用于我们的场景,我们选择了自研自建。
上图是一套中心架构,我们会有一套中心管控系统。用户的用例会通过统一仓库的镜像的方式接入,使用我们通用的 sdk 库,自定义巡检和探测逻辑。我们会在中心管控系统上配置好集群和用例的关系配置,如某用例应该执行在哪些集群组上,并做好各种运行时配置。我们支持了周期触发/手动触发/事件触发(如发布)的用例触发方式。用例触发后会在集群内创建一个执行巡检/探测逻辑的 Pod,这个 Pod 里会执行各种用户自定义的业务巡检/探测逻辑,并在成功和失败后通过直接回调/消息队列的方式通知中心端。中心端会负责告警和用例资源清理的工作。 我举一个例子,比如 Kubelet 在我们的组件运维平台上做分批发布,每批次都会触发一次相关集群的链路探测用例作为后置检查,一旦我们发现某次发布的后置检查失败,我们会阻断掉用户的当前发布,防止伤害扩大,同时第一时间告警以及通知相关同事进入排查,是否组件新版本不符合预期。 同时,我们也支持第三方的事件回调,可以更快的集成进三方系统中。 另外,我们对于某些需要 7*24 小时不间断的高频次短周期探测用例,我们还实现了另外一套常驻分布式架构,这套架构使用一个集群内的 ProbeOperator 监听 Probe Config CRD 变化,在探测 pod 中周而复始的执行探测逻辑。这套架构,完美复用了 KubeProbe 中心端提供的告警/根因分析/发布阻断等等附加功能,同时使用了标准 Operator 的云原生架构设计,常驻体系带来了极大的探测频率提升(因为去掉了创建巡检 pod 和清理数据的开销)基本可以做到对集群的 7*24 小时无缝覆盖,同时便于对外集成。
另外还有一个必须要提的非常重要的点,即平台只是提供了一个平台层的能力支持,真正这个东西要起作用,还是要看在这个平台上构建的用例是否丰富,能不能方便的让更多人进来写各种巡检和探测用例。就像测试平台很重要,但测试用例比测试平台更重要这个道理一样。一些通用的 workload 探测,组件探测,固然能发现很多管控链路上的问题,但是更多的问题,甚至业务层的问题暴露,实际上依赖于基础设施和业务层同学的共同努力。 从我们的实践上来说,测试同学和业务同学贡献了很多相关的检查用例,比如测试同学贡献的 ACK & ASK 的创建删除全链路探测巡检,金丝雀业务全链路扩容用例,比如本地生活同学的 PaaS 平台应用检查等等,也得到了很多稳定性上的结果和收益。目前我们维护的巡检/探测用例有数十个,明年有机会破百,巡检/探测次数近 3000 万次,明年可能会过亿。目前可以提前发现 99%以上的集群管控问题和隐患,效果是非常好的。 接下来我们聊聊发现问题之后的事情,这里有一个类似于问诊对话的例子,患者发现 “哎呀我不舒服了!” 这就是发现问题。医生参考各种化验单,同时做了信息聚合分析推断,告诉患者“你已经 24 小时没睡觉了,你睡不着是因为你很焦虑,你焦虑的根因是因为后天就要期末考试了。”这便是定位问题根因,然后针对根因去解决这个问题,他告诉患者“不要担心,我刚收到的消息,小学生已经不需要期末考试了。”这个过程一定要快!
来自探测链路的告警内容往往是混沌的,和数据监控告警是有所差异的。就像上文提到的,链路探测告警的告警很可能就是一句患者的我不舒服了,需要你作为医生去判断,为什么他不舒服了呢?根因是什么。而数据监控很多时候本身就代表了原因,比如 Etcd OOM,用已有的 oncall 经验可能得不到最好的效果。 另外快速定位问题和根因分析,是一个树状的搜索,经验加工判断的过程,也就是如何从一个混沌的表象推断出根因,核心是逻辑。 这和健康体检是不同的,健康体检是列出检查项 1,2,3,4,5......然后告诉你一堆数值。很多时候,即使存在体检中心,我们仍然也需要医院的专业医生来为您解读和判断病情,不是吗? 同时,根因分析/问题自愈的关键在于专家经验的下沉,也就是把专家经验下沉到系统中去,专家经验的下沉带来的最大收益是可复用可输出。你可以想一下,如果我们把一个最专业的医生的能力放进系统里,他是不是更方便的为每一个人分析病情呢?
这便是 KubeProbe 发现问题之后的全流程,我们首先会经过一个我们自建的中心化根因分析系统,在这里我们会聚合分析所有和本次失败相关的信息,包括事件/日志/变更/告警/组件升级等等,我们将这些信息进行聚合分析,并对事件做关联处理,最终通过一个树状的分析系统初步定位出某次探测失败的原因,比如说 APIServer 超时或者 etcd 断连等等。 此外我再补充一点,文本联想也是一个很好的根因分析方式,我们可以通过机器学习训练文本识别的方式来联想出和这种失败 case 最关联的根因,这种 AIOps 的工作我们只是略微涉及,还在持续的探索中,我们的数据量非常大,我认为这一定是未来的方向之一。
上图的左下方是某次我们失败的告警,它经过根因分析系统之后发现首先最核心,最关联,最大的原因可能是 APIserver 的连接断开并且当前已经恢复,所以可能只是偶发的网络抖动,我们暂时不用特别关注,但此时可以看到置信度为 90%。 另外还有一些可能的原因都会关联起来。比如某个组件,这次探测它是由某一个组件发布出发的,它的发布人是 XXX,我们可以观察这个发布对 API server 会产生某些影响,是否多次 list watch 不符合预期,然后把 API server list watch 出问题了,置信度有 50%。 当我们得到一个初步的原因之后,我们会进入二次确认系统做二次的原因确认,比如我们判断原因可能是 APIServer 超时/etcd 断联/节点超时等,我们就会自动重新拉取一下 APIServer 接口,看一下此时是否仍然超时,是否恢复,如果恢复了,我们就普通告警,并且告诉用户,现在没事了,但是你得关注。如果没恢复,那这就很严重了,属于最高优先级,直接电话告警。 就是这个思路,如果有系统无法定位的问题,并且持续无法定位,我们也会触发高级别告警,并且会增加相关的根因分析识别树逻辑。 过多的告警等于没有告警,我是最讨厌告警海的。从经验上讲,当我们构建了一套这样的根因分析+二次确认+后置检查系统之后,我们的 Oncall 成本下降了 90% 以上,并且还能够持续下降,终态可以说是无人值守,大家也可以试试类似的工作,可以说是投入小,见效大。自从这些系统建设起来以后,我们可以自豪的说,我们用很小的精力 Oncall 了每一个告警条目(对,是每一条告警,是数千个集群,数千万次探测巡检的每一条告警)并且不会有任何遗漏了。 最后是一些给 Oncall 人员的小甜品,Chat-ops。
我们利用钉钉提供的 NLP 机器人,构建了一套比较完善的 Chat-ops 系统,这样之后我们的 Oncall 人员就可以很方便的在告警群里通过聊天的方式操作 KubeProbe 相关功能了,比如:重跑失败探测,查询集群状态,拉取诊断信息,查询探测日志,集群告警静默。
上图是我们操作 Chat-ops 系统的过程。这个过程非常方便。 比如晚上我已经再被窝里了,这时候它给我了一个告警,比如某个集群之前出现了某次失败但当前已经恢复了,需要我关注一下。 既然我关注了,我便希望某一个常用例再跑一次(它可能周期比较长,例如一个钟头),由于短链路的用例可能随时都在跑,此时我便告诉机器人再跑一次,机器人就会识别我的语义,将集群再跑一次。跑完之后,我再通过查询状态看一下这个集群当前的状态怎么样了,这样是非常方便的,有时候你晚上上班了,或者是在路上,或者是在被窝里,都也可以很舒服的去 on-call 一个系统了。
点击“ 阅读原文 ”即可下载《云原生与云未来的新可能》电子书全部内容。
https://developer.aliyun.com/topic/download?id=8265 1、 云未来、新可能 - 绿色、无处不在、可信的计算 2、 以一致的体验交付和管理云原生多集群应用 3、 如何在零停机的情况下迁移 Kubernetes 集群 4、最佳实践:Kubernetes 集群中 DNS 故障的可观测性与根因诊断
面对大规模 K8s 集群,如何先于用户发现问题?
作者 | 彭南光(光南)
绪论
不知道大家是否经历过这样的情景:突然被用户告知系统出现问题,然后一脸懵地惶惶然排查修复;或是等到自己发现系统出现故障时,实际已经对用户造成了严重的恶劣影响。
所谓千里之堤,溃于蚁穴。用户信任的建立是长期而艰难的,然而要摧毁这种信任却很简单。一旦出现上述问题,不仅极大影响用户使用体验,同时会给用户留下一个这个产品/团队不可靠的印象,丧失用户对产品/团队长期好不容易积累下来的信用资本,未来再想建立这样的信任关系就很难了。
这也是为什么我们说快速发现问题的能力如此重要的原因, 只有 先做到快速发现问题,才能谈怎样排查问题、如何解决问题。
那么怎样才能在复杂的大规模场景中,做到真正先于用户发现问题呢?下面我会带来我们在管理大规模 ASI 集群过程中对于快速发现问题的一些经验和实践,希望能对大家有所启发。
注:ASI 是 Alibaba Serverless infrastructure 的缩写,是阿里巴巴针对云原生应用设计的统
一基础设施。有兴趣可以阅读:。
背景
我们所管理的大规模 ASI 集群场景非常复杂,这为我们的工作带来了极大挑战,任何一个场景处理不慎就有可能导致意料之外的伤害扩大化。
从组件维度看,我们目前有几百个组件,每年有几万次的组件变更。频繁的组件变更如何在稳定性和效率之间取得权衡,怎样让变更时更稳定,怎样让灰度更确信,从而降低爆炸半径?
从集群维度看,目前有上千个集群和海量节点,碰到的集群/节点问题较多,监控链路覆盖比较繁复,怎样让集群运行时更加可信?
从二方用户和业务场景看,我们支持了大量的集团二方用户,同时业务场景也非常复杂,怎样保证各有特色的业务场景都能得到一致的细心关照?
数据监控作为正向链路,无法无死角覆盖所有场景。即使链路中各个节点的监控数据正常,也不能 100% 保证链路可用。
集群状态每时每刻都在变化,各个组件也在不停地更新升级,同时链路上的每个系统也在不停的变更,监控数据的覆盖永远是正向的追赶,只能逼近 100% 全覆盖而无法完全达到。
即使整个集群链路中所有组件/节点的监控数据都正常,也不能保证集群链路 100% 可用。就如同业务系统一样,看上去都是可用的,没有问题暴露。但只有通过全链路压测实际探测过整个链路后,才能得到实际可用的结论。
你要正向证明一个东西可用,需要举证无数的例子。而如果要反向证明不可用,一个反例就够了。数据监控链路只能逼近全覆盖,而无法保证真正全覆盖。
大规模场景下,数据无法达到 100% 的完全一致性。
当集群规模足够大时,数据的一致性问题将会愈加显现。比如全局风控组件是否全集群链路覆盖?相关流控配置是否全集群链路推平?pod 主容器时区是否与上层一致?集群客户端节点证书是否有即将过期?等等问题,一旦疏忽,将有可能酿成严重的故障。
只有弥补上述两类风险点,才能有底气真正做到先于用户发现问题。我们解决上述两类风险的思路分别是:
所谓黑盒探测,既模拟广义上的用户行为,探测链路是否正常。
所谓巡检,既检查集群异常指标,找到已有或可能将存在的风险点。
基于以上思路,我们设计并实现了 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"
KPclient.ReportSuccess()
os.Exit (0 )
KPclient.ReportFailure([]string{"我失败啦!" })
os.Exit (1 )
我们可以通过提供好的 Makefile 将这个用例打包成镜像,录入 KubeProbe 中心端就可以对集群做配置和下发了。将具体巡检/探测逻辑和 KubeProbe 中心管控端解耦,可以灵活而又简便的让更多的二方用户接入自己的特殊巡检/探测逻辑。
通用探测:模拟 pod / deployment / statefulset 生命周期探测集群整条管控链路。
etcd 黑盒探测:模拟 etcd 的基本操作,探测元集群中各 etcd 状态。
金丝雀探测(感谢质量技术同学的大力支持):模拟用户使用 ASI 的部署场景,实现金丝雀应用的全链路模拟发布/扩容/缩容。
Virtual cluster 探测:探测 vc 虚拟集群的管控链路状态。
节点通用探测:在集群每个节点上模拟调度一个探测 pod,探测节点侧链路状态。
ASI 客户端/服务端证书巡检:检查客户端/服务端证书有效性以及到期时间是否已超过告警阈值。
全局风控限流巡检:检查各 ASI 集群是否已经推平并开启 KubeDefender 全局限流风控配置。
编写完成探测/巡检用例,并打包上传好镜像后,就需要在 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 的链路探测告警就有很多不一样,比如:
Statefulset 链路探测失败,Failed to create pod sandbox: rpc error: code = Unknown
etcd 全流程黑盒探测失败,context deadline exceeded
CloneSet 扩容失败,connect: connection refused
这些 KubeProbe 的告警往往比较难从字面看出到底这次巡检/探测是为什么失败了,我们往往需要根据相关的用例返回日志,巡检/探测 pod 日志,KubeProbe 相关集群事件综合排查,定位失败原因。
我们以比较混沌的 KubeProbe 探测失败告警作为线索,构建了一套 KubeProbe 自闭环的根因定位系统,将问题排查的专家经验下沉进系统中,实现了快速和自动的问题定位功能,一个简单的定位规则如下:
我们会通过普通的根因分析树以及对失败巡检探测事件/日志的机器学习分类算法(持续开发投入中),为每一个 KubeProbe 的探测失败 Case 做根因定位,并通过 KubeProbe 内统一实现的问题严重性评估系统(目前这里的规则仍比较简单),为告警的严重性做评估,从而判断应该如何做后续的处理适宜,比如是否自愈,是否电话告警等等。
有了上面提到的根因定位以及告警严重性评估系统,我们使用了 nlp 告警机器人,实现了一套自动化的 Oncall 系统以及 ChatOps,展示一些使用的 case 如下,通过 ChatOps 和 Oncall 机器人,极大的降低了问题处理的复杂度,尽量用技术的手段解决重复的问题。
以上是我们在管理大规模 Kubernetes 集群中的一点经验,也解决了一些常见的问题,希望能对大家有所帮助。同时,这些工作在阿里云海量规模的场景下还需要持续打磨,我们仍在路上,并且将持续在路上。
以上是关于在阿里巴巴,我们如何先于用户发现和定位 Kubernetes 集群问题?的主要内容,如果未能解决你的问题,请参考以下文章
Cloud Foundry平台中国唯一云供应商,阿里云持续链接Cloud Foundry/Kuber
面对大规模 K8s 集群,如何先于用户发现问题?
定位弹窗广告软件
老用户购买阿里云产品如何获得优惠?
老用户购买阿里云产品如何获得优惠?
阿里云技术专家郝晨栋:云上可观测能力——问题的发现与定位实践