非常好的问题,这里你已经抓到了关键差异。总结如下👇
🔍 现象总结
- 在
aarch64+ iptables (legacy) 的控制节点k8s-ctrl上执行脚本 不会断 SSH。 - 在
x86_64+ iptables (nf_tables) 的工作节点k8s-work1上执行同样的脚本后,SSH 立即断联且无法重新连接。
脚本本质上做的是:
-
备份现有规则;
-
执行:
iptables-save | grep -v -i ovn | iptables-restore即:重新加载一份去掉包含 “ovn” 的规则;
-
删除与 “ovn” 相关的 ipset。
🧠 根因分析
1️⃣ legacy vs nf_tables 模式差异
这两种模式虽然命令相同,但内部实现完全不同:
| 对比项 | legacy | nf_tables |
|---|---|---|
| 实现层 | 经典 iptables 内核模块 | 使用 nftables 后端 |
| 规则保存/恢复行为 | 严格按文本匹配和顺序 | 转换为 nftables 规则集后再重建 |
| 默认链与 policy | 保留系统已有链 | 可能清空表后重新定义默认链 |
👉 在 nf_tables 模式 下,执行
iptables-save | grep -v -i ovn | iptables-restore
会触发整个 filter、nat、mangle 表被重新创建。
而 iptables-restore 默认不保留现有规则和默认链的 policy,除非你手动保留。
这意味着:
你的 SSH 允许规则(例如
ACCEPT tcp -- anywhere anywhere tcp dpt:ssh)如果没有匹配ovn字样,也可能被清空掉,因为整个表被替换。
在 legacy 模式下,由于规则链和表行为略不同,部分默认规则(例如 INPUT ACCEPT)仍被保留,因而不会断 SSH。
2️⃣ iptables-restore 的行为细节
iptables-restore 默认行为是:
重写整个表内容,而不是在原有规则上“增删改”。
grep -v -i ovn 过滤掉的只是包含 “ovn” 的行,但你忘了一点:
iptables-save 的输出里包含如下内容:
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
...
COMMIT
在 nf_tables 模式下,这些链定义、引用、计数器都很脆弱。
grep -v -i ovn 过滤后可能打断某个 COMMIT 块或去掉部分链引用,从而导致加载异常或默认 DROP。
3️⃣ SSH 掉线的直接原因
在 k8s-work1 上:
- 执行
iptables-restore重新加载时,INPUT链可能被清空; - 没有任何允许
22/tcp的规则; - 甚至可能
INPUTpolicy 默认为DROP;
→ 于是 SSH 连接瞬间被切断。
而断联后无法重新连上,是因为 iptables 状态已经被持久化在内核中,没有 ACCEPT 规则可再匹配。
✅ 安全修正版脚本
可以改成这样来安全清理 OVN 相关规则,而不影响 SSH:
#!/usr/bin/env bash
set -e
# 备份
iptables-save > "ovn-iptables-backup-$(date +%Y%m%d%H%M%S).txt"
ip6tables-save > "ovn-ip6tables-backup-$(date +%Y%m%d%H%M%S).txt"
# 临时保存当前 SSH 规则
SSH_RULES=$(iptables-save | grep dpt:ssh || true)
# 清理含 ovn 的规则(仅删除匹配的行,而不整体重载)
iptables-save | grep -v -i ovn > /tmp/iptables-no-ovn.txt
# 确保保留 SSH 规则
echo "$SSH_RULES" >> /tmp/iptables-no-ovn.txt
# 确保有基本链定义和 COMMIT
if ! grep -q "COMMIT" /tmp/iptables-no-ovn.txt; then
echo "COMMIT" >> /tmp/iptables-no-ovn.txt
fi
# 安全恢复
iptables-restore < /tmp/iptables-no-ovn.txt
# 清理 OVN ipsets
for s in $(ipset list -name | grep -i ovn); do
ipset destroy "$s" || true
done
🔧 额外建议
-
不要直接管道
grep | restore
→ 这样会把iptables-restore置于非交互状态,任何语法错误或链缺失都可能立即生效(破坏 SSH)。 -
在远程执行前测试 dry-run
iptables-save | grep -v -i ovn > /tmp/new.rules iptables-restore --test < /tmp/new.rules -
尽量使用
iptables-nft明确后端
若系统默认nf_tables,你也可以通过:update-alternatives --set iptables /usr/sbin/iptables-legacy临时切换到 legacy 模式执行清理。
💡结论
| 节点 | 后端类型 | 结果 | 原因 |
|---|---|---|---|
| k8s-ctrl (aarch64) | legacy | SSH 正常 | iptables-restore 保留默认 ACCEPT |
| k8s-work1 (x86_64) | nf_tables | SSH 断联 | iptables-restore 重写全表导致 INPUT policy 或规则丢失 |