Docker Swarm 的覆蓋網路 DNS 總是將主機名稱解析為比容器實際 IP 小一號的 IP 位址

Docker Swarm 的覆蓋網路 DNS 總是將主機名稱解析為比容器實際 IP 小一號的 IP 位址

我在使用 Docker Swarm 時遇到了一個非常奇怪的可重現問題。我正在嘗試透過 Docker Swarm 跨四個 LXD 容器部署 Dgraph 伺服器叢集。對於上下文,Dgraph Zero 是控制伺服器,每個 Dgraph Alpha 伺服器負責提升,並且必須在啟動時連接到零伺服器。 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。

我目前正在運行一個群,當我docker container inspect在正在運行的零容器上運行時,我得到以下網路配置輸出:

"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
                }
            }
        }

可以看到,我的零容器的IP位址是10.0.9.3。但是,如果我登入任何 Alpha 容器的 shell 並執行ping zero它,則會嘗試 ping 10.0.9.2。透過銷毀並重新部署堆疊,可以一致地重現這一點。我的零容器的 IP 位址中的最後一個八位元組總是比主機名稱zero在其他三個容器中解析為的 IP 位址大 1。我可以使用正確的 IP 位址對所有容器進行 ping 操作,但我必須使用主機名,因為我不知道在建立 swarm 之前另一個容器的位址是什麼,而且我需要配置伺服器叢集來彼此進行通訊。

沒有適當的防火牆規則。我的 LXD 容器都可以通訊。所有 LXD 容器 IP 位址都在 Docker 網路配置中以對等點列出。我不知道它是否相關,但即使我已經發布了端口,我也無法從主機容器訪問我的服務。如果可能相關,我可以提供更多我發現的信息,但現在我將不予考慮。

如何找出為什麼我的叢集無法將正確的主機名稱解析到正確的容器?

官方倉庫中的 Docker 版本為 19.03.5。 LXD 容器是來自 Ubuntu LXD 映像伺服器的官方 18.04 雲端容器。主機是基於 Ubuntu 18.04 的 KDE Neon。

相關內容