共计 7252 个字符,预计需要花费 19 分钟才能阅读完成。
作者:彭南光(光南)
本文整顿自阿里云高级研发工程师彭南光(光南) 在 KubeCon China 2021 大会的演讲实录,分享了阿里巴巴是如何通过自研通用链路探测 + 定向巡检工具 KubeProbe 应答大规模集群的稳定性挑战的。对于阿里云云原生团队在本次 KubeCon 上分享的全部内容积淀于电子书《云原生与云将来的新可能》当中,可点击文末“浏览原文”下载。
疾速发现和定位问题的能力是疾速复原零碎的基石,只有先做到疾速发现和定位问题,能力谈如何解决问题,尽量减少用户损失。那么如何在简单的大规模场景中,做到真正的先于用户发现和定位问题呢?我会将咱们在治理大型 Kubernetes 集群过程中疾速发现和定位问题的一些教训和实际带给大家——咱们是如何通过自研通用链路探测 + 定向巡检工具 KubeProbe 应答遇到的大规模集群的稳定性挑战的。
链路探测: 模仿狭义用户行为,探测链路和零碎是否异样
定向检测: 查看集群异样指标,发现将来存在或可能存在的危险点
零碎加强: 发现问题提速增效,根因剖析
发现问题之后: 后置检查和自愈,Chat-Ops
业务背景和挑战
阿里云云原生利用平台的容器服务团队,领有 ACK、ASI 等产品,治理了大规模的 Kubernetes 集群,不仅向内部私有云用户提供 Kubernetes 服务,还承当了阿里巴巴团体上云,阿里巴巴利用全面容器化的工作。
目前,整个阿里巴巴的业务都跑在 Kubernetes 集群上并实现了云原生和容器化,例如:天猫 / 淘宝 / 高德 / 考拉 / 饿了么等等。容器服务作为阿里云的管控底座,各种云服务也运行在这些集群之上,例如视频云 /dataworks /MSE 微服务引擎 /MQ 音讯队列等等。咱们须要对这些基础设施的稳定性负责。
当初,云原生的架构越来越风行,越来越多的产品和利用开始抉择云原生架构,这里有一张图,大抵示意了古代的云原生利用架构,利用生于云上,长于云上,各级提供分层的服务,这种分层的服务可能让业务和利用专一于业务层,屏蔽平台和基础设施层的简单概念。
从稳定性的角度来讲,这种利用的架构分层,下层利用的稳定性就会开始依赖底层基础设施的反对;另外,大一统的基座既为大规模的资源调度优化和在离线混部提供场景,也对基础设施团队保护大规模集群的稳定性问题提出极大的挑战。
这里有两张形象的图示能够展现出云原生利用架构下的业务利用和平台层基础设施的关系,Kubernetes 集群是非常复杂的,一个单集群的链路组件就有数十个甚至上百个之多,何况是大规模的多集群治理呢?但运行在下层的业务同学并不会感知到简单,因为咱们曾经把简单包掉了,留给用户的是一个简略的对立接口。就像淘宝这样的利用其实是非常复杂的,但在用户看来只是一个简略的提交订单而已,按键背地蕴含着极其简单的内容。为什么做到这样?因为咱们把简单留给了本人,把简略交给了用户。
很多时候,好的利用开发者不肯定是基础设施专家,云原生让业务专一业务,基础设施专一基础设施。同时,业务很多时候也只能关怀业务本身的稳定性,业务大多数时候没有能力关怀,或者是不心愿投入大量的人力关怀基础设施和平台层的稳定性,所以,对于平台层和基础设施的稳定性问题上,咱们须要把简单留给本人,把简略留给用户,为用户提供稳固的平台层服务。同时,更加关怀全局稳定性和全局的可用性,而不是单点可用性。
容器服务是阿里巴巴团体业务以及阿里云管控 / 云服务的底座,下面跑着各种各样的业务,如电商业务 / 中间件 / 二方业务 / 搜寻 / 阿里云云服务等等。此外还有数百个自研和开源的组件,每年数十万次的组件变更 / 数千个集群 / 数十万台节点,甚至大的集群单集群节点规模已过万。业务架构更是纷繁复杂,有单租集群、多租集群、vc 集群、联邦集群等等,同时还有各种在离线混布、对立调度、大促流动。在运行时也存在多种状态,如 runC,runD 等等。
因而组件的繁冗、变更频繁、用户场景各异、集群规模宏大、业务架构简单……都给业务带来了挑战:
挑战一:如何升高零碎危险。 场景简单,业务形态各异,任何一个不起眼细节的脱漏或环节的处理不慎都有可能导致挫伤的扩大化;
挑战二:如何对用户集群的稳定性负责。 如何先于用户发现和定位问题成为容器服务生产稳定性建设的重中之重,也是全局高可用体系的基石。
零碎是如此的简单,任何一个不起眼的细节脱漏或解决不慎都有可能导致非预期的挫伤,咱们要怎样才能升高零碎危险呢?另外咱们又是如何对形态各异的用户集群运行时全局稳定性负责的呢?如何能力先于用户发现和定位这些集群中曾经存在或行将产生的问题,是保障集群的稳定性建设的重中之重,也是 Kubernetes 全局高可用体系的基石。
思考和计划
基于这些挑战,咱们做了一些思考和预设。下图是一个极度简化的用户公布扩容链路,虽说极度简化,但理论咱们仍能够看出,链路还是比较复杂的。
为了保障这次用户的扩容 / 公布链路畅通,咱们首先带来几个预设:
预设 1: 链路简单组件泛滥,各组件别离降级迭代,数据监控无奈无死角笼罩全副场景;**
预设 2: 即便链路中各组件 / 节点监控数据失常,也不能保障集群整体链路 100% 可用,只有通过理论业务全链路探测能力确定理论可用的论断;
预设 3: 反证法在证实集群不可用场景肯定优于举证法,即便 100% 监控数据失常,但只有公布失败则证实链路不通。另外,在单集群之外,咱们还要关注多集群的治理,上面是一些多集群管控中的不稳定性因素示例,能够看到,多集群场景下,稳定性管控的复杂度会被放大,咱们持续带来几个预设:
预设 4: 在大规模集群场景下数据一致性的问题会更加浮现,并且可能引发重大故障,成为一个显著的不稳固因素;
预设 5: 集群内的监控告警链路存在自依赖危险,如果集群故障,则监控告警也有可能同时故障。
接下来是咱们基于以上预设的一些解决方案。
摸索和解决方案
1. 链路探测
链路探测即模仿狭义上的用户行为,探测链路是否畅通,流程是否无异样。
想要做到先于用户发现零碎问题,咱们本人首先要成为零碎用户,并且是应用最多、理解最深、无时无刻不在应用和感知零碎状态的用户。
所谓链路探测,就是模仿狭义上的用户行为,去对集群组件链路中的各种期待探测的对象去做探测。此处要特地阐明的是,这里的用户并不仅仅指的是广义上应用零碎的同学,而是更狭义的用户,或者能够了解和引申成为依赖上游。
另外,在实现全链路探测的同时,拆解电路,实现全电路中的短路探测也是十分必要的,也是对全链路探测的一个补充。
2. 定向巡检
定向巡检是指检查和剖析大规模集群的异样指标,找到已有或未来可能存在的危险点,就像检修管道一样。
例如有若干个集群,它分为很多集群组,不同集群组之间的 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 在咱们的组件运维平台上做分批公布,每批次都会触发一次相干集群的链路探测用例作为后置查看,一旦咱们发现某次公布的后置查看失败,咱们会阻断掉用户的以后公布,避免挫伤扩充,同时第一工夫告警以及告诉相干共事进入排查,是否组件新版本不合乎预期。
同时,咱们也反对第三方的事件回调,能够更快的集成进三方零碎中。
另外,咱们对于某些须要 724 小时不间断的高频次短周期探测用例,咱们还实现了另外一套常驻分布式架构,这套架构应用一个集群内的 ProbeOperator 监听 Probe Config CRD 变动,在探测 pod 中周而复始的执行探测逻辑。这套架构,完满复用了 KubeProbe 核心端提供的告警 / 根因剖析 / 公布阻断等等附加性能,同时应用了规范 Operator 的云原生架构设计,常驻体系带来了极大的探测频率晋升 (因为去掉了创立巡检 pod 和清理数据的开销) 根本能够做到对集群的 724 小时无缝笼罩,同时便于对外集成。
另外还有一个必须要提的十分重要的点,即平台只是提供了一个平台层的能力反对,真正这个货色要起作用,还是要看在这个平台上构建的用例是否丰盛,能不能不便的让更多人进来写各种巡检和探测用例。就像测试平台很重要,但测试用例比测试平台更重要这个情理一样。一些通用的 workload 探测,组件探测,诚然能发现很多管控链路上的问题,然而更多的问题,甚至业务层的问题裸露,实际上依赖于基础设施和业务层同学的共同努力。
从咱们的实际上来说,测试同学和业务同学奉献了很多相干的查看用例,比方测试同学奉献的 ACK & ASK 的创立删除全链路探测巡检,金丝雀业务全链路扩容用例,比方本地生存同学的 PaaS 平台利用查看等等,也失去了很多稳定性上的后果和收益。目前咱们保护的巡检 / 探测用例有数十个,明年有机会破百,巡检 / 探测次数近 3000 万次,明年可能会过亿。目前能够提前发现 99% 以上的集群管控问题和隐患,成果是十分好的。
发现问题之后:根因剖析和事件处理
接下来咱们聊聊发现问题之后的事件,这里有一个相似于问诊对话的例子,患者发现“哎呀我不难受了!”这就是发现问题。医生参考各种化验单,同时做了信息聚合剖析推断,通知患者“你曾经 24 小时没睡觉了,你睡不着是因为你很焦虑,你焦虑的根因是因为先天就要期末考试了。”这便是定位问题根因,而后针对根因去解决这个问题,他通知患者“不要放心,我刚收到的音讯,小学生曾经不须要期末考试了。”这个过程肯定要快!
来自探测链路的告警内容往往是混沌的,和数据监控告警是有所差别的。就像上文提到的,链路探测告警的告警很可能就是一句患者的我不难受了,须要你作为医生去判断,为什么他不难受了呢?根因是什么。而数据监控很多时候自身就代表了起因,比方 Etcd OOM,用已有的 oncall 教训可能得不到最好的成果。
另外疾速定位问题和根因剖析,是一个树状的搜寻,教训加工判断的过程,也就是如何从一个混沌的表象推断出根因,外围是逻辑。
这和衰弱体检是不同的,衰弱体检是列出查看项 1,2,3,4,5…… 而后通知你一堆数值。很多时候,即便存在体检中心,咱们依然也须要医院的业余医生来为您解读和判断病情,不是吗?
同时,根因剖析 / 问题自愈的关键在于专家教训的下沉,也就是把专家教训下沉到零碎中去,专家教训的下沉带来的最大收益是可复用可输入。你能够想一下,如果咱们把一个最业余的医生的能力放进零碎里,他是不是更不便的为每一个人剖析病情呢?
这便是 KubeProbe 发现问题之后的全流程,咱们首先会通过一个咱们自建的中心化根因剖析零碎,在这里咱们会聚合剖析所有和本次失败相干的信息,包含事件 / 日志 / 变更 / 告警 / 组件降级等等,咱们将这些信息进行聚合剖析,并对事件做关联解决,最终通过一个树状的剖析零碎初步定位出某次探测失败的起因,比如说 APIServer 超时或者 etcd 断连等等。
此外我再补充一点,文本联想也是一个很好的根因剖析形式,咱们能够通过机器学习训练文本辨认的形式来联想出和这种失败 case 最关联的根因,这种 AIOps 的工作咱们只是稍微波及,还在继续的摸索中,咱们的数据量十分大,我认为这肯定是将来的方向之一。
KubeProbe 根因剖析和后置解决全流程
上图的左下方是某次咱们失败的告警,它通过根因剖析零碎之后发现首先最外围,最关联,最大的起因可能是 APIserver 的连贯断开并且以后曾经复原,所以可能只是偶发的网络抖动,咱们临时不必特地关注,但此时能够看到置信度为 90%。
另外还有一些可能的起因都会关联起来。比方某个组件,这次探测它是由某一个组件公布登程的,它的公布人是 XXX,咱们能够察看这个公布对 API server 会产生某些影响,是否屡次 list watch 不合乎预期,而后把 API server list watch 出问题了,置信度有 50%。
当咱们失去一个初步的起因之后,咱们会进入二次确认零碎做二次的起因确认,比方咱们判断起因可能是 APIServer 超时 /etcd 断联 / 节点超时等, 咱们就会主动从新拉取一下 APIServer 接口,看一下此时是否依然超时,是否复原,如果复原了,咱们就一般告警,并且通知用户,当初没事了,然而你得关注。如果没复原,那这就很重大了,属于最高优先级,间接电话告警。
就是这个思路,如果有零碎无奈定位的问题,并且继续无奈定位,咱们也会触发高级别告警,并且会减少相干的根因剖析辨认树逻辑。
过多的告警等于没有告警,我是最厌恶告警海的。从教训上讲,当咱们构建了一套这样的根因剖析 + 二次确认 + 后置查看零碎之后,咱们的 Oncall 老本降落了 90% 以上,并且还可能继续降落,终态能够说是无人值守,大家也能够试试相似的工作,能够说是投入小,奏效大。自从这些零碎建设起来当前,咱们能够骄傲的说,咱们用很小的精力 Oncall 了每一个告警条目(对,是每一条告警,是数千个集群,数千万次探测巡检的每一条告警)并且不会有任何脱漏了。
最初是一些给 Oncall 人员的小甜品,Chat-ops。
基于 NLP 语义辨认的 Chat-ops 零碎
咱们利用钉钉提供的 NLP 机器人,构建了一套比较完善的 Chat-ops 零碎,这样之后咱们的 Oncall 人员就能够很不便的在告警群里通过聊天的形式操作 KubeProbe 相干性能了,比方:重跑失败探测,查问集群状态,拉取诊断信息,查问探测日志,集群告警静默。
上图是咱们操作 Chat-ops 零碎的过程。这个过程十分不便。
比方早晨我曾经再被窝里了,这时候它给我了一个告警,比方某个集群之前呈现了某次失败但以后曾经复原了,须要我关注一下。
既然我关注了,我便心愿某一个罕用例再跑一次(它可能周期比拟长,例如一个钟头),因为短链路的用例可能随时都在跑,此时我便通知机器人再跑一次,机器人就会辨认我的语义,将集群再跑一次。跑完之后,我再通过查问状态看一下这个集群以后的状态怎么样了,这样是十分不便的,有时候你早晨下班了,或者是在路上,或者是在被窝里,都也能够很难受的去 on-call 一个零碎了。
Demo 示例
1、公布
2、探测列表
3、探测 Pod 开始运行
4、探测后果
5、根因剖析 & 告警
6、Chat-ops
点击“ 此处 ”即可下载《云原生与云将来的新可能》电子书全部内容。
近期热门
# 云原生与云将来的新可能 #
复制并返回下方链接,即可收费下载电子书
https://developer.aliyun.com/topic/download?id=8265