UCloud 生产环境中负载均衡产品DPDK问题的解决

未知 admin 2020-05-01 05:53

第二步结论让全部排查进步了一大年夜步,然则队列包是经由一系列法度榜样处理的,并不是真正的原始营业报文。不达目标不罢休,关键时刻照样要上镜像抓包,于是当晚紧急接洽收集运维同事在交换机上设备port-mirroring(端口镜像),将发往ULB4集群的流量镜像到一个余暇办事器长进行镜像抓包。当然,镜像办事器还须要做特别设备,如下:

ULB4是UCloud自立研发的基于DPDK的高可用四层负载均衡产品,转发才能接近线速;DPDK则是一个高机能的开源数据面开辟套件。ULB4作为用户应用的全局进口,在大年夜流量多元化场景下包管用户营业的持续稳定至关重要,这也是UCloud收集产品团队的技巧任务。尤其现网单个ULB集群承载带宽已达10G,包量83万PPS,运行情况复杂,即使面对突发身分(比如触发未知BUG),我们也要设法包管产品正常工作,避免产生严重影响。

近期,我们在ULB4的线上情况中,发清楚明了一个DPDK的发包异常现象,因为全部ULB产品为集群架构,该异常并未导致用户办事弗成用。但为了任何时刻都能包管用户办事的足够稳定,团队经由过程GDB、报文导出对象、临盆情况流量镜像等手段,从现网GB级流量中捕获异常报文,再结合DPDK源码分析,定位到原因出自DPDK本身的BUG并修复解决。时代未对用户营业造成影响,进一步包管了UCloud数万ULB实例的稳定运行。

本文将从问题现象着手,抽丝剥茧,胪陈问题定位、分析与解决全过程,欲望能为ULB用户和DPDK开辟者供给参考与启发。

问题背景

在12月初一贯稳定的ULB4集群中忽然出现了容灾,某台ULB4办事器工作异常被主动移出了集群。当时的现象是:

转发面办事监控到网卡接收偏向流量正常,然则发送偏向流量为0,重启转发面办过后又可以正常收发,同时集群其他机械也会不按期出现异常情况。对用户营业而言,会出现少量连接稍微颤抖,随后敏捷恢复。

下面是全部问题的处理过程,我们在此过程中做出各种测验测验,最终结合DPDK源码完成分析和解决,后续也预备将自研的报文导出对象开源共享。

问题定位与分析

ULB4集群一向很稳定地工作,忽然陆续在集群的不合机械上出现同样的问题,并且机械恢复参加集群后,过了一段时光又再次出现同样的问题。根据我们的运营经验,初步猜测是某种异常报文触发了法度榜样BUG。然则,面对GB级流量若何捕获到异常报文?又如安在不影响营业情况下找出问题呢?

想要知道全部法度榜样为什么不发包,最好的办法就是可以或许进入到法度榜样中去看看具体的履行过程。对于DPDK用户态法度榜样来说,GDB显然是一个好用的对象。我们在发包法度榜样逻辑中设置断点,并经由过程disassemble敕令查看该函数的履行逻辑,反汇编之后足足有七百多行。(该函数中调用的很多函数都应用了inline润饰,导致该函数在汇编之后指令特别多)

结合对应DPDK版本的源码,单条指令一步步履行。在多次测验测验之后,发明每次都邑鄙人图所示的处所直接返回。

大年夜致流程是i40e_xmit_pkts()在发送的时刻,发明发送队列满了就会去调用i40e_xmit_cleanup()清理队列。DPDK中网卡在发送完数据包后会去回写特定字段,注解该报文已经发送,而驱动法度榜样去查看该字段就可以知道这个报文是否已经被发过。此处的问题就是驱动法度榜样认为该队列中的报文始终未被网卡发送出去,后续来的报文将无法参加到队列而被直接丢弃。

至此,直接原因已经找到,就是网卡因为某种原因不发包或者没能精确回写特定字段,导致驱动法度榜样认为发送队列始终处于队列满的状况,而无法将后续的报文参加发送队列。

那么为什么出现队列满?异常包是否相干呢?带着这个疑问,我们做了第二个测验测验。

二、一键还原网卡报文

基于对DPDK的深刻研究,我们根据以下步调导出报文。

?我们看i40e_xmit_pkts()函数,会发明第一个参数就是发送队列,所以我们可以获取到队列的信息。

?如下图所示,在刚进入断点的时刻,查看存放器信息,以此来获得该函数对应的参数。

?当我们打印该队列的消息时,却发明没有符号信息,此时我们可以如下图所示去加载编译时刻生成的 i40e_rxtx.o 来获取对应符号信息。

?在获得队列信息后,我们应用GDB的dump敕令将全部队列中所有的报文全部按队列中的次序导出,对每个报文按序号定名。

?此时导出的报文照样原始的报文,我们无法应用wireshark便利地查看报文信息。为此如下图所示,我们应用libpcap库写了个简单的小对象转换成wireshark可以解析的pcap文件。

果真,如下图所示,在导出的所有报文中包含了一个长度为26字节,但内容为全0的报文。这个报文看上去十分异常,似乎初步验证了我们的猜测:

为了进步在排盘考题时导出报文的速度,我们写了一个报文一键导出对象,可以在异常时一键导出所有的报文并转成pcap格局。

在多次导出报文后,我们发明一个规律:每次都邑有一个长度为26字节然则全0的报文,并且在其前面都邑有一个同样长度的报文,且每次源IP地址网段都来自于同一个地区。

三、流量镜像,确认异常包

1. 设置网卡混淆模式,用于收取镜像流量(ifconfig net2 promisc)。

2. 封闭GRO功能(ethtool -K net2 gro off),用于收取最原始的报文,防止Linux的GRO功能提前将报文进行组装。

根据异常IP的地区特点,我们针对性抓取了部分源IP段的流量。

参考敕令:nohup tcpdump -i net2 -s0 -w %Y%m%d_%H-%M-%S.pcap -G 1800 “proto gre and (((ip[54:4]&0x11223000)==0x11223000) or ((ip[58:4]&0x11223000)==0x11223000))” &

经由多次测验测验后,工夫不负有心人,故障出现了,经由层层剥离筛选,找到了如下报文:

这是IP分片报文,然则奇怪的是IP分片的第二片只有IP头。经由细心比对,这两个报文合在一路就是导出队列报文中的那两个连在一路的报文。后26字节和全0报文完全吻合。

我们知道在TCP/IP协定中,假如发送时一个IP报文长度跨越了MTU,将会触发IP分片,会被拆成多个小的分片报文进行发送。正常情况下,所有的分片肯定都是携带稀有据的。然则这一个分片报文就很异常,报文的总长度是20,也就是说只有一个IP头,后面不再携带任何信息,如许的报文是没有任何意义的。这个报文还因为长度太短在经由交换机后被填充了26字节的0。

至此,我们最终找到了这个异常报文,也根本验证了我们的猜测。然则还须要去实际验证是否为这种异常报文导致。(从全部报文的交互来看,这一片报文本来是设置了弗成分片的TCP报文,然则在经由某个公网网关后被强迫设定了许可分片,并且分片出了这种异常的情势。)

四、解决筹划

假如确切是这个异常报文导致的,那么只要在收包时对这种异常报文进行检查然后丢弃就可以了。于是,我们修改DPDK法度榜样,丢弃这类报文。作为验证,先宣布了一台线上办事器,经由1天运行再也没有出现异常容灾情况。既然问题根因已经找到,恰是这种异常报文导致了DPDK工作异常,后续就可以按灰度全网宣布了。

五、DPDK社区反馈

本着对开源社区负义务的立场,我们预备将BUG向DPDK社区同步。比较最新的commit后,找到11月6日提交的一个commit,情况千篇一律,如下:

ip_frag: check fragment length of incoming packet

在有了根本懂得后,我们猜想假如直接在法度榜样中手动构造这种类似的异常报文,是否也会导致网卡异常不发包?

复盘和总结

处理完所有问题后,我们开端做整体复盘。

队列满,并且后面的报文一向加不进去,解释此时队列里面的报文一向卡在那。既然我们猜测可能是存在异常报文,那么有没有可能异常报文还在队列里面呢?假如可以把当前队列里面的报文全部导出来,那就可以进一步验证我们的猜测了。

ULB4无法发包的全部产生过程如下:

1. DPDK收到分片报文中的第一片,将其缓存下来等待后续分片;

2. 第二片只有IP头的异常分片到来,DPDK按照正常的报文处理逻辑进行处理,并没有进行检查丢弃,于是两片报文的rte_mbuf构造被链在一路,构成了一个链式报文返回给ULB4;

3. 如许的报文被ULB4接收后,因为全部报文的总长度并没有达到须要分片的长度,所以ULB4直接调用DPDK的发送接口发送出去;

DPDK 18.11最新宣布的版本中,已对此进行了修复,和我们处理逻辑一致,也是丢弃该异常报文。

4. DPDK没有对这种异常报文进行检查,而是直接调用响应的用户态网卡驱动直接将报文发送出去;

5. 用户态网卡驱动在发送如许的异常报文时触发了网卡tx hang;

6. 触发tx hang后,网卡不再工作,驱动队列中报文对应的发送描述符不再被网卡精确设置发送完成标记;

7. 后续的报文持续到来,开端在发送队列中积存,最终将全部队列占满,再有报文到来时将被直接丢弃。

二、为什么异常报文会触发网卡tx hang

起首我们看下DPDK中跟网卡发送报文相干的代码。

从以上的图中我们可以看到,根据网卡的Datasheet对相干字段进行精确设置异常重要,假如某种原因设置缺点,将可能会导致弗成预知的后果(具体照样要参考网卡的Datasheet)。

一、GDB调试报文,发明疑点

一、ULB无法发包的成因总结

如下图所示,平日网卡对应的Datasheet中会对响应字段进行相干描述,网卡驱动中一般都邑有响应的数据构造与其对应。

谜底是肯定的。

如下图所示,我们应用如许的代码片段构成异常报文,然后调用DPDK接口直接发送,很快网卡就会tx hang。

三、对直接操作硬件的思虑

直接操作硬件是一件须要异常谨慎的工作,在传统的Linux体系中,驱动法度榜样一般处于内核态由内核去治理,并且驱动法度榜样代码中可能进行了各类异常处理,是以很少会产生用户法度榜样操作导致硬件不工作的情况。而DPDK因为其自身应用用户态驱动的特点,使得可以在用户态直接操作硬件,同时为了晋升机能可能进行了异常多的优化,假如用户自身法度榜样处理出问题就有可能会导致网卡tx hang如许的异常情况产生。

四、对象的价值

我们编写了一键导出DPDK驱动队列报文的对象,如许就可以在每次出现问题时,快速导出网卡驱动发送队列中的所有报文,大年夜大年夜进步了排查效力。这个对象再优化下后,预备在UCloud GitHub上开源,欲望对DPDK开辟者有所赞助。

写在最后

DPDK作为开源套件,平日情况下稳定性和靠得住性不存在什么问题,然则实际的应用处景千变万化,一些特别情况可能导致DPDK工作异常。固然产生概率很小,然则DPDK平日在关键的网关地位,一旦出现了问题,哪怕是很少见的问题也将会产生严重影响。

是以技巧团队懂得其工作道理并对其源码进行分析,同时可以或许结合具表现象一步步定位出DPDK存在的问题,对进步全部DPDK法度榜样的办事靠得住性具有重要意义。值得一提的是,ULB4的高可用集群架构在本次问题的处理过程中发挥了重要感化,在一台弗成用的时刻,集群中其他机械也可以持续为用户供给靠得住办事,有效晋升了用户营业的靠得住性。


0

相关文章

我来评论

评论