概述

在使用tcpdump等命令抓包时,如果有请求包,没有回复包,那么就可能是发生了丢包。丢包有很多种原因,下面分别介绍一下。

1.路由器或交换机问题

在数据包传输等过程中,会经过交换机,路由器,如果在这些设备上面有做过设置,就可能学习不到路由,导致网络无法访问。也可能链路中某个设备关机了,导致丢包。

2.防火墙拒绝

iptables/firewalld/selinux

检查报文是否有命中 iptables 规则:

iptables -t filter -nvL
iptables -t nat -nvL
iptables -t raw -nvL
iptables -t mangle -nvL
iptables-save

查看更新firewalld规则:

systemctl status firewalld.service
firewall-cmd --list-all
firewall-cmd --permanent --add/remove-port=999/tcp
firewall-cmd --zone=public --add-rich-rule 'rule family="ipv4" source address="10.45.2.35" accept' 
firewall-cmd --reload

查看selinux状态:

getenforce
ecs安全

检查ecs安全组出入方向的规则,看是否允许相关端口或ip。

硬件防火墙F5等

一般大型公司在出口还会有一个硬件防火墙F5,这里面也会有设定规则。

slb白名单

云上的应用出外网的话一般都是设置ingress为loadbalancer类型,再绑定一个公网slb。slb是可以设置白名单的,需要检查ip是否在白名单内。

3.MTU 不一致导致丢包

如果容器内网卡 MTU 和另一端宿主机内的网卡 MTU 不一致(通常是 CNI 插件问题),数据包就可能被截断导致一些数据丢失:

  • 如果容器内的 MTU 更大,发出去的包如果超过 MTU 可能就被丢弃了。
  • 如果容器内的 MTU 更小,进来的包如果超过 MTU 可能就被丢弃。

查看MTU 大小:

ip address show
ifconfig

file

4.PPS 限速丢包

一般在购买ecs时,会选择网卡带宽,如果超过阈值后就不保证能正常转发,可能就丢包了。

5.listen 了源 port_range 范围内的端口

查看内核和apiserver配置:

net.ipv4.ip_local_port_range=32768 60999
- --service-node-port-range=1-65535

file

当client发送请求时,选取其中的一个端口比如33000,而nodePort已经使用了33000端口,那么就会选取失败,导致丢包。

6.socket buffer 满导致丢包

查看buffer errors:

netstat -s | grep "buffer errors"

如果数量在持续增加,说明流量较大,socket buffer 不够用,需要调大下 buffer 容量:

net.ipv4.tcp_wmem = 4096        16384   4194304
net.ipv4.tcp_rmem = 4096        87380   6291456
net.ipv4.tcp_mem = 381462       508616  762924
net.core.rmem_default = 8388608
net.core.rmem_max = 26214400
net.core.wmem_max = 26214400

6.连接队列满导致丢包

对于 TCP 连接,三次握手建立连接,没建连成功前存储在半连接队列,建连成功但还没被应用层 accept 之前,存储在全连接队列。队列大小是有上限的,如果慢了就会丢包:

  • 如果并发太高或机器负载过高,半连接队列可能会满,新来的 SYN 建连包会被丢包。
  • 如果应用层 accept 连接过慢,会导致全连接队列堆积,满了就会丢包,通常是并发高、机器负载高或应用hang死等原因。

确认方法:

netstat -s | grep -E 'drop|overflow'

file

全连接队列可以观察 Rec-Q:

ss -lnt

file

调整队列大小:

net.ipv4.tcp_max_syn_backlog = 8096 # 调整半连接队列上限
net.core.somaxconn = 32768 # 调整全连接队列上限

7.源端口耗尽

当作为 client 发请求,或外部流量从 NodePort 进来时进行 SNAT,会从当前 netns 中选择一个端口作为源端口,端口范围由 net.ipv4.ip_local_port_range 这个内核参数决定,如果并发量大,就可能导致源端口耗尽,从而丢包。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐