Docker swarm 集群跨服务商部署 overlay 网络无法通信的问题

通过 docker 部署 swarm 集群可以将你不同服务商的机器利用起来,串起一个大的集群环境,也方便一键部署应用到对应机器中。

但是最近观察通过 swarm 部署的应用之间,如果分布在不同的机器里面他们无法使用应用名访问,ping 对方容器 IP 也无法连接,简而言之分布在不同宿主机的容器是无法通信的,这是不合理的。

swarm 默认通过 overlay 网络驱动创建 ingress 网络,在集群中不同宿主机之间用于实现网络互联。而此时,却无法通信,但并不是所有机器之间都无法通信,而是腾讯云、aws、阿里云这些运营商宿主机之间无法通信,一些小商家的反倒非常正常。

通过多端排查,内外防火墙一切正常甚至 TCP/UDP 全部开放了,日志存在部分 IP 无法连接,看似也正常。

  • 2377 (TCP) 用于管理节点与 worker 节点之间通信

  • 7946 (TCP and UDP) 节点之间通信使用

  • 4789 (UDP) overlay 覆盖网络通信使用

在搜索了半天之后遇到类似的问题,说是阿里云之类的服务商提供的 vpc 网络实例,会使用 udp 端口 4789 来进行 vxlan 技术组网会和 docker 的 overlay 冲突。

经过多天各种百度 Google 后还是无法解决 docker swarm overlay 多机无法 ping 通 问题,偶然看到一篇 docker swarm 相关文章提到 各大云服务器专有网都是用到 vxlan 网络占用了 udp 端口 4789,而 docker swarm overlay 主机间网络通信也是用的 vxlan。所以呢 各大云服务器 应该都不支持 docker swarm overlay 网络模式。
下面是我提给阿里云的工单,阿里云员工回答:

阿里云售后工程师 : 您好,vpc 网络不支持自建 vxlan,跟底层有冲突。 不推荐您自建集群,一是难度很高花费时间很大,二是自建有很多兼容性问题。而且自建的容器集群没有阿里云容器服务官方技术支持,只能自己在网上找资料解决。 建议您考虑用阿里云提供的容器服务来搭建集群,容器服务本身是免费的,只是集群关联的云资源是付费的,您可以建个免费的集群,把现有的 ECS 加到集群的节点里面直接使用,省去了您搭建、调试集群的步骤。

阿里员工 明确回答:vpc 网络不支持的自建 vxlan, 而 docker overlay 用了 vxlan!

另外其他各大云服务器应该也是不行,有人测过腾讯云服务器也不行(这个我没验证!)。

docker swarm 集群可以使用阿里云提供的容器服务(阿里云容器服务提供了 docker swarm 或 k8s 的集群服务),或者自己机房搭建!
至于自建 k8s 还没弄过暂时不清楚。

https://blog.csdn.net/a704397849/article/details/100054793

事情到这里时,以为解决不了了,但不应该,应该有大量的人使用跨运营商组网,怎么会无法连接呢,如果存在问题网上应该有大量的人吐槽反馈。

vpc 网络和经典网络的区别就是,VPC 网络的实例绑定是内网 IP,经典网络的实例绑定的直接是公网 IP。而现在基本上都是 VPC 网络,进而淘汰了经典网络,方便大厂自己进行管理和组网以及实现其他防火墙与异地组网等。

最后我又去观察了下 aws 和腾讯云的 ingress 网络情况,在 peers 字段里。发现它们都能够连接到其他小商家的服务器,却无法在腾讯、aws 之间互相连接。

docker network inspect ingress

返回的节选

{
//...
"Peers": [
            {
                "Name": "66bd255fa98b",
                "IP": "172.x.x.x"
            },
            {
                "Name": "aa567ab71f18",
                "IP": "142.x.x.x"
            },
            {
                "Name": "ded7ed86f4c1",
                "IP": "66.x.x.x"
            },
            {
                "Name": "b1caadd3cdfe",
                "IP": "50.x.x.x"
            },
            {
                "Name": "449dede233f6",
                "IP": "67.x.x.x"
            },
            {
                "Name": "5cda4076ce56",
                "IP": "13.x.x.x"
            },
            {
                "Name": "bde9bb923eff",
                "IP": "130.x.x.x"
            },
            {
                "Name": "b6eccacb62a8",
                "IP": "118.x.x.x"
            }
        ]

//...
}

结果之中观察发现第一个 172.x.x.x.x 非常明显这是一个内网地址,所以最终猜测另外一个原因,这可能是因为集群 worker 加入集群网络时没有正确广播自己的 IP,导致其他服务器无法或者错误连接这台服务器才导致这一问题。

事实经过验证也确实如此,只需要在 worker 机器加入集群时正确广播自己的 IP 就行了,docker 也为此配置了参数 --advertise-addr

  1. worker 离开集群,会关闭所有容器服务,需要注意。

    docker swarm leave
  2. worker 重新加入集群,需要提前寻找集群密钥,并配置 --advertise-addr

    docker swarm join --token SWMTKN-1-xxxxxxxxxxxxxxxxx <manager-ip>:2377 --advertise-addr <worker-public-ip>:2377

    问题自此解决了,可能阿里云 VPC 网络下 4789 端口的 vxlan 确实存在问题,但我并没有遇到,猜测如果存在且未解决的话,应该只存在于服务商内网通信里面。

Comments