Docker Swarm 的覆盖网络 DNS 始终将主机名解析为比容器实际 IP 小一个数字的 IP 地址

Docker Swarm 的覆盖网络 DNS 始终将主机名解析为比容器实际 IP 小一个数字的 IP 地址

我在使用 Docker Swarm 时遇到了一个非常奇怪的可重现问题。我正尝试通过 Docker Swarm 在四个 LXD 容器中部署一个 Dgraph 服务器集群。就上下文而言,Dgraph Zero 是控制服务器,每个 Dgraph Alpha 服务器都负责处理任务,并且必须在启动时连接到 Zero 服务器。Ratel 只是一个用于数据库查询和变异的 Web UI 服务器。拓扑结构如下所示:

  • 主机:KDE Neon 工作站
    • LXD 容器:零
      • Docker 节点:dg-zero
        • Docker 容器:dgraph_zero
        • Docker 容器:dgraph_ratel
    • LXD 容器:alpha1
      • Docker 节点:dg-alpha1
        • Docker 容器:dgraph_alpha1
    • LXD 容器:alpha2
      • Docker 节点:dg-alpha2
        • Docker容器:dgraph_alpha2
    • LXD 容器:alpha3
      • Docker 节点:dg-alpha3
        • Docker容器:dgraph_alpha3

docker stack deploy这些都通过使用以下 docker-compose.yml 配置以群形式部署:

version: "3"
networks:
  dgraph:
services:
  zero:
    image: dgraph/dgraph:latest
    hostname: "zero"
    volumes:
      - data-volume:/dgraph
    ports:
      - "5080:5080"
      - "6080:6080"
    networks:
      - dgraph
    deploy:
      placement:
        constraints:
          - node.hostname == dg-zero
    command: dgraph zero --my=zero:5080 --replicas 3 --bindall=true
  alpha1:
    image: dgraph/dgraph:latest
    hostname: "alpha1"
    volumes:
      - data-volume:/dgraph
    ports:
      - "8080:8080"
      - "9080:9080"
    networks:
      - dgraph
    deploy:
      placement:
        constraints:
          - node.hostname == dg-alpha1
    command: dgraph alpha --my=alpha1:7080 --lru_mb=1024 --zero=zero:5080 --bindall=true
  alpha2:
    image: dgraph/dgraph:latest
    hostname: "alpha2"
    volumes:
      - data-volume:/dgraph
    ports:
      - "8081:8081"
      - "9081:9081"
    networks:
      - dgraph
    deploy:
      placement:
        constraints:
          - node.hostname == dg-alpha2
    command: dgraph alpha --my=alpha2:7081 --lru_mb=1024 --zero=zero:5080 -o 1 --bindall=true
  alpha3:
    image: dgraph/dgraph:latest
    hostname: "alpha3"
    volumes:
      - data-volume:/dgraph
    ports:
      - "8082:8082"
      - "9082:9082"
    networks:
      - dgraph
    deploy:
      placement:
        constraints:
          - node.hostname == dg-alpha3
    command: dgraph alpha --my=alpha3:7082 --lru_mb=1024 --zero=zero:5080 -o 2 --bindall=true
  ratel:
    image: dgraph/dgraph:latest
    hostname: "ratel"
    ports:
      - "8000:8000"
    networks:
      - dgraph
    command: dgraph-ratel
volumes:
  data-volume:

所有服务均已正确部署并正在运行。问题是它们无法相互通信,因为主机名未解析为正确的 IP。

我目前正在运行一个 Swarm,当我docker container inspect在正在运行的 Zero 容器上运行时,我得到了网络配置的以下输出:

"NetworkSettings": {
            "Bridge": "",
            "SandboxID": "4548013a15833d086b281a8c2dd61ced6ea5c92f815a305f7337effe9b04a13a",
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "Ports": {
                "8080/tcp": null,
                "9080/tcp": null
            },
            "SandboxKey": "/var/run/docker/netns/4548013a1583",
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "",
            "Gateway": "",
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "IPAddress": "",
            "IPPrefixLen": 0,
            "IPv6Gateway": "",
            "MacAddress": "",
            "Networks": {
                "dgraph_dgraph": {
                    "IPAMConfig": {
                        "IPv4Address": "10.0.9.3"
                    },
                    "Links": null,
                    "Aliases": [
                        "8b48711ab0cd"
                    ],
                    "NetworkID": "lve3kr9vm42rwu1nci897zey7",
                    "EndpointID": "056ae62475da805ec212d9ec2b2e4a5c9e09e2405c15ad6e8b298e90669b512d",
                    "Gateway": "",
                    "IPAddress": "10.0.9.3",
                    "IPPrefixLen": 24,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:0a:00:09:03",
                    "DriverOpts": null
                },
                "ingress": {
                    "IPAMConfig": {
                        "IPv4Address": "10.0.0.157"
                    },
                    "Links": null,
                    "Aliases": [
                        "8b48711ab0cd"
                    ],
                    "NetworkID": "vjhpbsc1766lbvtu169fmh81l",
                    "EndpointID": "29bbc4de97e98b2e05a46dd42020dd1fbb75ff07d8c08a00b8ba6f2f4e00ec2a",
                    "Gateway": "",
                    "IPAddress": "10.0.0.157",
                    "IPPrefixLen": 24,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:0a:00:00:9d",
                    "DriverOpts": null
                }
            }
        }

可以看出,我的 Zero 容器的 IP 地址是 10.0.9.3。但是,如果我登录到我的任何 Alpha 容器的 shell 并运行ping zero它,它会尝试 ping 10.0.9.2。通过销毁并重新部署堆栈,可以始终重现此情况。我的 Zero 容器 IP 地址中的最后一个八位字节始终比主机名zero在其他三个容器中解析的 IP 地址大一。我可以使用正确的 IP 地址从彼此内部 ping 我的所有容器,但我必须使用主机名,因为在创建群集之前我不知道其他容器的地址是什么,并且我需要配置服务器群集以相互通信。

没有防火墙规则。我的 LXD 容器都可以通信。所有 LXD 容器 IP 地址在 Docker 网络配置中都列为对等。我不知道这是否相关,但即使我已发布端口,我也无法从主机容器访问我的服务。如果可能相关,我可以提供更多我发现的信息,但目前我先不提。

我如何弄清楚为什么我的 Swarm 没有将正确的主机名解析为正确的容器?

Docker 版本是来自官方仓库的 19.03.5。LXD 容器是来自 Ubuntu 的 LXD 镜像服务器的官方 18.04 云容器。主机是基于 Ubuntu 18.04 的 KDE Neon。

相关内容