当我们谈论云原生网络时,Kube-OVN 究竟能带来什么?(下)|视频回顾

下面介绍一下灵雀云开源的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在工程方面的一些工作。

PIC1.png

我们在早期主要关注控制平面的性能,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作为默认的配置节点的网络配置和管理方案。大家可以看一下右边这张图:

PIC2.png

现在在欧洲和日本的电信那边开始尝试。配合 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把规则写死,从而避免由于变化频繁产生的一些问题。

阅读 195

推荐阅读