关于k8s的ipvs转发svc服务访问慢的问题分析(一)

系统环境描述:

系统环境:macos,vmware下搭建k8s单master/双worker伪集群环境.

软件环境描述:

单Master结点(192.168.182.100)、WORK1(192.168.182.101)、WORK2(192.168.182.102)结点环境,网络环境为flannel+ipvs, 创建了deployment服务nginx,replicas=2,即work1、work2分别有个pod运行,同进生成svc。

备注:此3台机器最开始搭建的是calio+iptables网络环境,后来使用kubeadm reset重置后,重新搭建的flannel+ipvs.

查看ivs的配置

这个nginx的svc最开始是ClusterIP模式,因出现此问题后,改成NodePort模式测试。

问题复现:

1、在work1节点上访问svc时,当ipvs将负载轮询到work2上的pod的ip进行访问时,出现3秒的访问时间

2、在work2节点上访问svc时,当ipvs将负载轮询到work1上的pod的ip进行访问时,出现3秒的访问时间

3、在master节点上访问svc时,每次都出现3秒的访问时间;

备1:访问svc时使用curl http://10.96.223.27:3000/hostname.html命令访问;

备2:将svc改成NodePort方案时,从笔记本电脑本机访问master、worker1、worker2时均无任何问题,能够快速访问到;

备3:另外一个问题是任何一次访问后,通过watch ipvsadm -lnc,监测ipvsadm的连接变化发现每个访问不会立即释放,即处于TIME_WAIT状态,原因是k8s设计初衷为优雅的释放链接,这个暂且不管,参考https://mp.weixin.qq.com/s/sN4ztCVJT-4HGRfkApr65w

问题截图:

 

问题分析:

先来了解下k8s+flannel的网络方案架构图,以便分析网络数据包的流转:

分析:结合上图,访问svc的网络传输路径

Work1节点 —> curl —> ipvs —> flannel.1 —> ens33 ——>|vm 网络|——>  ens33 —>flannel.1 — >cni—>pod work2节点

                                                S1                S2.                                                S3.             S4

s1/s2/s3/s4定义为几个阶段

知道大概的访问路径,开始抓包,对上面s1/s2/s3/s4阶段都进行抓包,抓了work2上的包 :ens33和flannel.1 如下图,发现work1发给work2时,会发3条SYN请求,即在上面流程的S3阶段处对ens33网卡抓包,也收到了3条SYN请求,但是ens33转给flannel.1网桥处理时,前2个SYN请求未被抓到,具体原因暂时不明

问题出现在ens33未将SYN转发给flannel,具体原因不确定,这就是要去分析的:

猜测一下:

1、是否像https://www.v2ex.com/t/645262所说的,缺少什么路由?

2、另外我搭建的环境可能并不干净,因为是在搭建过calio网络方案的3台虚拟机器上reset集群后,重新搭建的基于flannel网络方案的k8s,另外虚拟机与主机网络是采用NAT方案,不像尚硅谷教育的视频教程(传送门:https://study.163.com/course/courseLearn.htm?courseId=1209568805#/learn/video?lessonId=1279884406&courseId=1209568805 )里的,基于koolshare软路由搭建的overlay网络。

3、通过抓包可以看到work1发起的前2次SYN的发起端口为46238,这2个SYN并未被work2的ens33转发给flannel,而第3次SYN的发起端口变成了39988后,SYN被成功转发给flannel, work2机器的目标端口一至都为8472。

经过一阵查询,发现以上猜测都没什么用~不过发现几个命令可以用来分析丢包问题:

ethtool -k ens33 |grep rx       #查看网卡状态

netstat -s          #查询网络协议统计数据,一般都用netstat -ntpl查看端口,这个统计参数很有用

cat /proc/net/snmp |grep Udp

通过2次请求,发现Udp下的InCsumErrors这个统计值每次都会加2次,Shit~这下有点蒙逼了,我用的明明是curl请求的http,如果真有问题,也是统计到tcp下,怎么会将错误统计在Udp下呢?颠覆了LZ对http协议的认知啊~

百度了一下发现HTTP3真的用UDP来实现,但是还是觉得奇怪,我用的CURL,curl就这么快使用http3了?

不是有那么句话:没有什么网络问题不是一次抓包不能解决的,如果不能,那就再抓一次!

再抓次导到wireshark中查看下

对比前3帧SYN(用tcpdump打出来的能看到SYN标志,此处虽然是UDP协议,但其实是SYN),发现了最大的不同,前2帧的Checksum值为0xffff,最后一帧值为missing,即没有值。终于离真相近了一步!另外看下了下数据帧中的http协议使用的是1.1版本,并不是3.0版本。

到目前,我们应该将原因定位到lvs了,猜测并思考下:

1、lvs将http以UDP连接转发,才出现的本应该是tcp连接,抓到的却是udp?  并且netstat -s统计的也是udp的Checksum错误

2、lvs什么配置或机制导致发送的第3帧与前2帧的checksum值不一致,是否有什么配置导致的?

3、是网络导致的使用UDP协议,与lvs无关?

经过查询分析,发现flannel的原理是将网络包封装在UDP里,原来如此!!!

接下来就是看怎么配置的flannel了,使用的是默认的flannel的配置文件

#下载flannel脚本

wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

#应用flannel网络

kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

经过很多查询,都查不到太多线索,最后通过“flannel udp 关闭checksum”关键词找到一篇文章记录了相关类似的问题(传送门),该文章记录的是用dig命令查询dns时出现超时,仔细了解了相关内容后,使用了该文章的命令修改flannel网卡的checksum参数,将发送端checksum校验关闭,最终发现请求正常了!!!

[root@worker2 ~]# ethtool -K flannel.1 tx-checksum-ip-generic off

归因:flannel网络设置将发送端的checksum打开了,但是flannel想利用了Checksum offloading的机制,自己不计算checksum,想留给网卡硬件来计算,这样的目的是不消耗CPU,利用网卡硬件分担CPU消耗,这原本是没问题的,但是flannel下层还有个ens33,这个ens33才是真的NIC,但是对ens33来说,从flannel发过来的是属于报文,ens33是否会对上层协议报文进行校验,然后将值填写到udp层报文内容去呢?这个我感觉不会,如果会的话,还要再了解下flannel的虚拟网络及硬件网卡之间的offloadinig机制。

总结:经过分析抓包,对k8s的网络架构有了更深入的了解。对于各层协议及各网卡处理的封包、拆包加强了一定认识。

 

  • 8
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值