本文转载自微信公众号「小咩社长」,作者小咩社长。转载本文请联系小咩社长公众号。
写在前面:
最近一保险客户火急火燎的找到我说:“涛哥,我们最近这段时间每天晚上在执行批处理的过程中,频繁的报错,十万次的HTTP POST请求中,大概会有六七百次的请求失败的情况发生,故障现象随时可以复现,赶紧帮看看“。经过老中医我一番悬丝诊脉,梳理完整个业务访问流程后,下一良方,辅以悍药猛攻,基本上药到病除。
由于此故障场景很有代表性,于是专门整理出这篇文章,希望能给到大家在日常运维排错中一点启发。话不多少,上干货。
网络逻辑拓扑及业务流:
业务的逻辑拓扑图,如下图所示。
批处理业务服务器:Server1 10.160.XX.81:8000、Server2 10.160.XX.82:8000。并且通过前端F5设备提供负载均衡和业务对外发布,VIP地址:10.50.XX.67:8165。
测试终端:通过Curl的方式向 F5 VIP 10.50.XX.67:8165 发送POST请求(批处理流程)
访问流程:
- 用户使用脚本通过curl 提交POST请求到F5 VIP 10.50.XX.67:8165
- F5将客户的POST请求按照负载均衡算法将请求转发给真实服务器Server1或者server2
- F5和服务器之间有一个国产XX信的NGFW设备(上联F5设备使用的是防火墙feth11接口,下联交换机使用是防火墙feth10接口),注意防火墙出入接口,接下来分析数据包的时候会提到。
故障现象:
用户在使用脚本提交POST请求到F5 VIP 10.50.XX.67:8165的时候,运行一段时间后会卡住(即:POST请求发出后没有响应),几秒钟后收到F5 返回来的RESET包。
抓包大杀器TCPDUMP:
乍一看,很明显F5发了RESET包,显然是F5的锅嘛。其实有时眼见不一定为实,需要透过现象找到问题本质,并不是谁发了RESET包就是谁的锅。
话不多说,直接掏出大杀器tcpdump,这种疑难杂症还得猛药去攻。在客户执行批处理操作的同时,我们在以下三个位置进行抓包。
一、F5设备上执行tcpdump抓包
#同时抓取客户端IP、F5 VIP、服务器IP,可以抓全整个访问环节的数据包,方便定位故障点
- #同时抓取客户端IP、F5 VIP、服务器IP,可以抓全整个访问环节的数据包,方便定位故障点
- tcpdump -ni 0.0:nnn -s0 host 10.50.xx.88 or 10.50.xx.67 or 10.160.xx.81 or 10.160.xx.82 -w /var/tmp/test0421-6.pcap.pcap
二、XX信防火墙抓包,抓取流经上联接口feth11和下联接口feth10的所有流量。
三、在服务器 Server1 10.160.XX.81、Server2 10.160.XX.82上使用tcpdump抓取流经服务器网卡的所有数据包。
抓包进行时:
测试端使用脚本跑批处理的时候,三个点同时进行抓包,当测试端故障复现,三个点停止抓包。
数据包分析:
不负众望,故障现象成功复现,下面进行最重要的阶段,数据包分(甩)析(锅):
一、F5上数据包分析:测试客户端到F5 VIP数据包分析(clientside):
注意故障包的时间:20点57分12秒,以下分析基于该时间点的故障数据包分析,注意数据包前时间!!!
通过wireshark查看F5上tcpdump抓取的数据包,找到故障会话,可以看到
客户端10.50.X.88:54373访问 F5 VIP 10.50.XX.67:8165的访问流量,通过数据包我们可以得到到以下信息:
- 客户端10.50.X.88:54373访问 F5 VIP 10.50.XX.67:8165 TCP三次握手建立成功
- 客户端发起了POST请求,并且F5确认收到该请求 (ack)
- F5没有响应回http response给客户端
- F5返回给客户端一个RST,RST原因为:F5RST(peer) TCP retransmit timeout(重传超时)。
事实上当F5和客户端建立完TCP三次握手之后,F5会基于负载算法选择一台服务器进行tcp三次握手建链,然后将客户端发来的POST请求转发给真实的服务器:
通过wireshark上使用F5的扩展插件,该会话流程中还能看到以下信息。
- 在该会话中F5选择了10.160.XX.82:8000这台服务器
- F5启用了源地址转换功能,将客户端的真实IP地址10.50.XX.88转换为10.50.XX.247
- 源端口为43166
二、F5上数据包分析:F5 (10.50.XX.247)到10.160.XX.82:8000流量分析(serverside):
通过wireshark查看F5上tcpdump抓取的数据包,过滤tcp.port ==43166,可以看到
F5端(10.50.XX.247:43166)访问 server2 10.160.XX.82:8000的访问流量,通过数据包我们可以得到到以下信息:
- 当F5端(10.50.XX.247:43166)尝试与 server2 10.160.XX.82:8000建立链接
- F5 发送SYN包给server2,但是server2并未无回应 SYN-ACK
- F5触发重传机制,三次重传后未得到服务端的响应(于是F5 触发RST机制,强制断开客户端的链接)
三、服务器数据包分析:server2 10.160.XX.82 数据包分析:
通过上述F5上数据包我们分析了clientside和serverside的数据交互,得出初步结论,F5和服务端server2建立链接失败,假设可能的原因有以下几种:
- 防火墙将F5给服务器server2发送的SYN包转发给了Server2,Server2没收到
- 防火墙将F5给服务器server2发送的SYN包转发给了Server2,Server2收到但是没有响应
- 防火墙没有收到F5给服务器server2发送的SYN包
- 防火墙收到F5给服务器server2发送的SYN包,没有给服务器server2转发
现在我们首先解决假设2,这个很easy,我们直接查看在server2上抓的数据包即可,如果在时间点20点57分12秒收到了来自防火墙的数据包,那么代表防火墙转发了数据包,server2有没有回应zai数据包中一目了然。通过数据包我们可以得到到以下信息:
server2 0.160.XX.82在20点57分03秒后就再也没有收到来自F5 10.50.XX.247:43166的数据包。
四、拨云见日:XX信防火墙数据包分析:
通过查看server2上的抓包,我们看到server2并未收到来自F5的数据包,接下来就清晰多了,就剩下XX信防火墙了,查看XX信的抓包,我们基本上就可以解决剩下的三个假设,直接定位问题。
接下来就是见证奇迹的时刻:打开XX信防火墙的数据包瞅一瞅:
通过数据包对比查看定位到故障包时间点20点57分13 14 15秒钟XX信防火墙上联接口feth11收到了F5发给server2的SYN包,但是并未从feth10接口转出。。。。
故障定位:
通过以上分析,我们大概能够还原整个故障原因:
首先客户端发起批处理操作,在不断的POST的过程中,中间XX信防火墙转发数据异常,导致服务端无法接收到F5设备转发到服务端的数据,于是F5尝试重传数据包,当三次重传都未能成功建立连接后,F5执行RST动作,强制断开服务端的链接。
F5 RST机制
一、由于F5的全代理架构,客户端到F5(clientside)、F5到服务器(serverside)维护连个TCP/IP协议栈,受益于架构设计,才可以做到客户端和F5之间跑http2,F5和服务器跑http1.1,前端跑https,后端跑http。所以F5在TCP/HTTP等协议会做RFC合规校验,再特定的包结构下或者协议安全上会触发RST动作,保障业务的安全和设备稳定性,以下是部分RST说明,详情见链接:
链接:https://support.f5.com/csp/article/K13223
总结
通过层层抓包,一步步接近问题真相,快感还是有,虽然最终不是自己F5设备的问题,但是能帮助客户第一时间定位问题,这其实也是我们作为服务商的价值,若有坑,召比填,填必满!最近一直再忙F5 CVE的事,一直没时间输出。老铁们不用担心,rancher商业版我这已经申请测试了,目前再搭demo环境,rancher联动F5和k8s集群的的干货文章在路上了!