2025-11-09 12:29:02
目前社区在 Kubernetes 实现网络多租户主流选型是 Kube-OVN 和 ovn-kubernetes,这两个方案本质上都是在物理网络上通过 OVS 和 OVN 的能力构建了一层 Overlay 虚拟网络。这种方案不太关心底层物理网络架构,有着比较好的兼容性,但是双层网络架构也加大了整体架构的复杂度。
最近我在调研 EVPN 这种物理网络多租户的方案,发现了 OpenPERouter 这个开源项目,他把 EVPN 的理念引入了容器网络,提供了一种新的在 Kubernetes 上实现多租户的方案。该方案不仅能统一软硬件网络架构,还在一定程度上能兼容现有 Calico 这种通过 BGP 方式发布路由的 CNI,我甚至已经看到通过少量工作就可以让 Calico 具备多租户能力的前景。虽然这个项目还在早期,但我认为这是一个相当不错的方向,未来很可能会成为构建大规模数据中心的一个有竞争力选型。
OVN 类方案的主要局限性有两个一个是集中式控制平面的规模限制,另一个就是网络复杂度。
尽管 Kube-OVN 在社区已经存在了上千节点的大规模案例,但是由于 OVN 这种集中式控制面的架构,会导致控制面存在比较大的压力,成为整个集群的瓶颈。特别是在控制面节点断电或者故障时,可能会需要较长时间网络控制面才能恢复。

这个问题主要是由 OVN 集中式控制平面的架构带来的,无法完全规避。ovn-kubernetes 中采用了每个节点一个 OVN 控制平面,多节点之间通过 OVN-IC 互联的方案来规避这个瓶颈。但是这个方案同时也会导致架构的复杂,并且相当于主动弃用了 OVN 本身的集群网络能力,使得大量的 OVN 能力无法使用。
另一个问题就在于 OVS/OVN 这套体系本身的复杂度,使用者需要重新再构建一套 OVN 规范下的网络拓扑,流表的知识体系才能保证自己面对实际问题时不会手足无措。而这套体系和底层的物理网络往往又是不同的,实际中相当于存在两套网络体系,这不仅会使问题排查变得更复杂,还会导致需要物理网络团队和容器网络团队两套人马,双方往往都无法理解彼此的工作内容,无法有效协同。
以上两个局限性更多的是选型上的取舍,如果希望能够软件集中控制,希望容器网络能不关心底层物理网络,那这样的选择必然就会带来这样的局限性。
在和 OVS 这种纯软件方案平行的另一个硬件世界,有另一套硬件版本的多租户网络方案,那就是 EVPN。
在 EVPN 的世界里,在数据平面交换机之间通过 Vxlan 对数据包做封装,通过在 Vxlan 的 Header 中设置 VNI 来区分不同租户的流量,实现了流量的隔离。
同时,交换机之间通过 BGP 在控制平面来同步 L2/L3 的路由以及 VNI 的信息,能够快速的学习整个网络拓扑中的地址,路由和租户信息。

通过这种方式,大型数据中心可以自动化分布式的实现多租户网络。这套方案在很多大型数据中心都已经落地了,主流的交换机目前也都已经支持。那么在容器领域有没有基于这种技术架构做网络的呢?这就是我最近发现的 OpenPERouter 了。
OpenPERouter 的核心理念是将 EVPN 交换机的逻辑下沉到节点,在每台机器上运行一个 FRR 通过直接和物理交换机建立 BGP 和 VXLAN 隧道,将容器网络直接打通到已有的 EVPN 架构的物理网络。

现有的容器网络想接入 OpenPERouter 也并不算复杂,基于 BGP 的 CNI 需要和 OpenPERouter 建立 BGP Peer;对于基于 veth 和网桥的 CNI,需要把原来在宿主机一侧的 veth 改为接入到 OpenPERouter 所在的 net ns 即可。
这个方案带来了一些独特的优点:
当然这个方案当前也有它的局限性:
在我看来,EVPN 会是未来容器网络里的一个极其有竞争力的技术方案,但是当下并没有很成熟的开源项目,OpenPERouter 做了很好的尝试,我也很希望看到未来有一款专门为 EVPN 架构设计的 CNI 能够大幅简化全局的网络设计。
2025-08-15 22:48:00
MetalLB 目前几乎成了私有云场景下 Kubernetes 提供 LoadBalancer 类型 Service 的事实标准。他的实现逻辑简单清晰,并且功能单一,基于 Gossip 的分布式选主也保证了 VIP 的漂移可以做到迅速且不依赖 Kubernetes 的状态。但是它在专注的情况下也缺少了一些在生产环境极为重要的功能,这也是为什么我最近在调研其他的开源项目,并发现了 LoxiLB 这个很不错的 MetalLB 替代项目。
MetalLB 虽有 LB 之名,但实际上并不处理任何转发平面的工作。严格来说它只提供了 VIP 的对外通告能力,所有转发平面的事情都是依赖 kube-proxy 或者各类的 kube-proxy 的替代 来实现。这样的好处是它可以专注在提供各种类型的 VIP 宣告方式,并且能和 Kubernetes 本身的行为保持最大的兼容性,但同时由于 kube-proxy 本身孱弱的能力,也限制了 MetalLB 本身的功能。
这是 Kubernetes 由来已久的一个问题,Service 后端的 Endpoint 健康状态依赖 Pod 本身的 ReadinessProbe/LivenessProbe,Probe 的执行依赖当前节点的 kubelet。造成的结果就是断电或类似的直接宕机情况下 kubelet 无法更新 Pod 的健康状态,需要等到触发 node not ready 的超时才会修改 Pod 监控状态,通常在大集群这个超时可能会有数分钟,导致这段时间内访问 Service 会出现失败。
严格来说这并不是 MetalLB 的问题,但是由于 MetalLB 本身对数据转发平面没有任何控制能力,无法主动探测 Pod 真实健康情况也无法修改 Pod 健康状态,只能被动接受这种机制。
虽然通过 Pod ReadinessGates 可以使用额外的 controller 主动探测来控制 Pod 健康状态,间接解决这个问题,但对于 MetalLB 来说这个也和它没有什么关系,并没有能开箱即用的方案,这对生产环境还是个很大的隐患。
这同样是依赖 kube-proxy 实现导致的一个问题,kube-proxy 的多种实现方式都没有流量层面的监控,导致的后果就是如果你看 MetalLB 提供的监控指标就会发现里面没有任何流量的指标。这种几乎没有任何数据平面监控的 LB 要上生产,就有点过于松弛了。
LoxiLB 本身是一个为电信场景的特殊需求,使用 eBPF 打造的专用 LB,它完全实现了控制平面和数据平面是一个完整的 LB 实现。LoxiLB 本身的功能十分多,尤其在 SCTP 领域有十分多专属能力,这里不赘述只是重点看一下针对 MetalLB 缺陷的补足。
LoxiLB 可以给每个 Service 配置主动健康检查,支持 ping, tcp, udp, sctp, http, https 也支持超时,重试之类的细粒度配置,虽然称不上多优秀,但 MetalLB 就是没有这个功能,这就显得很尴尬。
这一点就是 eBPF 的强项了,LoxiLB 内置了不少 Metrics 和 Grafana 面板,此外由于数据平面是自己实现的,添加各类监控指标也相对容易一些。
整体来看 LoxiLB 是一个我很喜欢的项目,甚至很多关于 SCTP 协议的理解我都是看了它的一些配置才能理解是怎么回事。但是他还是有着一些不足的地方:
MetalLB 依然是一个我很喜欢的项目,它极其精准地解决了 VIP 宣告及高可用的问题,但是如果达到生产上完备的状态还需要配合其他组件。LoxiLB 则是一套完整的 LB 解决方案,但是社区的发展还处于早期,还有待更多人的参与。
2025-07-09 06:48:00
在做 MetalLB 和 Calico 的一些测试时需要验证 BGP 相关的功能,然而每次测试要去联系运维团队配合网络变更是不太现实的,并且大多数情况我们只要验证 BGP 信息正常交换就可以了,不需要真的去改变物理网络。于是就找到了 GoBGP 这个软件路由器进行模拟。
GoBGP 本身有着很复杂的配置,但是如果你只是像我一样只是想有个虚拟的路由器,让客户端把 BGP 信息发送过来,检查路由表信息是否正确更新,那看这篇文章就可以了。
去 Release 制品列表里找到对应系统的制品解压即可,重要的只有两个二进制文件: gobgpd 虚拟路由器进程,gobgp命令行工具,用来查看路由对不对。
创建一个 gobgp.toml 文件,最简单的配置就照着我下面这个就好了,大部分基础的云原生领域 BGP 相关的软件测试用这个就够了。
1 |
[global.config] |
启动 gobgpd
1 |
./gobgpd -f gobgp.toml |
在另一个终端观察当前的路由表
1 |
./gobgp global rib |
这样基本上 MetalLB,Calico 的基础 BGP 能力就可以测试了。如果想更配更复杂的模式,比如 Router Reflector,EVPN 那就再去翻 GoBGP 的文档吧。
2025-07-06 21:00:10
最近打算把 Kube-OVN 的文档整理一遍,同时思考怎样的文档规范能尽可能做到:
我决定先按照下面的结构重构一下文档,来看看效果。
大家有什么其他的建议也可以一块来讨论一下。
2025-06-28 08:02:21
这篇博客是内部分享的一个提示文稿,并没有做仔细整理,大体思路就是捕获所有 Kube-OVN 的依赖:操作系统,Golang,程序依赖,环境组件(k8s,kubevirt 等),然后激进的实时更新所有依赖做到动态清零。
Kube-OVN CVEs 问题修复的流程经历了如下几个阶段:
优势:
增加工作:
优势:
只要依赖更新版本就尝试更新,不考虑是否是安全更新。尝试解决比 CVE 修复更大的一个问题,自动就解决了 CVE 问题的修复。
我们的依赖项:
ubuntu:24.04, apt-get install ....
OVS, OVN
kubernetes, kubevirt,multus, metallb, cilium, talos
要做的事情:
go.mod 里的所有依赖版本优点:
劣势:
2025-05-24 18:40:04
这两天接了个 Kube-OVN 培训的任务,事实上这已经是这几年第三次给这家公司培训相同的内容了,形式也从线上转到线下还要求手把手的敲命令,可想而知之前几次的最终效果怎样。我可以理解需求方的技术焦虑,但我认为培训这种形式是极其低效的,更多的只是培训当时能获得一些虚假的满足感,不会产生什么长期收益。
一方面培训是一种被动学习方式,完全由老师带节奏前进,那听讲的人只是被动的吸收,很难有深度的思考。另一方面需要等到培训才了解的知识大概率是实际上用不到的知识,如果每天都用的话根本来不及等这种一年一次的培训。如果实际用不到,那么哪怕当场掌握了,很快也会什么都剩不下。
我觉得这和我们一直以来的教育理念有些关系,传统上我们认为认真听老师讲课,努力记笔记,不会的问题堵着老师问,都是优秀的学习习惯。但这些都是偏被动的学习方法,我们很多年的教育过程中其实缺乏主动学习的机会。这种被动的方式早期的效果可能会很好,因为早期学校里的知识难度不大,而且我们展示学习成果的方式就是考试,而考试是可以通过过拟合的方式来提升效果的,并不能真正反映你对知识的掌握程度。
在我的经历里,到了初中阶段,最出色的那批人就不再是认真听课,努力记笔记那批人了。而是换成了那批给人感觉平时一直玩,考试成绩还很好的一批人,事实上越往后这批人的比例越高。我认为这里并不是智商的区别而是被动学习和主动学习模式的区别。主动学习的人会更多依赖自己思考来解决问题,而不是依赖老师的讲解,这个方法看似低效其实最终效果会更好。想象一下同样一道题,一个人是老师之前讲过所以考试的时候做出来了,另一个人是上课没听到但是考试的时候临场也做出来了。从考试的结果来说两个人是一样的,但两个人的实际能力是天差地别的。后者实际上拥有更好的学习方法和能力,并且在更难的问题上有更好的泛化能力,自然可以显得游刃有余。就好比前者一直在用冒泡算法去排序,后者则是不断用快排,在小规模上前者可能更简单更不容易出错,效果会比后者好,但是后者一旦调整好了,在更大规模的数据上会有指数级别的优势。
这也是为什么有些转行的程序员的表现会比科班的表现好。一方面他们采用的是主动学习这种高速方法,另一方面科班的被动学习学到的大量都是实际中毫无用处的知识,两者的基础差距本身就没那么大,用一个更高速的方法很容易短期就实现超越。
所以还是要主动学习,学点有用的。(不要再折腾供应商搞什么高级培训了