问题一:calico特定场景下的网络性能问题
**问题现象** 最近我们在做kosmos的性能测试,本来是想做一个简单的对比,说明我们kosmos搭建的vxlan网络和calico的集群内的容器网络性能差不多在同一水平,但是测试下来,我们发现kosmos在连通跨集群的容器网络时,表现竟然远远好于calico的集群内容器网络,这令我们非常困惑。 我们先看下集群内的calico容器网络,iperf3 server端启动在一个节点的容器内,iperf3 client端启动在另一个节点的容器内,测试后发现,传输速度大约只有2.9Gbit/s,如下图所示
calico集群内容器网络传输-优化前
再看下kosmos跨容器网络传输速度大概是6Gbit/s,如下图所示
kosmos跨集群网路网络测试
此时,我们测试物理机本身的网络,iperf3 client端访问物理网卡即可,测试结果大致为9.38Gbit/s,如下图所示
物理机网络传输测
可以看到物理机性的网络传输性能远高于calico容器网络,68% 的性能损耗几乎无法接受
**问题的定位** 因为现象是kosmos的跨集群网络比calico的容器网络性能好,我们主要的精力都花在了对比测试上。 排查过程中,我们找了一些工具来检查环境中的流量,但是没有明显看到其他进程挤占流量,值得注意的是,我们使用iptraf-ng命令观察网卡流量的时候,发现每次一启动程序iperf测试的带宽就会迅速下降,不清楚这个工具的具体机制,为什么会影响到网络带宽性能,这也给我们提了个醒,在线上排查问题的时候选择工具也要考虑对环境的影响。 经过对比vxlan网卡的配置,如sysctl -a查询网卡相关的系统参数,对比ip linkx show devname中的配置项,以及ethool查询网卡配置,最终我们发现问题出在网卡的checksum/offload参数上。 现在我们手动执行命令**ethtool -K vxlan.calico tx on**修改参数进行测试,如下图所示
ethtool调整参数
发现一开始修改后传输性能提升了很多,但是后续却迅速下降到了未修改前的情况
ethtool调整参数后测试
再次查看参数,发现参数又被calico修改回去了,他不想让我们修改!
再次检查参数
经过资料检索,我们在 calico-node 这个daemonset中增加了如下环境变量 ```js name: FELIX_FEATUREDETECTOVERRIDE value: ChecksumOffloadBroken=false ``` 效果如下所示:
修改calico-node配置
等calico-node重启,在所有主机上修改参数进行测试,效果如下所示 结果如下所示
性能和Kosmos差不多,这大概符合我们的预期。
**进一步讨论:calico为何要锁定这个参数?** 大概是因为存在一个checksum相关的bug,可能和内核版本以及k8s版本相关,猜测因此在低内核版本下,calico默认关掉了这个配置项 > 内核中存在一个和VXLAN处理有关的缺陷,该缺陷会导致Checksum Offloading不能正确完成。这个缺陷仅仅在很边缘的场景下才会表现出来。 > 在VXLAN的UDP头被NAT过的前提下,如果: > 1. VXLAN设备禁用(这是RFC的建议)了UDP Checksum > 1. VXLAN设备启用了Tx Checksum Offloading > 就会导致生成错误的UDP Checksum。 > 从资料[1]看,K8S的v1.18.5版本已经修复了这个问题,但我的问题是在v1.21.0上发现的,所以不确定只升级K8S是否可以解决该问题,或者升级后还需要额外配置什么? > 从资料[3]和[4]看,calico在v3.20.0版本做了修改:在kernels < v5.7时也禁用了calico.vxlan接口的Offloading功能。 > 1. 绿色记忆:内核缺陷触发的NodePort服务63秒延迟问题 > 1. Kubernetes v1.17+ 集群下 CNI 使用 VXLAN 模式 SVC 有 63 秒延迟的触发原因定位 | 云原生社区(中国) > 1. k8s vxlan 作为 cni 后端引发的 63 秒延迟 > 1. https://github.com/projectcalico/calico/issues/3145 > 1. https://github.com/projectcalico/felix/pull/2811/files > 1. K8S问题排查-Calico的Vxlan模式下节点发起K8s Service请求延迟 | 云原生知识星球 我个人在生产环境中也遇到了一个网络问题,怀疑也是checksum的问题,当时的现象是ping测试网络不通,且收到的包有checkum error之类的报错,但是curl测试tcp协议的包可以正常传输,不过因为是现网环境,没有修改参数测试。 checksum和offload是关联的配置项,真正影响我们测试性能的应该是offload这个配置 找了一点资料简单介绍下: > TSO就是将TCP Segmentation的工作,卸载(offload)到网卡来完成。有了TSO,操作系统只需要传给硬件网卡一个大的TCP数据(当然是包在Ethernet Header和IP Header内,且不超过64K)。网卡会代替TCP/IP协议栈完成TCP Segmentation。这样,就消除了TCP Segmentation带来的CPU负担。 > 另一个好处在DMA。虽然说每次DMA操作,不需要CPU太多的介入,但是仍然需要CPU配置DMA控制器。DMA的特点在于,无论传输数据的长短,配置工作量是一样的。如果系统内核自己完成TCP Segmentation,那么就有若干个TCP Segments需要通过DMA传给网卡。而采用TSO,因为传输的是一大段数据,只需要配置一次DMA,就可以将数据拷贝到网卡。这也一定程度减轻了CPU的负担。 > 支持TSO的网卡,仍然会按照TCP/IP协议将网络数据包生成好并发送出去。对于外界系统来说,感受不到TSO的存在。 > https://zhuanlan.zhihu.com/p/44635205 > https://klysisle.space/archives/3b5f401c.html
总结 我们是在性能测试中遇到的这个问题,是由于为了对比测试性能,我们特意把calico的网络模式调整成了vxlanMode: Always,我们的内核版本是4.19,kubernetes版本是v1.21.5,calico的版本是v3.23.2。我们生产环境中的配置应该是vxlanMode: CrossSubnet,也就是说只有在跨网段且使用vxlan网络模式的情况下才有可能出现这种性能瓶颈,同网段不会存在问题。 另外经过前面的讨论,我们也能看到,开启了checksum相关的特性,在某些场景下会引起一些诡异的网络问题,我们应该要针对特定场景做充分的测试才能修改系统参数。