导语:边缘计算模式下,云端的控制中心和边缘端的设备之间网络环境较复杂,网络质量差次不齐没有保障。用户往往希望在弱网环境下,边缘容器能提供高可用的业务能力。TKE 边缘容器团队在弱网环境下提出了边缘自治功能。本文着重介绍了边缘容器在弱网环境下为了保证业务高可用而做的工作。
边缘计算使用的边缘设备数量庞大、分布全国各地,网络环境复杂,因特网、以太网、5G、WIFI 等形态均有可能。因此,云端的控制中心和边缘端的设备之间网络环境较复杂,网络质量差次不齐没有保障。
kubernetes 传统工作模式是所有组件 list-watch kube-apiserver,然后 reconcile 各种资源到期望状态。各节点的健康都强依赖于其与 kube-apiserver 通信的稳定。kubernetes 在传统的集群环境上工作很完美,因为大多数集群都能保证在一个局域网内。然而,在边缘计算的业务场景下,有一个稳定的网络环境着实是一件奢侈的事情。
在这样的背景下,如何保证边缘集群的业务高可用性以及服务高可用性?一直都是一个难题。为此我们腾讯云边缘容器团队(TKE@EDGE)设计了两个利器来专门啃下这块硬骨头,本篇将重点讲第一个利器——边缘自治。
(注:此文提到的网络环境,都是指节点与云端的网络环境,而不是业务运行所在环境。)
我们来以一个常见的厂房模型来介绍一下用户在弱网环境下使用传统 kubernetes 遇到的问题以及 TKE 边缘容器团队在此类场景下提出的解决方案。
如上图所示,该案例采用的部署模式为:用户在腾讯云公有云上购买了几台 CVM 机器作为 master 节点,其上部署了 kube-apiserver、kube-controller-manager、kube-scheduler 三大组件。然后根据业务需求,为每一个厂房都创建多个边缘 worker 节点,部署 kubelet 和 kube-proxy 以及 dockerd。同厂房节点之间可以互相访问, 不同厂房节点网络不互通。比如两个分布在北京和广州的厂房的边缘节点虽然可以归属于同一个集群,但是它们之间的网络是不互通的。每个厂房内所有节点会通过公网连接至云端管控端,但是这个网络通道都属于不可靠的弱网环境。
厂房A在北京地区,厂房B在广州地区。二者之间是不能互通的。
用户通过 kubernetes 管理平台进行workload的管理,master 与 worker 节点所在的厂房之间的网络环境网络环境是不能保证的,可能弱网A断网,网络B仍然正常。用户在这样的场景下,提出了几个需求:
对于用户来说,这些诉求是他们的基本需求,也是其业务上云的关键因素。用户想要既享受 kubernetes 带来方便的管理运维,同时也要具备弱网环境下的容灾能力。这对传统标准 kubernentes 解决方案提出了挑战。
我们来温习一下标准的 kubernentes 下,如果节点断网失联并且发生异常重启的行为后,会出现哪些现象呢?
我们依次来看,首先,在传统的模式下,节点是否健康取决于节点上 kubelet 组件的心跳或者续租。如果网络断了,云端组件当然会认为节点是不可用状态。这个状态可以提示用户,该节点可能有异常,需要运维介入。同时,由于 kubelet 还在接管所有本机 Pod,即使业务容器异常退出,容器也是可以继续被拉起的。失联的节点上所有的 Pod ,它们的 IP 都会被从 Endpoint list 中摘除,导致微服务不能访问到这个节点,在传统 kubernentes 集群中,这是一个高可用的措施。但是在边缘集群内,这个“节点不可用=服务不可用”等式是否还成立呢?这个地方是需要探讨的,其实很多业务场景下,用户希望节点即使和云端断网,该节点上的 Pod 也要能继续对外提供服务。
因此我们团队认为,在边缘容器的场景下,单纯与云端网络失联是不能被粗暴地认为“服务不可用”的。为此我们特意设计了第二件利器——“分布式节点健康检查”插件,来解决这个痛点,该功能会在后续文章进行详细介绍。
下面重头戏来了,断网的节点重启一下,容器还会在吗?服务还可用吗?回答是,容器当然不在喽。而且容器不在了,服务肯定不能访问了。用户最关键的需求,显然在传统的 kubernentes 模式下,是不能满足的。
那么来看看我们边缘计算的利器——边缘自治功能能达到的效果吧。
我们为了达到最符合用户的效果,配合使用了分布式节点健康检查插件功能,来保证节点在断网情况下即使节点被置为NotReady 状态,但是服务还是继续可用。同时该节点上的 Pod 也不会在新的节点上重新拉起新的 Pod 副本。
我们在极端网络环境下,将运行业务的多个节点手动执行重启操作来模拟节点异常重启场景。节点重启之后,节点组件正常启动,之前的 Pod 也会被自动被拉起,并且运行正常,处于 Running 状态。
那服务以及网络呢?我们测试后发现,重启多个节点之后,我们在节点手动请求 Pod ip,可以访问成功;进入 Pod A 内部分别请求在同一个节点上的 Pod B 以及另一个节点上的 Pod C(需要同一个厂房环境),都可以访问成功;在 Pod A 解析 同一厂房的 Service A, 可以解析并成功。最后,在外部对于该厂房内部的服务进行请求,访问成功。
如此看来,边缘自治功能,有效解决了传统 kubernetes 在弱网环境下所不能解决的用户痛点。
我们团队为边缘自治功能打磨了很久,涉及方面众多,修改以及设计的地方比较多,本文不太介绍具体代码实现细节。有兴趣的同学可以和TKE边缘容器同学共同进行学习探讨。在此我简单分享一些设计原理。
kubernetes 是典型的通过数据进行交互的架构。解决数据问题就能提供一个夯实的基础。所以弱网环境的边缘自治,首当其冲的,最最最需要解决的问题就是数据问题。
考虑到弱网、断网情况,需要保证节点的组件与云端组件“通信”,或者说让节点认为此时还是可以“通信”的。如上图所示,我们在边缘端加了一层镜像 lite-apiserver 组件。边缘节点上所有对 kube-apiserver 的请求都会发往 lite-apiserver,并由 lite-apiserver 转发到 kube-apiserver。对于边缘节点来说,lite-apiserver 提供的功能就是 kube-apiserver 一样,但是一方面 lite-apiserver 只对本节点有效,另一方面相比较标准的 kube-apiserver,我们对于 lite-apiserver 进行了裁剪,大幅度降低了其资源占用。我们在没有修改原生 kube-apiserver 的情况下,实现了。在网络通畅的情况下,lite-apiserver 组件对于节点组件来说是透明的。当网络异常情况,lite-apiserver 组件会把本节点需要的数据返回给节点上组件,保证节点组件不会受网络异常情况影响。
OK,lite-apiserver 机制保证了断网情况下,节点也不会和“apiserver”失联。既然节点可以拉取到本节点对应的数据,那么业务 Pod 也就能够被 kubelet 成功拉起来。下一步就是解决 Pod 之间的互相访问的问题了。
在边缘容器场景下,考虑到适配性以及易用性,我们采用了 flannel 组件的 vxlan 模式作为网络解决方案。flannel 组件保证了跨节点之前的网络访问。节点上的flannel 以及每个 Pod 都有一些对应属于自己的网络信息,我们这里采用了网络快照机制,将专属于这些组件的网络信息定期快照,从而保证了断网环境下重启后网络可用。并且实现了同节点、跨节点 Pod 之间的网络互通。
用户业务对外正常提供服务,以及集群内微服务之间互相调用,这些问题都会涉及到域名解析。
如上图所示,在传统 kubernetes上,通过在集群中创建一个kube-dns deployment 来解决是来解决域名问题。但是边缘计算集群,所有节点可能是不在一个局域网,很可能是跨可用区的,各节点和 kube-dns 的访问无法保证,一个 kube-dns 的 deployment 不能满足边缘容器的需求。
在边缘容器场景下,采用 DaemonSet 方式部署kube-dns,保证每个节点都有可用的 kube-dns,同时修改每个节点上 kubelet 启动参数--cluster-dns
,将其指向本机IP。这样就保证了,即使断网情况下,也能解析 kubernetes service 的域名。
总结而言就是 lite-apiserver 机制为基础, kube-proxy、flannel、kube-dns 以及网络快照机制保证了边缘容器集群在弱网环境下的网络可靠性。
腾讯云边缘容器产品支持用户在云端通过 kubernetes 方式来管理边缘节点,支持管控平台与 work 节点网络环境分离,具备弱网环境下的容灾能力,支持用户自定义网络流量,并且所有核心组件都与开源 kubernentes 保持一致,目前已经支持 1.18 版本。
目前 TKE@EDGE 具备公有云和私有云两种产品形态,欢迎来官网体验使用边缘容器公有云产品( https://console.cloud.tencent.com/tke2/edge ),产品入口目前为白名单可见,请联系文章作者开通白名单。
后续我们还会有一系列工作,来加强在弱网环境下的工作稳定性。
我们的解决方案对于原生使用 kubernetes 的方案和理念都有所不同,但是我个人认为紧跟业务脚步的产品以及技术才是最有价值的。个人技术能力有限,表达可能有疏漏,技术可能有错误,欢迎大家指出错误,共同进步。
这里欢迎更多有业务场景需要、感兴趣的同学使用、加入、体验,提需求,共优化。欢迎扫码加腾小云同学好友,一起进群讨论。