docker swarm_docker swarm 网段
你遇到的问题是 Docker Swarm 的节点 IP 地址与 Ingress 网络地址段冲突,导致网络通信异常、服务无法正常删除或更新,并出现大量 NetworkDB DeleteEntry failed
、active attachments
等警告日志。
🔍 问题分析
你提供的信息中关键点如下:
- Docker 默认 IP 段:
10.20.0.0/16
- Swarm Ingress 网络使用段:
10.20.0.0/18
注意:
10.20.0.0/18
是10.20.0.0/16
的子集!
这意味着:
- Docker 分配给容器的 IP 地址范围(
10.20.0.0/16
)包含了 Ingress 网络使用的子网(10.20.0.0 - 10.20.63.255
)。 - 当 Ingress 网络尝试分配 IP 或进行 VXLAN 路由时,会与已有的容器网络或主机路由发生冲突。
- 这会导致:
- 网络策略混乱
- 容器间通信失败
- Ingress 流量无法正确转发
- 网络资源无法释放(如你看到的“should be removed but still has active attachments”)
- NetworkDB 报错(分布式数据库状态不一致)
🚨 日志解读
这些日志都指向网络清理失败和资源残留:
network qv0kgb2839wrc6tqv6jh7zpcd should be removed, but still has active attachments
→ 网络还在被使用,但应该被删了。可能是容器没干净退出。
deleteServiceInfoFromCluster NetworkDB DeleteEntry failed for ... does not exist or is already being deleted
→ 多个节点并发操作同一个网络条目,说明状态不一致 —— 常见于网络冲突或脑裂。
rmServiceBinding ... aborted c.serviceBindings[skey] !ok
→ 服务绑定删除失败,可能因为元数据错乱。
error while deleting neighbor entry: no such file or directory
→ ARP/邻居表项删除失败,底层网络设备或命名空间已消失。
这些错误 根本原因就是网络地址空间冲突 + 分布式状态不一致。
✅ 解决方案
✅ 步骤 1:避免 IP 地址段重叠(最重要)
你需要 将 Docker 默认 IP 池 和 Ingress 网络隔离,建议调整如下:
✅ 推荐配置:
--bip
)10.20.128.0/17
10.20.128.1 ~ 10.20.255.254
10.20.0.0/18
10.20.0.1 ~ 10.20.63.254
这样两者完全不重叠,避免冲突。
✅ 步骤 2:修改 Docker 默认 IP 段(可选)
如果你使用 dockerd
手动管理网络,可以通过配置 daemon.json
修改默认网桥:
{ \"bip\": \"10.20.128.1/17\", \"default-address-pools\": [ { \"base\": \"10.20.128.0/17\", \"size\": 24 } ]}
修改后需重启所有节点上的 Docker 服务:
sudo systemctl restart docker
⚠️ 注意:这会影响新创建的容器网络,旧容器需要重新创建。
✅ 步骤 3:重建 Ingress 网络(强烈建议)
默认的 ingress
网络一旦创建就很难修改 IP 段。你需要手动删除并重建它。
1. 查看当前 ingress 网络:
docker network inspect ingress
2. 删除默认 ingress(在 manager 节点执行):
docker network rm ingress
⚠️ 必须先停止所有使用 ingress 的服务(如
mode=replicated
, 发布了端口的服务)。
3. 重建 ingress 网络(指定子网):
docker network create \\ --driver overlay \\ --ingress \\ --subnet=10.20.0.0/18 \\ --gateway=10.20.0.1 \\ --opt com.docker.network.driver.overlay.vxlanid_list=4096 \\ ingress
注意:
vxlanid_list
可避免 VXLAN ID 冲突,推荐固定。
4. 重新部署你的服务
✅ 步骤 4:清理残留网络资源(重要)
有时旧网络未完全清理,导致后续问题。
1. 查看所有 overlay 网络:
docker network ls --filter driver=overlay
2. 删除无用网络(确认无容器使用后再删):
docker network rm <network-id>
3. 清理未使用的网络资源:
docker system prune -adocker network prune
⚠️
prune -a
会删所有未使用资源,请谨慎操作。
✅ 步骤 5:验证通信
-
启动一个测试服务:
docker service create --name test-web --publish 8080:80 nginx
-
检查是否可以从任意节点访问
http://:8080
-
检查容器 IP 是否在预期范围内:
docker exec <container> ip addr
-
检查 Ingress 网络 IP:
docker network inspect ingress | grep Subnet
🛡️ 最佳实践建议
10.20.128.0/17
10.20.0.0/18
10.20.64.0/18
开始分段7946 (tcp/udp)
, 4789 (udp)
, 2377 (tcp)
🧰 补充:检查端口和防火墙
确保以下端口在所有 Swarm 节点之间互通:
2377/tcp
– 集群管理通信7946/tcp,udp
– 节点通信(gossip)4789/udp
– VXLAN(overlay 网络流量)
# 检查端口监听ss -tulnp | grep -E \'(2377|7946|4789)\'
✅ 总结
10.20.0.0/18
属于 10.20.0.0/16
✅ 最终建议操作顺序:
- 停止所有服务
- 删除并重建
ingress
网络(使用独立子网) - 修改
daemon.json
设置bip
和default-address-pools
避开10.20.0.0/18
- 重启 Docker 服务
- 重新部署服务
- 验证跨节点访问
如果你提供 docker info
和 docker network ls
输出,我可以进一步帮你设计更优的 IP 规划。
需要我帮你写一份完整的 daemon.json
和重建 ingress 的脚本吗?