作者范建明、洪志国、张浩,均为腾讯云容器产品中心高级工程师,负责容器网络和Service Mesh,容器Runtime,调度等相关研发工作。 腾讯TKE团队[2] 开发了新的IPVS-BPF模式,完全绕过nf_conntrack的处理逻辑,使用eBPF完成SNAT功能。对最常用的Pod访问ClusterIP场景,短连接性能提升40%,p99时延降低31%;NodePort场景提升,详情见下表和性能测量
章节。
存在的问题:
1.可扩展性差。随着service数据达到数千个,其控制面和数据面的性能都会急剧下降。原因在于iptables控制面的接口设计中,每添加一条规则,需要遍历和修改所有的规则,其控制面性能是O(n²)。在数据面,规则是用链表组织的,其性能是O(n)
2.LB调度算法仅支持随机转发
IPVS 是专门为LB设计的。它用hash table管理service,对service的增删查找都是O(1)的时间复杂度。不过IPVS内核模块没有SNAT功能,因此借用了iptables的SNAT功能。IPVS 针对报文做DNAT后,将连接信息保存在nf_conntrack中,iptables据此接力做SNAT。该模式是目前Kubernetes网络性能最好的选择。但是由于nf_conntrack的复杂性,带来了很大的性能损耗。
eBPF[3]是Linux内核中软件实现的虚拟机。用户把eBPF程序编译为eBPF指令,然后通过bpf()系统调用将eBPF指令加载到内核的特定挂载点,由特定的事件来触发eBPF指令的执行。在挂载eBPF指令时内核会进行充分验证,避免eBPF代码影响内核的安全和稳定性。另外内核也会进行JIT编译,把eBPF指令翻译为本地指令,减少性能开销。
内核在网络处理路径上中预置了很多eBPF的挂载点,例如xdp, qdisc, tcp-bpf, socket等。eBPF程序可以加载到这些挂载点,并调用内核提供的特定API来修改和控制网络报文。eBPF程序可以通过map数据结构来保存和交换数据。
针对nf_conntrack带来的性能问题,腾讯TKE团队设计实现了IPVS-BPF。核心思想是绕过nf_conntrack,减少处理每个报文的指令数目,从而节约CPU,提高性能。其主要逻辑如下:
此外,针对icmp, fragmentation均有专门处理,详细背景和细节,会在后续的QCon在线会议[4]上介绍, 欢迎一起探讨。
可以看到,报文处理流程得到了极大简化。
很多读者会问,为什么还要用IPVS模块跟eBPF相结合,而不是直接使用eBPF把Service功能都实现了呢?
我们在设计之初也仔细研究了这个问题, 主要有以下几点考虑:
我们的目标是实现代码量可控,能落地的优化方案。基于以上考虑,我们选择了复用IPVS模块,绕过nf_conntrack,用eBPF完成SNAT的方案。最终数据面代码量为:500+行BPF代码, 1000+行IPVS模块改动(大部分为辅助SNAT map管理的新增代码)。
本章节通过量化分析的方法,用perf工具读取CPU性能计数器,从微观的角度解释宏观的性能数据。本文采用的压测程序是wrk和iperf。
复现该测试需要注意两点:
为了采集CPI等指标,这里LB节点(红色部分)采用黑石裸金属机器,但通过hotplug只打开一个核,关闭其余核。
这里LB节点(左边的Node)采用SA2 1核1G机型。
IPVS-BPF模式相对IPVS模式,NodePort短连接性能提高了64%,ClusterIP短连接性能提高了40%。
NodePort优化效果更明显,是因为NodePort需要SNAT,而我们的eBPF SNAT比iptables SNAT更高效,所以性能提升更多。
如上图所示,iperf带宽测试中IPVS-BPF模式相对IPVS mode性能提升了22%。
上图中,wrk测试表明NodePort 短连接p99延迟降低了47%。
上图中,wrk测试表明ClusterIP短连接的p99延迟降低了31%。
上图中从Perf工具看,平均每个请求耗费的CPU指令数,IPVS-BPF模式下降了38%。这也是性能提升的最主要原因。
IPVS-BPF 模式下CPI略有增加,大概16%。
Service类型 | 短连接cps | 短连接p99延迟 | 长连接吞吐 |
---|---|---|---|
clusterIP | +40% | -31% | 无,见下文 |
nodePort | +64% | -47% | +22% |
如上表,IPVS-BPF模式相对原生IPVS模式,Nodeport处理短连接性能提升了64%,p99延迟降低了47%,处理长连接带宽提升了22%;ClusterIP处理短连接吞吐量提升了40%, p99延迟降低了31%。
测试ClusterIP长连接吞吐时,iperf本身消耗了99% 的CPU,使得优化效果不容易直接测量。另外我们还发现IPVS-BPF模式下CPI有增加,值得进一步研究。
conn_reuse_mode = 1时新建性能低[5]以及no route to host问题[6]
这个问题是当client发起大量新建TCP连接时,新的连接被转发到terminating的Pod上,导致持续丢包。此问题在IPVS conn_reuse_mode=1的情况下不会有。但是conn_reuse_mode=1时,有另外的新建连接性能急剧下降的bug, 故一般都设置成了conn_reuse_mode=0。我们在TencentOS内核中彻底修复了该问题,代码在ef8004f8[7], 8ec35911[8], 07a6e5ff63[9] 同时也正在向内核社区提交修复。
DNS解析偶尔5s延时[10]
iptables SNAT分配lport到调用插入nf_conntrack,这中间是采用乐观锁机制。这中间如果发生竞争,相同的lport和五元组同时插入nf_conntrack会导致丢包。在IPVS-BPF模式下,SNAT选择lport的过程和插入hash table的过程在同一个循环中,循环次数最大为5次,从而减少了该问题的概率。
externalIP优化[11]造成clb健康检查失败问题
详情见:https://github.com/kubernetes/kubernetes/issues/79783#issuecomment-509007864
如下图,在腾讯云TKE控制台[12]创建集群时,高级设置
下的Kube-proxy代理模式
选项,选择 ipvs-bpf
即可。
目前该特性需要申请白名单。请通过申请页[13]提交申请。
本产品产生的相关专利申请如下:
2019050831CN 一种报文传输的方法及相关装置
2019070906CN 负载均衡方法、装置、设备及存储介质
2020030535CN 一种利用eBPF技术探测网络服务应用闲置的方法
2020040017CN 宿主机实时负载感知的自适应的负载均衡调度算法
Kubernetes Service: https://kubernetes.io/docs/concepts/services-networking/service/
[2]腾讯TKE: https://cloud.tencent.com/product/tke
[3]eBPF: https://lwn.net/Articles/740157/
[4]QCon在线会议: https://qcon.infoq.cn/2020/beijing/presentation/2321
[5]conn_reuse_mode = 1时新建性能低: https://github.com/kubernetes/kubernetes/issues/81775
[6]no route to host问题: https://tencentcloudcontainerteam.github.io/2019/12/15/no-route-to-host/
[7]ef8004f8: https://github.com/Tencent/TencentOS-kernel/commit/ef8004f8fe7d46e758955799a41cc9d66fa1ae34
[8]8ec35911: https://github.com/Tencent/TencentOS-kernel/commit/8ec35911f7c5e1cb29059c18d42cf3aec4fcc673
[9]07a6e5ff63: https://github.com/Tencent/TencentOS-kernel/commit/07a6e5ff63a74efcca67d496f6ac8126f1f114ff
[10]DNS解析偶尔5s延时: https://tencentcloudcontainerteam.github.io/2018/10/26/DNS-5-seconds-delay/
[11]externalIP优化: https://github.com/kubernetes/kubernetes/pull/63066
[12]腾讯云TKE控制台: https://console.cloud.tencent.com/tke2/cluster?rid=16
[13]申请页: https://cloud.tencent.com/apply/p/iwezhfpubqi
文章来源:腾讯云原生 / 原文链接
联系客服