K8S|线上压测之nf_conntrack: table full, dropping

Sommaire de cet article :
  1. 分析
  2. 原因
  3. 解决
  4. 总结

又是一年6.18
公司已经开启了密集压测模式,分析系统瓶颈,提升抗并发能力.
几轮压测过后,系统容量已经有了大幅度的增加.在分析的过程中,发现一个重要的核心网关,三个实例中的一个,在某个时间点陡然请求数为0.另外两个实例,出现了压力不均的情况.正常情况下,k8s中的实例的资源使用和请求数基本是一致的.

分析

立马祭出pod的资源数据,发现CPU和内存的使用比较稳定,没有明显波动.
后怀疑,是否因为同主机上的其它节点有资源抢占,结果只有一个后端服务与其运行在一起,同一时间段资源使用也不高.
一时间分析陷入了僵局.
突然间灵机一动,想着因为压测结果越来越好,后端网关的压力也越来越大,是不是系统层面的参数影响到了服务的运行?随即登陆有问题的节点查看系统日志/var/log/syslog.果然发现了重要信息

16788 May 20 02:03:28 k8s-168-35 kernel: [122013.114610] net_ratelimit: 1 callbacks suppressed
16789 May 20 02:03:28 k8s-168-35 kernel: [122013.114614] nf_conntrack: table full, dropping packet
16790 May 20 02:03:28 k8s-168-35 kernel: [122013.121276] nf_conntrack: table full, dropping packet
16791 May 20 02:03:29 k8s-168-35 kernel: [122014.151307] nf_conntrack: table full, dropping packet
16792 May 20 02:03:29 k8s-168-35 kernel: [122014.694497] nf_conntrack: table full, dropping packet
16793 May 20 02:03:29 k8s-168-35 kernel: [122014.732505] nf_conntrack: table full, dropping packet
16794 May 20 02:03:30 k8s-168-35 kernel: [122015.528920] nf_conntrack: table full, dropping packet
16795 May 20 02:03:30 k8s-168-35 kernel: [122015.804467] nf_conntrack: table full, dropping packet
16796 May 20 02:03:31 k8s-168-35 kernel: [122016.201035] nf_conntrack: table full, dropping packet
16797 May 20 02:03:31 k8s-168-35 kernel: [122016.292206] nf_conntrack: table full, dropping packet
16798 May 20 02:03:31 k8s-168-35 kernel: [122016.305049] nf_conntrack: table full, dropping packet
16799 May 20 02:03:33 k8s-168-35 kernel: [122018.216549] net_ratelimit: 3 callbacks suppressed

看到这里,差点儿爆粗口了,同样的坑去年踩过一遍了!!!

原因

错误是:kernel: nf_conntrack: table full, dropping packet
意思是:tcp连接过多,nf_conntrack表无法记录,直接丢弃的新连接.
原因是:
nf_conntrack 模块在 kernel 2.6.15(2006-01-03 发布) 被引入,支持 IPv4 和 IPv6,取代只支持 IPv4 的 ip_connktrack,用于跟踪连接的状态,供其他模块使用。
需要 NAT 的服务都会用到它,例如防火墙、Docker 等。以 iptables 的 nat 和 state 模块为例:

ipv4 2 icmp 1 29 src=127.0.0.1 dst=127.0.0.1 type=8 code=0 id=26067 src=127.0.0.1 dst=127.0.0.1 type=0 code=0 id=26067 mark=0 use=1

nat:根据转发规则修改 IP 包的源/目标地址,靠 conntrack 记录才能让返回的包能路由到发请求的机器。
state:直接用 conntrack 记录的连接状态(NEW/ESTABLISHED/RELATED/INVALID 等)来匹配防火墙过滤规则。
nf_conntrack 跟踪所有网络连接,记录存储在 1 个哈希表里。首先根据五元组算出哈希值,分配一个桶,如果有冲突就在链表上遍历,直到找到一个精确匹配的。如果没有匹配的则新建。

即使来自客户端的访问量不多,内部请求多的话照样会塞满哈希表,例如 ping 本机也会留下这么一条记录:

ipv4 2 icmp 1 29 src=127.0.0.1 dst=127.0.0.1 type=8 code=0 id=26067 src=127.0.0.1 dst=127.0.0.1 type=0 code=0 id=26067 mark=0 use=1

连接记录会在哈希表里保留一段时间,根据协议和状态有所不同,直到超时都没有收发包就会清除记录。如果服务器比较繁忙,新连接进来的速度远高于释放的速度,把哈希表塞满了,新连接的数据包就会被丢掉。此时 netfilter 变成了一个黑洞, 这发生在3层(网络层),应用程序毫无办法。

解决

解决办法

#检查配置
cat /proc/sys/net/netfilter/nf_conntrack_max
262144
#更改配置
sysctl -w net.netfilter.nf_conntrack_max=1048576

#验证配置
cat /proc/sys/net/netfilter/nf_conntrack_max  
1048576
#开机加载配置
echo 'net.netfilter.nf_conntrack_max=1048576' >>/etc/sysctl.conf

总结

之所有遇到这样的问题,说明系统的压力已经比较大了,连接数比较多,又因为网络层用的iptables模式,不知道如果切到ipvs会不会有同样的问题,留待未来kubernetes版本升级以后再看吧


相关博文

About rainbird

IOS攻城狮
This entry was posted in K8S, linux and tagged , , , , , , , , . Bookmark the permalink.

发表评论