本文已参与「新人创作礼」活动,一起开启掘金创作之路。
原文参考:www.phpmianshi.com/?id=111
概述:
在日常的服务器运维过程中,发现某段时间 /var/log/messages日志报错
nf_conntrack:table full,drop packet
简介:
nf_conntrack是内核模块中的连接追踪模块。与iptables有关。用于跟踪一个连接状态。连接跟踪状态可以供其他模块使用,例如state等,可通过以下查看
[root@VM_0_11_centos vhost]# lsmod |egrep conntracknf_conntrack_ipv4 15053 0nf_defrag_ipv4 12729 1 nf_conntrack_ipv4nf_conntrack 133053 1 nf_conntrack_ipv4libcrc32c 12644 2 sctp,nf_conntrac# 查看nf_conntrack表最大连接数[root@VM_0_11_centos vhost]# cat /proc/sys/net/netfilter/nf_conntrack_max6553500# 查看nf_conntrack表当前连接数[root@VM_0_11_centos vhost]# cat /proc/sys/net/netfilter/nf_conntrack_count114查出目前 nf_conntrack 的排名:[root@VM_0_11_centos vhost]# cat /proc/net/nf_conntrack |awk '{print $11}' |cut -d '=' -f 2 | sort |uniq -c | sort -nr | head -n 10 55 169.254.0.4 31 172.16.0.11 1 169.254.0.55 1 169.254.0.15 1 0
当有大量的网站访问时,若iptables记录连接跟踪状态,就可能导出现“nf_conntrack:table full”,从而导致一系列问题。
像php-fpm这种提供web短连接服务的项目,server端主动断开连接成功就会有个2MLS的time_wait,这些连接也都被track,该conntrack也会占用2分钟的时间。
这都不用并发太高的环境,比如每秒并发个100,2MLS的时间2分钟得生成2x60x100=12000,生成1万多的time_wait记录。这里就是个短连接不断积累的过程,不断地server主动断开,不断地timewait,这些都会被conntrack跟踪记录。所以一般默认的nf_conntrack_max=65535,很快就被塞满了。一旦塞满了就会随机的drop包。在外面看来就是丢包情况非常厉害。
解决方案:
1.优化参数
nf_conntrack_max决定连接跟踪表的大小,默认值是65535,理论最大值官方有个计算公式
CONNTRACK_MAX = RAMSIZE (in bytes) / 16384 / (ARCH / 32)
以16G的64位操作系统为例,CONNTRACK_MAX = 16*1024*1024*1024/16384/2 = 524288
nf_conntrack_buckets决定存储conntrack条目的哈希表大小,其哈希表大小通常为总表的1/8,最大为1/2。默认值是nf_conntrack_max的1/4
CONNTRACK_BUCKETS = CONNTRACK_MAX / 4
同样64G的64位操作系统,哈希最佳范围是 65536 ~ 262144 。
运行状态中通过 sysctl net.netfilter.nf_conntrack_buckets 进行查看
旧版本修改: echo 262144 > /sys/module/nf_conntrack/parameters/hashsize 进行设置
4.9内核下能直接修改 /proc/sys/net/netfilter/nf_conntrack_buckets
nf_conntrack_tcp_timeout_established决定ESTABLISHED状态连接的超时时间,默认值是5天,可以缩短到1小时,即3600。
还有些相关的系统参数`sysctl -a | grep nf_conntrack`可以调优(/etc/sysctl.conf ):
vim /etc/sysctl.conf
#加大 ip_conntrack_max 值
net.nf_conntrack_max = 524288
net.netfilter.nf_conntrack_max = 524288
net.netfilter.nf_conntrack_tcp_timeout_close_wait = 60
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 120
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 120
net.netfilter.nf_conntrack_tcp_timeout_established = 3600
增加完以上内容后,通过sysctl -p 使配置生效 。不过该方法缺点:一是重启iptables后,ip_conntrack_max值又会变成65535默认值,需要重新sysctl -p
2.移除模块
modprobe -r xt_NOTRACK nf_conntrack_netbios_ns nf_conntrack_ipv4 xt_state
modprobe -r nf_conntrack
执行完查看/proc/net/ 下面如果没用了 nf_conntrack ,就证明模块移除成功了
注意: 此方法会将state模块也一块儿移除掉,如果我们的iptables应用nat会用到state模块,卸载后导致iptables某些功能无法使用。
3.使用raw表,跳过跟踪记录。
首先先认识下什么是raw表?做什么用的?
iptables有5个链:PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING,4个表:filter,nat,mangle,raw 。
4个表的优先级由高到低的顺序为:raw–>mangle–>nat–>filter
举例来说:如果PRROUTING链上,即有mangle表,也有nat表,那么先由mangle处理,然后由nat表处理 。
RAW表只使用在PREROUTING链和OUTPUT链上,因为优先级最高,从而可以对收到的数据包在连接跟踪前进行处理。一但用户使用了RAW表,在某个链上,RAW表处理完后,将跳过NAT表和 ip_conntrack处理,即不再做地址转换和数据包的链接跟踪处理了。
RAW表可以应用在那些不需要做nat的情况下,以提高性能。如大量访问的web服务器,可以让80端口不再让iptables做数据包的链接跟踪处理,以提高用户的访问速度 。
使用方法:
(1)改/etc/sysconfig/iptables 文件中的-A INPUT -m state –state RELATED,ESTABLISHED, UNTRACKED -j ACCEPT 行。增加”UNTRACKED”,保存并restart iptables
注意: 必须更改此步,增加”UNTRACKED“,否则执行后面的语句会造成相应的端口不能访问。我使用该方法时就因为没有执行第一步的操作,造成web访问不能使用。
(2)增加以下语句
# 针对进入本机的包
/sbin/iptables -t raw -A PREROUTING -p tcp -m multiport --dports 80 -j NOTRACK
# 针对从本机出去的包
/sbin/iptables -t raw -A OUTPUT -p tcp -m multiport --sports 80 -j NOTRACK
/sbin/iptables -t raw -A PREROUTING -i lo -j NOTRACK
/sbin/iptables -t raw -A OUTPUT -o lo -j NOTRACK
注意: 一定将进入和出去的包都设置规则。这样的好处是治本,把不需要track的iptables直接notrack,那自然就不会去占hashtable空间了,更不会报错了。