CentOS 7.9 的网关机器上 nat 表有上万条 DNAT 规则,每次 iptables-restore 要八秒,这期间新建连接全部失败,业务侧看到成片的超时。

一开始怀疑是「用了 -w 但没有设置足够的等待时间,锁竞争让恢复更慢」,查了一圈,方向不对。

真正麻烦的地方在于,几个原因的现象几乎一样。nat 表在规则加载时会整表重建,期间匹配不到任何规则。还有一种是规则按 IP 逐条写,没有做聚合,条数随着客户增长线性膨胀。

少数情况下是conntrack 表在重建时被清空,长连接也跟着断。

先看表里到底有多少条

iptables -t nat -L -n | wc -l && iptables -t nat -S | wc -l

然后把相邻网段聚合成大段

iptables -t nat -S | awk '{print $4}' | sort -u | head -20

随后用 ipset 把逐条规则换成集合匹配

ipset create dnat_map hash:ip,port && ipset add dnat_map 10.0.0.5,8080

末了改用 -w 并择时下发规则

iptables-restore -w 10 < /etc/sysconfig/nat.rules

恢复的判定其实很直接。iptables -t nat -S 的规则数量降到百条以内,restore 在一秒内完成,切流期间新建连接不再成片失败。

补一句。nat 表是整表替换的,规则越多空窗越长;上万条规则的场景应该上 ipset 或者直接换成 nftables,别再堆 iptables 条目。如果同一现象隔几天又出现,说明根因没找到,别当偶发处理。

作者 9823189