How to build Kubernetes Native Cloud side efficient collaborative network
导读:OpenYurt是阿里巴巴开源的云边协同一体化架构,与同类开源方案相比,OpenYurt拥有可实现边缘计算全场景覆盖的能力。
- OpenYurt是如何在弱网和断网环境下实现边缘自治的——YurtHub
- OpenYurt另一个核心能力——云边通信,以及相关组件Yurttunnel
Yurttunnel使用场景
在应用的部署和运维过程中,用户常常需要获取应用的日志,或直接登录到应用的运行环境中进行调试。在 Kubernetes 环境中,我们通常使用 kubectl log,kubectl exec 等指令来实现这些需求。如下图所示,在 kubectl 请求链路上, kubelet 将扮演服务器端,负责处理由 kube-apiserver(KAS) 转发来的请求,这就要求 KAS 和 kubelet 之间需要存在一条网络通路,允许 KAS 主动访问 kubelet。 然而,在边缘计算场景中,边缘节点常位于本地专有网络中,这虽然保证了边缘节点的安全,但也造成位于云端管控节点的KAS无法直接访问位于边缘节点的kubelet。因此,为了支持通过云端节点对边缘端应用进行运维操作,我们必须在云、边之间建立反向运维通道。
反向通道
Yurttunnel是OpenYurt近期开源的一个重要组件,用来解决云边通信问题。反向通道是解决跨网络通信的一种常见方式,而 Yurttunnel 的本质就是一个反向通道。一个边缘集群下属的节点常位于不同的 network region 中,而位于同一个 region 内的节点之间是可以相互通信的,因此在设置反向通道时,我们只需保证在每个 region 内设置一个与 proxy server 相连的 agent 即可。具体包括以下几个步骤:
-
在管控组件所在网络内,部署 proxy server。
-
proxy server 对外开放一个公网可以访问的 IP。
-
在每个 region 部署个 agent,并通过 server 的公网 IP 与 server 建立长连接。
-
管控组件对边缘节点的访问请求都将转发致 proxy server。
-
proxy server 再将请求通过对应的长连接发往目标节点。
在 Yurttunnel 中,我们选择使用上游项目apiserver-network-proxy(ANP) 来实现server 和 agent 间的通信。ANP 是基于 kubernetes 1.16 Alpha 新功能EgressSelector 开发,意在实现 Kubernetes 集群组件的跨 intranet 通信(例如,master 位于管控 VPC,而 kubelet 等其他组件位于用户 VPC)。
读者可能会好奇,既然 OpenYurt 是基于 ACK@Edge 开源的,而在生产环境中, ACK@Edge 的云边运维通道使用的是自研组件 tunnellib,那为什么在开源版本里我们要选用一个新的组件呢?这里不得不再次提到 OpenYurt 的核心设计理念 “Extend upstream Kubernetes to Edge”。
诚然,tunnellib 经过了复杂线上环境的考验,组件性能稳定,但我们更希望能与上游保持最大的技术公约数,让 OpenYurt 的用户体验更接近原生 Kubernetes ;同时,在 ACK@Edge 的开发和运维过程中,我们发现,边缘集群的许多需求也同样存在于其他场景中(例如,大多数云厂商也需要实现节点跨网络通信),并且运维通道的传输效率也能进一步优化(4.5章将详述优化过程)。因此,秉承开放分享、平等普惠的开源精神,我们希望能将开发和运维过程中积累的的宝贵经验在上游社区与更多的开发者分享。
ANP并非开箱即用
然而 ANP 项目仍处于起步阶段,功能尚未完善,许多问题仍有待解决。我们从实践中发现的主要问题包括:
-
如何转发云端节点的请求 -- 反向通道正常工作的一个前提是,管控节点发往边缘节点的请求必须先经过 proxy server。对于 Kubernetes 1.16 + 版本,KAS 能借由 EgressSelector 将发往节点的 请求先发往指定的 proxy server。但对于 1.16 以前的版本,KAS 及其他管控组件(Prometheus 和 metrics server)只能直接访问节点,而不能绕道 proxy server。可以预见的是,部分用户在短期内,仍将使用 1.16 以前的版本,并且 Prometheus 和 metrics server 等管控组件在短期内也没有支持 EgressSelector 的计划。因此,我们要解决的第一个问题是,如何将管控组件发往节点的请求转发致 proxy server。
-
如何确保 server 副本覆盖所有的 region -- 在生产环境中,一个边缘集群常常包含上万个节点,并同时服务上百名用户,如果一个集群只有一个 proxy server, 那么,一旦 proxy server 出现故障,所有用户都将无法对位于边缘节点上的 pod 进行操作。因此,我们必须同时部署多个 proxy server 副本以保证集群高可用。同时,proxy server 的工作负荷将随着访问流量的增大而增大,用户的访问延时也势必增加。因此在部署 proxy server 时,我们还需考虑如何对 proxy server 进行水平拓展,以应对高并发场景。一个应对单点故障和高并发场景的经典解决方案是,部署多个 proxy server 副本,并使用负载均衡进行流量分发。然而在 OpenYurt 场景下,对于 KAS 发来的任意请求,LoadBalancer (LB) 会转发给哪个 server 副本是不可控的,因此,需要解决的第二个问题是,如何保证每个 server 副本都能与所有的 agent 建立连接。
-
如何将请求转发给正确的 agent -- 在运行过程中,proxy server 在收到请求后,需根据请求的 destination IP,将请求转发至位于对应 network region 内的 agent。然而,ANP目前的实现,假设所有的节点都位于一个网络空间内, server 会随机挑选一个 agent 转发请求。因此,我们需要解决的第三个问题是,如何将请求正确地转发给指定的 agent。
-
如何解除组件对节点证书的依赖 -- 在运行时,我们需要为 server 提供一套 TLS 证书,以实现 server 与 KAS,server 与 agent 间的安全通信。同时,我们也需要为 agent 准备一套 TLS client 证书,用以建立 agent 和 server 间的 gRPC 信道。ANP 目前的实现,要求 server 必须和 KAS 部署在同一个节点上,并且在启动时挂载节点 volume 共享 KAS tls 证书。同样,agent 也需要在启动时挂载 volume 共享 kubelet tls 证书。这无形中降低了部署的灵活性,造成了组件对节点证书的强依赖,在有些情况下,用户可能希望将 server 部署在非 KAS 所在节点上。因此,另一个需要关注的问题是,如何解除组件对节点证书的依赖。
-
如何缩小 Tunnel 带宽 -- ANP 的一个核心设计思想,是使用 gRPC 封装 KAS 所有对外 HTTP 请求。这里选择 gRPC,主要是看重其对流(stream)的支持和清晰的接口规范,此外,强类型的客户端和服务器端可以有效减少运行时错误,提高系统稳定性。然而,我们也发现,相较于直接使用 TCP 协议,采用 ANP 也会带来额外的开销增加带宽。从产品层面考虑,Tunnel 流量走的是公网,带宽的增加也意味着用户成本的增加。因此,一个非常重要的问题是,在提高系统稳定性的同时,我们是否也能缩小带宽?