背景
测试部门压测,线上服务都是采用kubernetes服务部署,汇报压测数据上不去,开始尝试调整pod数量来解决,而结果并没有改变,开始排查服务器,服务器压力都不大,开始排查日志,dmesg,其中一条error引起了注意。
1 | kernel: nf_conntrack: table full, dropping packet. |
拒绝服务了 …
nf_conntrack是什么
nf_conntrack是内核netfilter模块用于跟踪链接状态,结合kubernetes的网络应用场景,kubernetes的kube-proxy的ipvs模式,ipvs只是采用了更快的反向代理模式(hash查找),比iptables规则的线性查找更加快速,但是容器与外界的通信必少不了iptables的nat功能参与。
nf_conntrack用hash表记录已建立的连接,如果连接进来比释放的快,把hash表塞满,新连接的数据包会被丢掉,此时netfilter变成了一个黑洞,导致拒绝服务,这发生在3层(网络层),应用程序毫无办法。
centos7默认加载该模块,ubuntu默认不加载,而我们用的是centos7
相关内容
超时的相关参数:
1 | sysctl -a | grep conntrack | grep timeout |
2 | net.netfilter.nf_conntrack_generic_timeout = 600 |
3 | net.netfilter.nf_conntrack_icmp_timeout = 30 |
4 | net.netfilter.nf_conntrack_tcp_timeout_close = 10 |
5 | net.netfilter.nf_conntrack_tcp_timeout_close_wait = 3600 |
6 | net.netfilter.nf_conntrack_tcp_timeout_established = 86400 |
7 | net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 120 |
8 | net.netfilter.nf_conntrack_tcp_timeout_last_ack = 30 |
9 | net.netfilter.nf_conntrack_tcp_timeout_max_retrans = 300 |
10 | net.netfilter.nf_conntrack_tcp_timeout_syn_recv = 60 |
11 | net.netfilter.nf_conntrack_tcp_timeout_syn_sent = 120 |
12 | net.netfilter.nf_conntrack_tcp_timeout_time_wait = 120 |
13 | net.netfilter.nf_conntrack_tcp_timeout_unacknowledged = 300 |
14 | net.netfilter.nf_conntrack_udp_timeout = 30 |
15 | net.netfilter.nf_conntrack_udp_timeout_stream = 180 |
超时时间 = 连接在哈希表里保留的时间
当前跟踪的连接数:
1 | sysctl net.netfilter.nf_conntrack_count |
2 | net.netfilter.nf_conntrack_count = 1166 |
查看每个连接的详情:
1 | cat /proc/net/nf_conntrack |
哈希表大小
1 | sysctl net.netfilter.nf_conntrack_buckets |
2 | net.netfilter.nf_conntrack_buckets = 32768 |
最大跟踪连接数,默认 nf_conntrack_buckets * 4
1 | sysctl net.netfilter.nf_conntrack_max |
2 | net.netfilter.nf_conntrack_max = 131072 |
3 | |
4 | sysctl net.nf_conntrack_max |
5 | net.nf_conntrack_max = 131072 |
tunning 优化
知道问题,无非两种解决方案:
- 加大buckets和conntrack的数量
- 优化超时事件,加速移除bucket
通常推荐bucket至少 262144,max至少 1048576,不够再继续加
通常挥手状态不重要:
- net.netfilter.nf_conntrack_tcp_timeout_fin_wait # 默认 120 秒
- net.netfilter.nf_conntrack_tcp_timeout_time_wait # 默认 120 秒
- net.netfilter.nf_conntrack_tcp_timeout_close_wait # 默认 60 秒
- net.netfilter.nf_conntrack_tcp_timeout_established # 默认 432000 秒(5天)
这里我挑大了bucket和max的值进行解决