其他分享
首页 > 其他分享> > OpenYurt 深度解读:如何构建 Kubernetes 原生云边高效协同网络?

OpenYurt 深度解读:如何构建 Kubernetes 原生云边高效协同网络?

作者:互联网

头图.png

作者 | 郑超

导读:OpenYurt 是阿里巴巴开源的云边协同一体化架构,与同类开源方案相比,OpenYurt 拥有可实现边缘计算全场景覆盖的能力。在之前的一篇文章中,我们介绍了 OpenYurt 是如何在弱网和断网场景下实现边缘自治的。本文作为 OpenYurt 系列文章的第四篇,我们将着重介绍 OpenYurt 的另一个核心能力——云边通信,以及相关组件 Yurttunnel。

使用场景

在应用的部署和运维过程中,用户常常需要获取应用的日志,或直接登录到应用的运行环境中进行调试。在 Kubernetes 环境中,我们通常使用 kubectl log,kubectl exec 等指令来实现这些需求。如下图所示,在 kubectl 请求链路上, kubelet 将扮演服务器端,负责处理由 kube-apiserver(KAS) 转发来的请求,这就要求 KAS 和 kubelet 之间需要存在一条网络通路,允许 KAS 主动访问 kubelet

1.png
图一:kubectl 执行流程

然而,在边缘计算场景中,边缘节点常位于本地专有网络中,这虽然保证了边缘节点的安全,但也造成位于云端管控节点的 KAS 无法直接访问位于边缘节点的 kubelet。因此,为了支持通过云端节点对边缘端应用进行运维操作,我们必须在云、边之间建立反向运维通道。

反向通道

Yurttunnel 是 OpenYurt 近期开源的一个重要组件,用来解决云边通信问题。反向通道是解决跨网络通信的一种常见方式,而 Yurttunnel 的本质就是一个反向通道。一个边缘集群下属的节点常位于不同的 network region 中,而位于同一个 region 内的节点之间是可以相互通信的,因此在设置反向通道时,我们只需保证在每个 region 内设置一个与 proxy server 相连的 agent 即可(如下图所示)。具体包括以下几个步骤:

2.png
图二

在 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 项目仍处于起步阶段,功能尚未完善,许多问题仍有待解决。我们从实践中发现的主要问题包括:

Yurttunnel 设计解析

1. 制定 DNAT 规则转发云端节点的请求

如前文所述,ANP 是基于上游新功能 EgressSelector 开发的,该功能允许用户在启动 KAS 时通过传入 egress configuration 来要求 KAS 将 egress 请求转发到指定的 proxy server。但由于我们需要兼顾新老版本的 Kubernetes 集群,并且考虑到,其他管控组件(Prometheus 和 metric server)并不支持 EgressSelector 特性,我们需要保证在无法使用 EgressSelector 的情况下也能将 KAS egress 请求转发致 proxy server。为此,我们在每一个云端管控节点上都部署一个 Yurttunnel Server 副本,并在 Server 中内嵌一个新组件 Iptabel Manager。Iptable Manager 会通过在宿主机的 Iptable 中的 OUTPUT 链中添加 DNAT 规则,将管控组件对节点的请求转发致 Yurttunnel Server。

同时,当启用 EgressSelector 后,KAS 对外请求都遵循一个统一的格式,因此我们新增一个组件, ANP interceptor。ANP interceptor 会负责截取从 master 发来的 http 请求,并将其封装成 EgressSelector 格式。Yurttunnel 请求转发的具体流程见图三。

3.png
图三:Yurttunnel 请求转发流程

2. 动态获取 Server 副本数

在上一节中,我们提到,我们将采用负载均衡的方式来管理 yurttunnel server,所有的 ingress 请求都会通过 LB 分发给一个 server 副本。由于我们无法预测 LB 会挑选哪个 server 副本,我们必须保证每个 server 副本都要与所有的 agent 建立连接。这里,我们将使用 ANP 自带的功能实现这一需求,具体流程如下:

该机制虽然帮助我们实现了 server 副本的全网段覆盖。但同时,也存在不可忽视的缺点,由于 agent 无法选择与哪个 server 副本建立连接,因此,为了连接所有的 server 副本,agent 必须反复访问 LB。在这个过程中,server 由于还没有与所有的 agent 建立连接,KAS 发来的请求可能无法转发至对应的节点。一个潜在的解决方案是,为每个 server 副本创建一个独立的 LB,负责与 agent 之间的连接,同时在 agent 端记录所有 server 副本对应 LB 的信息,这一方案能帮助 agent 快速地与所有的 server 副本建立连接。该方案的具体实现细节,目前仍在与上游社区的开发者讨论中。

3. 为 ANP 添加代理策略

在 OpenYurt 的网络模型下,边缘节点分布在不同的 network region 中,随机选择的 agent 可能无法将请求转发至位于其他 region 内的节点上。因此我们不得不修改 ANP server 底层代理转发的逻辑。然而,根据长期的经验,我们相信,proxy server 支持不同的代理策略,例如,将请求转发至指定数据中心,region,或者指定主机,是一个较为通用的需求。经过和 ANP 社区开发者讨论,我们决定重构 ANP 管理 agent 连接的接口,允许用户根据需求实现新的代理策略,并计划将该 feature 最终合入上游代码库。目前重构工作仍在进行中,在 Yurttunnel 第一个开源版本中,我们暂时采用以下配置:

我们计划在 OpenYurt 后续发布 Yurt Unit(边缘节点分区管控)之后,配合新增的 ANP 代理转发策略,实现 agent 的分区部署,和请求的分区转发。

4. 动态申请安全证书

为了解除 yurttunnel 组件对节点证书的依赖,我们在 yurttunnel 中新增 cert manager 组建,cert manager 会在 server 和 agent 运行后,向 KAS 提交 certificate signning request(CSR)。server 将使用申请到的证书来确保其与 KAS 和 agent 间的安全通信,agent 会使用申请到的证书确保其与 server 间 gRPC 信道的安全。由于 agent 和 kubelet 间是通过 tcp 协议连接,因此,我们无需为 agent 和 kubelet 间的连接准备证书。

5. 压缩 Tunnel 带宽,节约成本

在 3.5 中,我们提到,使用 gRPC 封装 Tunnel 虽然可以提高传输稳定性,但同时也会增加公网流量。这是否意味着稳定性和性能,我们只能二选一?通过对不同用户场景的分析,我们发现,在大多数情况下,用户使用运维通道是为了获取容器日志(即 kubectl log),而传统日志文件,存在许多相同的文本信息,因此我们推断使用 gzip 等压缩算法能有效缩小带宽。为了验证这一假设,我们在 ANP 底层的 gRPC 库中添加了 gzip compressor,并且对比了与使用原生 TCP 连接场景下的数据传输量。

我们考虑的第一个实验场景是,分别通过 TCP 连接和 ANP 获取同一 kubeproxy 容器的日志,我们截取了这一过程中 Tunnel 上双向 package 和 bytes 总量。

4.png
表 1: 原生 TCP V.S. ANP (kubectl logs kube-proxy)

如表 1 所示,通过使用 ANP, 总传输数据量下降了 29.93%

经过长时间运行,容器的日志文本常常可以达到十几兆,为了模拟获取大文本日志的场景。我们创建了一包含 10.5M systemd log(即 journalctl)的 ubuntu 容器,同样我们分别使用原生 TCP 连接和 ANP 传输该日志文件,并测量了 Tunnel 上的数据总量。

5.png
表 2: 原生 TCP V.S. ANP (large log file)

如表 2 所示,在日志文本较大的情况下,通过使用 ANP, 总传输数据量下降了 40.85%

由此可见,相较于原生 TCP 连接,ANP 不仅能提供更高的传输稳定性,还可以大幅降低公网流量。考虑到边缘集群动辄上万的节点规模,新的解决方案将帮助用户在公网流量方面节约大量开销。

Yurttunnel 系统架构

6.png
图四:Yurttunnel 系统架构

综上,Yurttunnel 主要包含以下组件:

总结与展望

Yurttunnel 作为 OpenYurt 近期开源的重要组件,打通了 OpenYurt 集群的云边通道,为边缘集群上的容器运维提供了一个统一的入口。通过对上游解决方案进行改造,Yurttunnel 不仅提供了更高的传输稳定性,也大幅降低了数据传输量。

OpenYurt 于 2020 年 5 月 29 日正式对外开源,借助社区和广大开发者的力量快速成长,开源仅 3 个月后就正式成为 CNCF 沙箱级别边缘计算云原生项目。未来,OpenYurt 将延续 “Extending your upstream Kubernetes to edge” 的核心设计理念,在选择与上游保持最大技术公约数的同时,发扬开源分享的精神,与广大开发者一起推进 Kubernetes 社区的进步。

 

 

原文链接
本文为阿里云原创内容,未经允许不得转载。

标签:Yurttunnel,请求,Kubernetes,云边,agent,server,ANP,OpenYurt,节点
来源: https://www.cnblogs.com/yunqishequ/p/13962374.html