下面介绍一下灵雀云开源的 Kube-OVN 在云原生实践方面所做的一些事情,Kube-OVN 根据日常实践中遇到的问题也在不断改进。
1 子网模型
Kube-OVN 比较大的改动是对子网模型进行了改进,把 Subnet Per Node 的模型改成了 Subnet Per Namespace。这样做有几点好处:首先,子网可以分布在所有节点上,避免了网络地址和主机地址的绑定。进行网络扩缩容时,不需要对整个机器集群进行改动,只需要增加或减少子网。
子网跟 namespace 关联时,后面会有很多独立的设置,比如每个 namespace 可以有独立的地址空间,对应到用户那边可能是某一个项目组,或者某个租户,这样的对应就很直接,因为它可能是租户对应到 namespace,租户对应到子网,是一个紧密关联的情况。子网跟 namespace 绑定后,可以根据租户来定义一些防火墙的策略,网关、NAT 策略,子网 IPv4 还是 IPv6,都可以按照这个子网的级别来进行设置,而不会跟节点绑死。
2 固定 IP
Kube-OVN 还对固定 IP 做了全面支持。
•Pod 支持固定 IP/Mac
•Workload 类型 (deployment/statefulset/dae monset/job) 可通过 ippool annotation 固定 IP, 保证在 deployment 生命周期内一直在复用 IP。
•StatefulSet 支持 IP 复用,生命周期内按名字复用已分配 IP。在创建 StatefulSet 时不知道 IP 是多少,一旦 StatefulSet 创建完成,pod 名字和 IP 是固定的。
我们对 StatefulSet 还做了一些额外的支持,在 StatefulSet 里面实现了默认的固定 IP。这一点其实有争议,有人觉得不该这么应用,但在我们的实践中,还是把最终的选择权留给用户。如果他不需要固定 IP 的功能,我们完全可以按照随机分配 IP 的方式去做。如果用户一些部门之间存在这样的问题,需要应用或者底层去做修改,可能应用方面不想改,但是又希望上容器,要用固定 IP,我们也能提供这样的能力。
3Gateway
出网的方式,在实际中会碰到应用一部分在 K8s 上,一部分不在,或者关联的一些系统不在 K8s 上,就涉及到集群内外互访的需求。我们提供几种不同的出网方式。默认是分布式网关,它和 Flannel、Calico 的默认模式类似,pod 如果想访问外部网络,从所在 node 节点直接出网。但这种方式不一定能满足所有场景。
采用这种方式如果你的 pod 飘移,意味着出网的地址也是飘移的,加白名单或做审计都是很困难的事情,这种情况下要把整个集群所有机器都加白名单。审计时,他也不清楚究竟审计应该从哪个节点过来流量。我们做了一个 namespace 级别的,这个和前面的子网是绑定的,只要配置子网的网关,就可以配置出网的方式。
每个 Namespace 可以设置独立的 Gateway 节点出网。在这个节点,所有出网的流量都通过一个特定节点,相当于通过一种固定的方式出网。在外部进行审计或加白名单时,对一个节点进行处理就可以。而且这个节点可以做高可用的,现在是主备模式,如果当前的断掉,或者故障下线,可以自动切换到下一个备用的节点。
除了这两种出网方式,我们还有一个特殊的设置,pod 出网要不要进行 NAT,如果进行的话,相当于是以当前主机节点 IP 的方式出网。如果不做 NAT,就相当于集群内外的互通。我们的做法还是把所有的能力都提供出来,交给用户去选择。
4 性能
最后一点性能,也是大家比较关注的话题。主要从控制平面和数据平面的性能两方面讲一下 Kube-OVN 在工程方面的一些工作。
我们在早期主要关注控制平面的性能,Kube-OVN 最早使用的是 OVN 控制平面。发现早期会有一些性能问题,在几千个 pod 时控制平面的延迟会非常严重。我们针对减缓延迟做了大量工作,比如:减少变更的规则条数,把 OVN 的变更进行一些合并,减少整体的变更数量,加快变更速度。
还有一个上游在做的事情,从全量更新变成增量更新。之前 OVN 的模式是说,网络变更需要每个节点去拉整个网络的拓扑,全量更新的话这个速度会非常慢,现在都变成增量更新,只变更新加或者更改的规则。这个变化蛮显著,按照官方的测试,之前下发上万条流表的更新要六秒左右。经过变更,只需要 200 到 300 毫秒。这个功能未来也会加入 Kube-OVN,到时控制平面的支撑会达到几万或者十几万个 pod 或 service 的规模。
还有一种方式是对网络的区域进行划分。现在用户使用的 K8s 集群都特别大,在大的集群里,如果每个节点都要同步所有网络拓扑是很大的一个开销。我们根据租户或者可用区,把大的集群再进行网络的分区,每个分区只要遵循自己内部的一些规则,再通过特定的网关,也可以减少控制平面所需要的流表数量,降低每个节点的负担。
还有一个场景,对控制平面性能要求最高的地方在于灾难恢复的速度。平常情况下,如果集群正常运行,增删改查的频率还是可控的,如果 master 节点宕掉了,或整个 OVN 的节点、几台机器都宕掉了,再恢复时涉及到网络的同步更新。Kube-OVN 有 controller 策略,需要对所有 pod 进行校验,controller 启动之后,会看所有的配置是不是同步到一个最新的状态。
大家可以想象,如果有 1 万个 pod 或者 service,启动时需要在 OVN 里重新配置。根据我们的测试,之前这个工作需要花十几分钟才能完成故障的恢复。我们对此进行了一些优化,主要有两点:第一,减少重复的网络配置。第二,对 evicted,failed 等网络资源进行实时清理。
控制平面的性能完成后,我们最近在数据平面做了一些事情。首先,之前默认的情况下使用的是 Geneve 这种封装方式,这也是 OVN 推荐的一种网络封装模式。Geneve 封装对物理网络拓扑要求低,封包解包存在性能损失。
我们现在也支持 Vlan 模式,对底层交换机是有要求的,需要底层的 Vlan 能够识别 Kube-OVN,只需要进行轻量的封装就可以把数据包通过物理交换机的方式来进行转化。我们测试了一下性能有很大的提升,接近物理网络的性能,这是锐捷在社区提的 PR。
上面两种都是基于内核的协议栈,我们现在还有一些电信、5G 的场景,他们在边缘节点会有极高的网络性能的要求,常规的内核网络不能满足他们的需求。所以我们现在也支持 DPDK 协议栈,容器挂载 vhost-user socket,容器内可运行高性能 DPDK 应用。
5 监控和故障排查
前面的性能等功能是大家在选型时比较关注的点,但实际中会发现运维和监控是更为重要的能力。如果出了问题会影响很多部门对容器网络的信心,所以 Kube-OVN 集成了很多常用的工具,包括常用的 Tcpdump 集成到了插件里,方便把流量导出来。还有 ovn-trace,如果网络从一个点到另一个点不通,可以通过 tracing 工具查看数据包从源到目的地的逻辑链是否存在问题。
此外还集成了大量监控,可能大家都是看某个容器的网络监控,比如带宽、错误率等,我们增加了常规的监控,从整体上提升网络质量的监控。主要分为以下几个维度:
•Pod-> Pod
•Pod-> Node
•Pod-> Service
•Pod-> DNS
•Pod-> External Address
我们会有定期的监测,包括延迟、连通性的质量,所有的数据都打到 Prometheus & Grafana 里面,帮助运维和网络的管理人员,实时看到当前网络的质量,而不需要等到应用出现问题再去追溯到网络。而且当应用出现问题,也可以通过监控数据,判断到底是容器网络的问题,还是应用层面的问题。还有一些流量走向的工作,所有的容器流量进行镜像,这样传统的一些分析工具,比如细粒度的流量分析、深度检测、安全检测,通过流量的方式来做一些更细粒度的网络性能、质量的监控。
6 用户案例
Openness
Kube-OVN 技术社区成形后,获得了大批开发者和用户的关注。Kube-OVN 功能、运维性、性能的提升过程中,多家厂商的开发伙伴加入了进来。比如近期大家都知道,我们和 Intel OpenNESS 爱尔兰开发团队的合作,加入了对 OVS-DPDK 的支持,以及性能优化的方案。
Openness 是 Intel 开源并主导的 5G 边缘计算套件,通过他们的模型,让 K8s 跑在边缘上。他们选择 Kube-OVN 作为默认的配置节点的网络配置和管理方案。大家可以看一下右边这张图:
现在在欧洲和日本的电信那边开始尝试。配合 Multus 实现工业界第一个 OVS- DPDK 和容器网络结合,容器化运行高性能 DPDK 应用。
欢迎国内边缘计算的网络方案厂商跟我们联系。
国内前三的公有云厂商在边缘容器场景下的应用
借助社区的能力,Kube-OVN 其实已经在若干项目和实际环境中投入使用。国内的公有云厂商里面有两家已经用到 Kube-OVN,用到的业务和场景也类似,都是在边缘计算。他们不是直接给用户卖 K8s,而是卖容器,类似用虚拟机的模式去卖容器。这里有一个需求,他们需要对带宽进行动态控制,因为可能涉及到超卖,如果流量上来,要对每个用户的带宽进行动态调整。
其次,他们的容器是直接对外的,需要有一个对应的公网 IP。他们之所以和 Kube-OVN 进行融合,主要基于两点:
•利用 Kube-OVN 的 QoS 能力对带宽进行动态调整
•结合固定 IP 的功能,利用 NAT 将公网 IP 和 容器 IP 直接进行映射
容器本身有一个控制带宽的插件,不过它是一次性的,只能在容器启动时指定带宽,起来之后如果想改带宽的话,只能重建才能生效。Kube-OVN 是动态调整的,业务不用重启,带宽可以实时调整。
还有固定 IP 的功能,用户可以直接把公网的 IP 和容器 IP 进行映射,这样就不会出现当容器起来之后,动态解绑再绑定的事情,通过固定 IP 把规则写死,从而避免由于变化频繁产生的一些问题。