nf_conntrack 在 openshift4.9上的处理

最近看到一个case,是运行了高负载docker应用的主机上,nf_conntrack报告table full。其实这是一个老问题了,原因是docker在处理容器网络的时候,默认会用nat的方式,也就是容器里面看到的地址空间是一个私有地址,需要操作系统iptables/nftables来转换。而这个转化,就需要nf_conntrack来追踪和支持。

也没什么太好的解决办法,要么就用host network,绕过nat,要么就用no tracking的方式,让iptables别记录nf_conntrack。总之没有什么特别好的办法。

openshift

openshift是一个容器平台,那么openshift上是怎么处理的呢?我们实际来看看。

# 可以看到,openshift上,对应vxlan的通讯,不进行nf_conntrack的追踪,也就是说,对于vxlan的通讯,不会被记录在nf_conntrack中。
iptables -L -v -n -t raw
# Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
#  pkts bytes target     prot opt in     out     source               destination
#   88M   39G OPENSHIFT-NOTRACK  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* disable conntrack for vxlan */

# Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
#  pkts bytes target     prot opt in     out     source               destination
#   87M   54G OPENSHIFT-NOTRACK  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* disable conntrack for vxlan */

# Chain OPENSHIFT-NOTRACK (2 references)
#  pkts bytes target     prot opt in     out     source               destination
#     0     0 CT         udp  --  *      *       0.0.0.0/0            0.0.0.0/0            udp dpt:4789 NOTRACK

# 统计总的连接跟踪数
conntrack -L -o extended | wc -l
# conntrack v1.4.4 (conntrack-tools): 760 flow entries have been shown.
# 760
 
# 统计 TCP 协议各个状态的连接跟踪数
conntrack -L -o extended | awk '/^.*tcp.*$/ {sum[$6]++} END {for(i in sum) print i, sum[i]}'
# conntrack v1.4.4 (conntrack-tools): 774 flow entries have been shown.
# LAST_ACK 1
# CLOSE 78
# ESTABLISHED 428
# SYN_SENT 1
# TIME_WAIT 214
 
# 统计各个源 IP 的连接跟踪数
conntrack -L -o extended | awk '{print $7}' | cut -d "=" -f 2 | sort | uniq -c | sort -nr | head -n 10
# conntrack v1.4.4 (conntrack-tools): 805 flow entries have been shown.
#     226 10.128.0.1
#     225 192.168.7.73
#      74 192.168.7.71
#      68 10.128.0.36
#      61 172.30.0.10
#      38 127.0.0.1
#      13 10.128.0.16
#      10 10.128.0.34
#       7 10.128.0.39
#       5 10.128.0.9

# 如果没有conntrack的话,可以用下面的命令来查看
awk -F'=' '{c[$2]++} END {for ( i in c) print i,c[i]}' /proc/net/nf_conntrack | sort -g -k 3
# ...ignored...
# 10.128.0.16 dst 13
# 10.128.0.37 dst 14
# 10.128.0.43 dst 27
# 127.0.0.1 dst 38
# 192.168.7.71 dst 62
# 10.128.0.36 dst 67
# 0000:0000:0000:0000:0000:0000:0000:0001 dst 208
# 192.168.7.73 dst 220
# 10.128.0.1 dst 230

# 如果链接数量太大的话,用下面的命令先把链接信息导出来,然后在别的机器上排序
awk -F'=' '{print $2}' /proc/net/nf_conntrack > list

awk '{c[$1]++} END {for ( i in c) print i,c[i]}' list | sort -g -k 2

reference

  • https://blog.cloudflare.com/conntrack-turns-a-blind-eye-to-dropped-syns/

  • https://blog.cloudflare.com/conntrack-tales-one-thousand-and-one-flows/

  • https://www.codeleading.com/article/31982187817/

  • https://blog.longwin.com.tw/2018/07/linux-nf-conntrack-table-full-drop-packet-2018/

  • https://www.reddit.com/r/docker/comments/iq04tw/nated_containers_conntrack_table_full_inside/

  • https://forum.proxmox.com/threads/how-to-disable-nf_conntrack-completely.17957/

  • https://docs.docker.com/network/iptables/

  • https://blog.csdn.net/chunnidong6528/article/details/100975427

  • https://www.cnblogs.com/sreops/p/14023368.html

  • https://zyh.cool/posts/f41d0763/

  • https://www.redhat.com/en/blog/mitigate-tcp-syn-flood-attacks-red-hat-enterprise-linux-7-beta

  • https://access.redhat.com/discussions/6307391

  • https://access.redhat.com/solutions/781873