驭势科技(UISEE)是国内领先的自动驾驶公司,致力于为全行业、全场景提供 AI 驾驶服务,交付赋能出行和物流新生态的 AI 驾驶员。由于需要保障各个场景下 “真 · 无人”(即无安全员在车上或跟车)的业务运作,我们比较注重在 “云端大脑” 上做了一些保障其高可用和可观察性方面的实践。
让我们假设有这样一个场景:在一个厂区运行了几十台的无人物流拖车,考虑到 “真无人” 环境下的安全运营,我们会采取车云连接长时间断开(一般为秒级)即停车的策略;如果在运营的过程中,云端出现故障且缺乏高可用能力,这将造成所有车辆停运。显然这对业务运营会造成巨大影响,因此云平台的稳定性和高可用性是非常重要和关键的。
我们和 KubeSphere 的结缘可以说是 “始于颜值,陷于才华”。早在 KubeSphere 2.0 发布之时,我们因缘际会在社区的新闻中留意到这个产品,并马上被它 “小清新” 的界面所吸引。于是,从 2.0 开始我们便开始在私有云上进行小范围试用,并在 2.1 发布之后开始投入到我们公有云环境的管理中使用。
KubeSphere 3.0 是一个非常重要的里程碑发布,它带来了 Kubernetes 多集群管理的能力、进一步增强了在监控和告警方面的能力,并在 3.1 中持续对这些能力进行夯实。由此,我们也开始更大范围地将 KubeSphere 应用到我们自有的和客户托管的集群(及在其中运行的工作负载)的管理上,同时我们也在进一步探索如何将现有的 DevOps 环境和 KubeSphere 做整合,最终的目标还是希望将 KubeSphere 打造成我们内部面向云原生各应用、服务、平台的统一入口和集中管理的核心。
正是由于 KubeSphere 提供了这样优秀的管控能力,使得我们有了更多时间从业务角度去提升云平台的可用性。这次分享的两个内容就是我们早期和现在正在推进的两项可用性相关的实践。
“高可用” 方面,我们期望解决的问题是如何确保云端服务出现故障时可以用最快的速度重新恢复到稳定运行的状态。
限定区域 L4 无人驾驶场景的 “高可用” 诉求
“高可用” 从时间量化的角度通常就是几个 9 级别选择,但落到具体的业务场景,所面临的问题和挑战却是各不相同的。如上图所列举的,对于我们 “限定区域 L4 无人驾驶场景” 而言,以 toB 业务为主所造成的客户私有云种类繁多、对于恢复过程容忍度不同、以及客户定制服务产生的历史包袱较多是制约我们构建高可用方案的几个主要问题。面对这些限制,我们选择了一个比较 “简单粗暴” 的思路,试图 “化繁为简” 跳出跨云高可用成本高、为服务附加高可用能力融合风险高的常见问题包围圈。
一种通过 Operator 实热备切换的高可用方法
如上图所示,这个方案的思路很直接 —— 实现服务 Pod 状态监测并在状态异常时进行主备 Pod 切换。如果我们从 Controller 的 “Observe - Analyze - Act” 体系来看,它做了如下工作:
在这个 Operator 的开发框架上,我们选用了 Kubernetes 官方社区的 Operator SDK,即 Kubebuilder[1]。从技术上看,它对于编写 Controller 通常需要的核心组件 client-go 有比较好的封装,可以帮助开发者更专注于业务逻辑的开发;从社区的支持角度看,发展也比较平稳,这里也向大家推荐在使用中可以参考云原生社区组织翻译的 Kubebuilder 中文文档[2]。
行百里者半九十:高可用功能落地的长尾在于测试
由于 “高可用” 功能的特殊性,它的测试尤其重要,但常规的测试手段可能并不是很适用(这里存在一个有意思的 “悖论”:测试是为了发现问题,而高可用的启用会避免发生问题)。所以我们在完成这个 Operator 的开发后,其实更多的时间是花在测试方面,在这里我们主要实施了三个方面的测试工作:
简单总结一下,在这个 “高可用” 方面的早期实践过程中,我们有几点体会:首先,还是需要熟悉 Kubernetes Controller 以及 client-go 类库的核心机制;其次,找一个趁手的 Operator 开发框架会大大提升你的研发效率;最后但也是最重要的一点,高可用这块的研发工作其实是由 “20% 时间的开发 + 80% 的全方位测试” 组成的,做好测试、做好全面测试非常非常重要。
“可观察” 方面,我们期望解决的问题是在服务故障恢复后,如何确保我们能够尽可能快的定位到问题的根源,以便尽早真正消除问题隐患。
无人驾驶车云一体化架构下的 “可观察” 诉求
“车云一体化” 架构是无人驾驶的一个重要核心,从云端视角来看,它的一个巨大挑战就是业务链路非常长,远长于传统的互联网纯云端的业务链路。这个超长链路上任意一点的问题都有可能引发故障,轻则告警、重则导致车辆异常离线,所以对于链路上的点点滴滴、各式各样的信息我们总是希望能够应收尽收,以便于定位问题。同时,纯粹的日志类数据也是不够的,因为链路太长且又分布在车云的不同地方,单靠日志不便于快速定位问题发生的区间从而进行有针对性的问题挖掘。
为了便于大家更具象的了解链路之长,下图我们给出了一个抽象的 “车云一体化” 架构图,感兴趣的朋友可以数一下这 “7 x 2” 的调用链路。
通过 SkyWalking 实现车云全链路追踪
Apache SkyWalking[7] 是社区中一个优秀而且活跃的可观察性平台项目,它同时提供了 Logging、Metrics、Tracing 可观察性三元组的功能,其中尤以追踪能力最为扎实,关于追踪系统的一些基本概念推荐可以参看吴晟老师翻译的 OpenTracing 概念和术语[8]。为了方便大家对后续内容有更好的把握,也弥补一下演讲时无法展开的细节,这边也简单整理几个关键点供大家参考:
SkyWalking 的插件体系是保障我们得以在一个庞大的微服务架构中进行埋点的基础,官方为 Java、Python、Go、 Node.js 等语言都提供了插件,对 HTTP 框架、SQL、NoSQL、MQ、RPC 等都有插件支持(Java 的插件最为丰富,有 50+,其他语言的插件可能没有这么全面 )。我们基于 Go 和 Python 官方插件的研发思路,又进一步扩展和自制了一些插件,例如:
由于微服务架构中涉及的语言环境、中间件种类以及业务诉求通常都比较丰富,这导致在接入全链路追踪的过程中难免遇到各种主观和客观的坑,这里给大家介绍几个常见场景。
案例一:Kong 网关的插件链路接入问题
找不到官方插件是最常见的一种接入问题。比如我们在接入 SkyWalking 时,官方还未发布 SkyWalking 的 Kong 插件(5 月才发布)。我们因为业务需要在
Kong 中接入了自定义的一个权限插件,用于对 API 和资源的授权;这个插件会调用权限服务的接口进行授权。那么这个插件中的调用,也应属于调用链中的一环
,所以我们的解决思路是直接在权限插件中进行了埋点,具体形成的链路如下图所示。
案例二:跨线程/跨进程的链路接入问题
对于跨线程,这里给大家一个提示:可以使用函数 capture() 以及 continued();使用 Snapshot,为 Context 上下文创建快照。对于跨进程,我们遇到一个比较坑的坑是 Python 版本问题:Python 服务中新起一个进程后,原先进程的 SkyWalking Agent 在新进程中无法被使用;需要重新启动一个 Agent 才能正常使用,实践后发现 Python 3.9 可行,Python 3.5 中则会报错 “agent can only be started once”(找谁说理去。。。)
案例三:官方 Python Redis 插件 Pub/Sub 断路问题
这个案例是一个典型的官方插件不能覆盖现实业务场景的问题。官方提供的 Python 库中,有提供 Redis 插件;一开始我们认为安装了 Redis 插件,对于一切 Redis 操作,都能互相连接;但是实际上,对于 Pub/Sub 操作,链路是会断开的。
查看代码后发现,对于所有的 Redis 操作,插件都创建一个 ExitSpan。但是在我们的场景中,需要进行 Pub/Sub 操作;这导致两个操作都会创建 ExitSpan,而使链路无法相连。对于这种情况,最后我们通过改造了一下插件来解决问题,大家如果遇到类似情况也需要注意官方插件的功能定位。
案例四:MQTT Broker 的多种 Data Bridge 接入问题
一般来说,对 MQTT Broker 的追踪链路是 Publisher => Subscriber;但是也存在场景,MQTT Broker 接收到消息后,通过规则引擎调用通知中心的接口;而规则引擎调用接口时,没有办法把 Trace 信息放到 Header 中。
这是一个典型的中间件高级能力未被插件覆盖的问题。通常这种情况还是得就坡下驴,按实际情况做定制。比如这个案例中我们通过约定好参数名称,放到请求体中,在通知中心收到请求后,从请求体中抽取链路的 Context 的方式最终实现了下图的链路贯通。
最后也总结一下我们在 “可观察” 这部分的一些实践体会:首先,还是需要依托一个成熟的持续演进的工具/平台 ;其次,就是依靠它,同时也要和它一起不断成长、不断自我完善;最后, 断路不可怕,伟人说过 “星星之火,可以燎原”,明确目标、坚持努力,一定有机会解决问题的。
最后的最后,再次感谢 KubeSphere 团队为中国乃至全球的开源社区贡献了这么一个卓越的云原生产品,我们也希望能尽自己所能多参与社区建设,与 KubeSphere 社区共成长!
[1]Kubebuilder: https://github.com/kubernetes-sigs/kubebuilder
[2]Kubebuilder 中文文档: https://cloudnative.to/kubebuilder/
[3]Godog: https://github.com/cucumber/godog
[4]Gherkin: https://cucumber.io/docs/gherkin/reference/
[5]ChaosBlade: https://github.com/chaosblade-io/chaosblade
[6]Chaos Mesh: https://github.com/chaos-mesh/chaos-mesh
[7]Apache SkyWalking: https://skywalking.apache.org/
[8]OpenTracing 概念和术语: https://wu-sheng.gitbooks.io/opentracing-io/content/pages/spec.html
留言与评论(共有 0 条评论) “” |