问题背景
公司微服务部署在 Docker Swarm 集群(1 Master + 5 Worker),使用 overlay 网络 swarm-net 实现跨节点容器互访。集群运行稳定超过一年,所有服务通过 Docker Service 部署,容器 IP 由 overlay 网络自动分配。
故障现象
6 月 8 日晚 9:00,运维收到大量服务异常告警:API Gateway 返回 502 Bad Gateway,所有后端服务的健康检查失败。进一步排查发现一个关键模式:同一节点上的容器之间通信正常,跨节点的容器通信全部失败。
|
|
所有 overlay 跨节点通信全部中断。
排查过程
第一步:Swarm 控制面状态
|
|
所有节点状态正常,Leader 可达。
第二步:overlay 网络状态
|
|
node-06 上的 peer 条目还在,但实际通信中 node-06 处于孤立状态。这说明 control plane 的 gossip 协议分发正常,但 data plane(VXLAN 隧道)出了问题。
第三步:检查 VXLAN 端口
Docker overlay 网络使用 VXLAN(端口 4789/UDP)在节点之间建立隧道:
|
|
节点 6 的 iptables 有一条全局 REJECT 规则在末尾,且没有 4789/udp 的允许规则——所有 VXLAN 流量被防火墙拒绝。
第四步:追溯防火墙变更
|
|
检查 /var/log/secure:当天下午,有人在 node-06 上执行了 systemctl restart iptables,导致运行时 iptables 规则被重新加载为文件中的版本——而文件中恰好缺失了 Docker 自动添加的 VXLAN 规则。
Docker daemon 在启动时会在 iptables 中自动添加 overlay 网络所需的规则,但 Docker 不会将这些规则持久化到配置文件中。一旦 iptables 服务被重启,Docker 自动添加的规则就会丢失。
解决方案
- 紧急恢复:重启 node-06 上的 Docker daemon
|
|
Docker 重启后自动重新添加了 iptables 规则,VXLAN 端口恢复监听。
- 固化 Docker 防火墙规则:
|
|
- 配置 iptables 持久化服务:安装
iptables-services,确保每次 Docker 启动后自动持久化规则。
根因分析
直接原因:node-06 的 iptables 被重启后丢失了 Docker overlay 网络的 VXLAN 规则,导致跨节点容器通信中断。Swarm 集群中只要有一个节点 VXLAN 不通,所有指向该节点的流量都会超时。
深层原因:
- Docker 自动生成的 iptables 规则不会自动持久化
- 缺少"防火墙重启后自动恢复 Docker 规则"的机制
- 集群缺少 overlay 网络健康检测
预防措施
- iptables 持久化策略:所有 Docker 节点配置 iptables-services 并在
/etc/docker/daemon.json中设置"iptables": true - 防火墙变更流程:修改 iptables 配置后必须验证 Docker overlay 网络连通性
- overlay 网络心跳监控:定期从每个节点 ping overlay 网络中的固定测试容器
- Swarm 节点健康检查:监控每个节点的 gossip 协议心跳和 VXLAN 隧道状态
- 配置管理:iptables 规则文件纳入版本管理,变更可审计
总结
Docker overlay 网络的脆弱点在于它依赖 iptables 的动态规则,而这些规则不在任何配置文件中。一旦有人重启了防火墙服务,Docker 不会自动感知并重建规则。这个设计意味着:在 Docker 集群中,操作 iptables 服务就等同于操作网络基础设施。如果你不知道 Docker 在背后往 iptables 里写了什么,那就别碰 iptables。