随着企业的业务规模不断扩大,Kubernetes 的使用也从单集群逐步扩展到多集群部署。多集群环境下,集群之间的通信成为一个重要的研究课题。本文将介绍五种跨 Kubernetes 集群通信的方案的基本原理,优点及其局限性。
1
1. Underlay 网络
这类网络插件包括 macvlan ( https://www.cni.dev/plugins/current/main/macvlan/ )/ipvlan ( https://www.cni.dev/plugins/current/main/ipvlan/ )/Kube-OVN underlay ( https://kubeovn.github.io/docs/stable/start/underlay/ ) 以及各种云上的 VPC CNI 等。
基本原理:
Underlay 网络从 CNI(容器网络接口)的角度来看是最简单的方式。这种方式依赖于底层基础设施在网络层面实现打通。例如,使用公有云上的 VPC Peering 或者物理网络配置路由和大二层。当底层网络实现了连通,跨集群的容器网络就自然连通了。
优点:
CNI 角度最为简单,无需额外操作。
架构上清晰,把跨集群通信的责任交给底层网络。
局限性:
依赖于特定 CNI,Underlay 类型的网络场景使用范围有限,有些情况只能使用 Overlay 网络。
在异构的环境,比如多云之间、公有云和私有云之间打通存在困难。
只是做了基础的容器网络通信打通,更上层的服务发现,域名和网络策略等功能存在缺失。
一次性打通所有集群的容器网络,缺乏细粒度的控制。
2
2. 提供跨集群通信能力的 Overlay CNI
在无法使用 Underlay 网络的情况下,一些特定的 CNI 在 Overlay 层面也实现了跨集群。例如 Cilium Cluster Mesh ( https://cilium.io/use-cases/cluster-mesh/ ), Antrea Multi-Cluster ( https://antrea.io/docs/v2.0.0/docs/multicluster/quick-start/ ) 和 Kube-OVN with ovn-ic ( https://kubeovn.github.io/docs/stable/en/advance/with-ovn-ic/ )。
基本原理:
这些 CNI 的实现方案其实大体一致,通过选择一组集群内的节点作为网关节点,然后网关节点之间建立隧道,跨集群流量通过网关节点转发。
优点:
- CNI 自包含跨集群功能,无需额外组件支持。
局限性:
依赖特定 CNI,无法实现不同 CNI 集群之间的通信。
无法处理 CIDR 重叠的情况,需要提前规划好网段。
除了 Cilium 实现的比较完整,把跨集群的服务发现和网络策略都实现了,其他的仅实现基础容器网络通信。
一次性打通所有集群的容器网络,缺乏细粒度的控制。
3
3. Submariner
由于跨集群网络互通存在着通用的需求,在实现上也存在着类似,各个 CNI 其实存在着一些重复造轮子的工作。Submariner ( https://submariner.io/ ) 作为一款 CNI 无关的跨集群网络插件提供了一种通用的能力,能将不同 CNI 的集群组成一个网络达到互通。Submariner 最早由 Rancher 的工程师创建,现在已经是 CNCF Sandbox 项目了,目前看红帽的工程师也在积极参与这个项目。
基本原理:
Submariner 选择集群内的网关节点,网关节点通过 VXLAN 通信。跨集群流量通过 VXLAN 传输。Submariner 依赖 CNI 将 egress 流量先发送到宿主机的网络内,然后再进行转发。此外,Submariner 部署了一组 CoreDNS 实现跨集群服务发现,并使用 Globalnet Controller 解决 CIDR 重叠问题。
优点:
一定程度上 CNI 无关,可以连接不同 CNI 的集群。
实现了跨集群服务发现,支持 Service 和域名解析。
支持 CIDR 重叠的集群通信,避免了集群部署后想互联却发现 IP 冲突的尴尬。
局限性:
并不是所有的 CNI 都可用,如果像 macvlan 或者 cilium 短路这种宿主机看不到流量的情况,就没有办法拦截流量到自己的隧道了。
Gateway 目前是主备模式,没法横向负载均衡,在大流量的场景下可能存在性能瓶颈。
一次性打通所有集群的容器网络,缺乏细粒度的控制。
4
4. Skupper
Skupper ( https://skupper.io/index.html ) 是我认为几个方案里最有意思的,它能够按需进行 Service 层面的网络打通,避免了一次完全打通的控制问题。而且很创新的使用了七层消息队列的方式来实现,可以说是对底层网络和 CNI 完全无依赖,上手也十分简单。目前 Skupper 看贡献者主要是红帽的工程师。
基本原理:
和上述几个方案使用隧道将容器 IP 直接打通不同,Skupper 提出了一个 VAN(Virtual Application Networks)的概念,要在 7 层将网络打通。简单说就是不把 IP 直接打通而是把 Service 拉通,概念上和 ServiceExporter,ServiceImporter 类似,但是这个项目启动的比较早,当时还没有这些社区提出来的概念,在当时应该算个很创新的想法了
在实现上 Skupper 也另辟蹊径,用的是个消息队列的实现,多个集群之间组成了一个大的消息队列,跨集群通信的数据包发送到这个消息队列里。另一端再去消费这个数据包。思路上其实类似反向代理,但用消息队列来实现也是个很开脑洞的想法。把 Service 变成了一个消息的订阅点来提供消费,这样就可以按需的在服务端和客户端之间建立一个消息队列,通过消息队列的概念去管理和控制这个消息通路。
优点:
CNI 兼容性好,完全不依赖 CNI 的行为在应用层进行数据包的打通
上手简单,不需要太复杂的前期网络规划,也没有 CIDR 不重叠要求。提供了 CLI 方便临时测试和快速演示
并不是容器网络互通而是按需将 Service 打通,可以做到细粒度的控制,对底层要求也更低
局限性:
文档介绍目前只支持 TCP 协议,UDP 和更底层的协议比如 ICMP 会有问题
由于是通过消息队列转发消息,IP 信息会丢失
通过消息队列转发的思路还是有些奇怪,在性能方面比如延迟和吞吐量上可能会有一些损失
而且 TCP 本身是有状态的,能否完全转换成消息队列的形式,兼容性如何是个疑问
5
5. KubeSlice
KubeSlice ( https://kubeslice.io/documentation/open-source/1.3.0 ) 是刚刚进入 CNCF Sandbox 的一个项目。上述的方案基于隧道做的没法做到细粒度控制和 CNI 完全兼容,基于应用层做的又没法做到网络协议完全兼容。KubeSlice 提供了一个新的思路,尝试同时解决这两个问题。
基本原理:
KubeSlice 最底层的思路十分简单粗暴,就是按需给 Pod 动态插入一块网卡,在这个网卡上面做跨集群的 Overlay,然后再在这个 Overlay 网络上面实现服务发现,和网络策略。用户可以按需的将跨集群的几个 Namespace 或者 某几个 Pod 组成一个网络,在可以使实现灵活的细粒度管控基础上由于走的是基于网卡的二层网络,也实现了网络协议的最大兼容性。
优点:
CNI 兼容性好,由于是额外插入了一块网卡完全不关心原先的 CNI 是什么,并且是额外的网络也不用担心原先网络地址是否有冲突的问题
网络协议兼容性好,同样是由于额外有了一块网卡做流量转发,所有的网络协议都是兼容的。
灵活度高,KubeSlice 提供了命令行工具可以动态的创建和加入网络,用户可以选择按应用的需求创建多个跨集群的虚拟网络
功能完善,按照文档的说法,该项目在额外的这个 Overlay 网络上实现了服务发现,DNS,QoS,Networkpolicy 和监控,可以说把各个方面都覆盖到了
局限性:
由于本质上是双网卡,应用侧需要感知这个事情选择合适的网络,可能会涉及到应用改造
由于跨集群走的是另一个网卡不是 Pod 主网卡的 IP,对监控和追踪等外部系统可能涉及到改造
目前看文档应该是一个内部的项目进行开源,文档里很多使用方式和 API 介绍的不是特别清楚,需要对着 reference 慢慢猜每个参数到底是什么意思。功能上看上去确实比较全,但能让外部用户很好的使用的话文档还有很多需要完善的地方。
6
总结
在 Kubernetes 多集群环境中实现高效通信有多种方案可供选择。每种方案都有其优点和局限性,用户可以根据具体需求和环境选择合适的方案。