You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker Swarm Overlay网络:服务可Ping通但TCP连接失败

问题

我运行着一个包含两个节点的Docker Swarm集群:管理节点(10.1.109.70)、工作节点(10.1.109.60)。创建了overlay网络(my-swarm-net),并在两个节点上部署了MySQL和Nginx服务。容器之间可互相Ping通,但telnet、nc、MySQL、HTTP等TCP连接均失败,例如从mysql1可Ping通mysql2,但无法通过telnet连接mysql2的3306端口,从nginx1也无法telnet连接nginx2的80端口。

在管理节点执行docker network inspect my-swarm-net仅能看到mysql1和nginx1,运行在工作节点的mysql2和nginx2未显示;在工作节点执行该命令,发现工作节点并未接入该网络。

已检查MySQL和Nginx端口监听正常、防火墙已开放所需端口(2377、7946、4789、3306、80),尝试重建网络并强制更新服务后问题仍存在。现咨询:

  1. 为何容器可Ping通但无法建立TCP连接?
  2. 如何确保所有服务正确加入overlay网络并实现TCP通信?

环境与配置

Swarm状态(docker info简化输出)

Swarm: active
Nodes: 2
Managers: 1
Overlay network: my-swarm-net

docker-compose.yml

version: "3.9"

services:
  mysql1:
    image: mysql:8.0.41-debian
    networks:
      - my-swarm-net
    deploy:
      placement:
        constraints:
          - "node.role == manager"

  mysql2:
    image: mysql:8.0.41-debian
    networks:
      - my-swarm-net
    deploy:
      placement:
        constraints:
          - "node.role == worker"

  nginx1:
    image: nginx:latest
    networks:
      - my-swarm-net
    deploy:
      placement:
        constraints:
          - "node.role == manager"

  nginx2:
    image: nginx:latest
    networks:
      - my-swarm-net
    deploy:
      placement:
        constraints:
          - "node.role == worker"

networks:
  my-swarm-net:
    driver: overlay
    attachable: true

已检查内容

  • 在mysql2容器内执行ss -tulnp | grep 3306,输出:
tcp   LISTEN   0  151    *:3306    *:*
  • CentOS Stream 9防火墙规则:sudo firewall-cmd --list-ports显示所有所需端口已开放。

尝试过的操作

docker network rm my-swarm-net
docker network create --driver=overlay --attachable my-swarm-net
docker service update --force mysql2
  • 工作节点执行docker ps显示mysql2和nginx2正在运行。

问题解答

1. 为何容器可Ping通但无法建立TCP连接?

Ping基于ICMP协议,容器能Ping通说明节点间的基础网络连通性没问题,但TCP连接失败且工作节点未接入overlay网络,核心原因是工作节点的overlay网络未正确初始化或同步:

  • 虽然容器在工作节点运行,但它们实际并未加入my-swarm-net,而是使用了默认的bridge网络(或临时网络),所以只能通过节点间的基础网络进行ICMP通信,无法通过overlay网络的TCP路由访问容器端口。
  • Swarm集群中,overlay网络需要跨节点同步配置,工作节点可能因Swarm agent通信异常、网络驱动加载失败,导致未成功加入集群的overlay网络,进而容器无法获取overlay网络的TCP转发规则。

2. 如何确保所有服务正确加入overlay网络并实现TCP通信?

按以下步骤排查修复:

步骤1:验证Swarm节点状态与通信

在管理节点执行:

docker node ls

确保工作节点状态为Ready,如果显示Down或Unreachable,先修复节点间的Swarm通信:

  • 检查工作节点的Docker daemon是否正常运行:systemctl status docker
  • 在工作节点重新加入Swarm集群:先执行docker swarm leave --force,再从管理节点获取加入命令(docker swarm join-token worker)重新加入。
步骤2:通过栈部署同步网络配置

不要手动创建网络后更新服务,直接通过docker stack deploy重新部署整个栈,确保网络配置自动同步到所有节点:

  1. 删除现有服务:
docker stack rm <你的栈名>
  1. 重新部署:
docker stack deploy -c docker-compose.yml <你的栈名>
步骤3:检查工作节点的overlay网络状态

在工作节点执行:

docker network ls

确认my-swarm-net存在。如果不存在,检查Docker的overlay驱动是否正常加载:

docker info | grep -A5 "Overlay"

确保输出中包含Overlay: true,如果驱动异常,重启Docker daemon:

systemctl restart docker

重启后重新加入Swarm并部署服务。

步骤4:验证容器的网络归属

在工作节点执行:

docker inspect <mysql2容器ID> | grep -A10 "Networks"

确认容器的Networks列表中包含my-swarm-net,而非默认的bridge网络。如果仍未加入,删除该服务并重新部署:

docker service rm mysql2 nginx2
docker stack deploy -c docker-compose.yml <你的栈名>
步骤5:补充防火墙规则

CentOS Stream 9的firewalld可能需要允许Docker的overlay子网流量,除了开放端口,添加富规则允许容器子网通信:

sudo firewall-cmd --add-rich-rule='rule family="ipv4" source address="10.0.0.0/8" accept' --permanent
sudo firewall-cmd --reload

注:10.0.0.0/8是Docker默认的overlay子网段,可通过docker network inspect my-swarm-net查看实际子网后调整。


内容的提问来源于stack exchange,提问作者mohamedyahya messaoud

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 04:25:23