kubernetes集群中pod访问外网丢包严重问题排查:mtu值设置不对

kubernetes集群中pod访问外网丢包严重问题排查:mtu值设置不对

问题描述和初步判断

k8s中部署的数据中台调用指云(open.imzhiyun.com)的sdk接口,调用了23次,成功了3次,其余20次都失败。我这边通过在宿主机上进行tcpdump抓包
抓包命令:

1. 查出调用sdk的容器名称
2. 查出该容器所在宿主机
3. 在这个宿主机上执行抓包命令,正对网卡eth0,域名是open.imzhiyun.com进行抓包:
tcpdump -i eth0 host open.imzhiyun.com -w result.cap

用工具分析下:


通过分析工具可以得知,三次握手会失败,丢包严重。

定位是容器网络问题还是宿主机网络问题

  1. sdk地址检查,无白名单设置,在本地环境、长沙机房开发测试环境调用正常。确保sdk地址没配错。

  2. 提供一个sdk接口调用的jar包,在宿主机上进行调用,测试宿主机网络

    多次执行,通过sdk接口调用jar包的运行结果得知,每次执行都能正常返回正常数据,说明宿主机网络正常。不正常的是容器对外网的网络。

  3. 检查容器内访问外网情况
    使用nsenter工具切换到容器网络(nsenter参考文档:https://www.cnblogs.com/zoujiaojiao/p/17021724.html)

使用百度的地址验证下:

从2个图对比可知,在容器内网络,sdk调用基本不会成功,curl 百度地址偶尔会成功,再次猜测是容器层面丢包。我们可以通过命令来确认

netstat -i


仔细观察上面 netstat 的输出界面,第二列正是每个网卡的 MTU 值。而以太网的 MTU 默认值是 1500,eth0 的 MTU 只有 1450,而docker0和容器网卡的mtu值都是1500,这个docker0和容器网卡的mtu值比eth0的大了,所以容器的mtu值比宿主机的大,大的数据包就会被拆开来传送,产生很多数据包碎片,增加丢包率,降低网络速度,要把容器mtu值设置为与eth0一样大。

mtu介绍

最大传输单元(Maximum Transmission Unit)是指一种通信协议的某一层上面所能通过的最大数据包大小(以字节为单位)。
我们在使用互联网时进行的各种网络操作,都是通过一个又一个“数据包”传输来实现的。而MTU指定了网络中可传输数据包的最大尺寸,在我们常用的以太网中,MTU是1500字节。超过此大小的数据包就会将多余的部分拆分再单独传输 。MTU的设置不是一个值天下通用,所以需要我们合理设置特殊场景的MTU 。
首先确认什么是不合理的 :
1.本地MTU值大于网络MTU值时,本地传输的数据包过大导致网络会拆包后传输,不但产生额外的数据包,而且消耗了“拆包、组包”的时间 。
2.本地MTU值小于网络MTU值时,本地传输的数据包可以直接传输,但是未能完全利用网络给予的数据包传输尺寸的上限值,传输能力未完全发挥 。
这样我们就知道:
所谓合理的设置MTU值,就是让本地的MTU值与网络的MTU值一致,既能完整发挥传输性能,又不让数据包拆分。
检测需要设置的合理的值:
大部分网络设备都是1500。如果本机的MTU比网关的MTU大,大的数据包就会被拆开来传送,这样会产生很多数据包碎片,增加丢包率,降低网络速度。把本机的MTU设成比网关的MTU小或相同,就可以减少丢包

检查宿主机网卡和容器网卡的mtu值

发现容器docker0、calico的mtu值比宿主机eth0的还大!!所以导致丢包严重。

解决问题

  1. 修改docker的mtu值
    将k8s集群所有机器的docker配置/etc/docker/daemon.json 增加 "mtu": 1450 ,如下:

    将docker服务进行重启
systemctl restart docker.service

重启后执行ip addr后docker0的mtu还是1500,别急,等重启pod后再看。

  1. 修改calico的配置
kubectl edit cm -n kube-system  canal-config
在kind: ConfigMap -- data:  下面增加 
veth_mtu: "1450"

  1. 重启所有资源
    将pod、svc、ingress等资源进行重启。

  2. 检查

netstat -i
posted @ 2023-10-16 15:22  邹姣姣  阅读(353)  评论(0编辑  收藏  举报