
我在使用 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
- Docker 節點:dg-zero
- LXD 容器:alpha1
- Docker 節點:dg-alpha1
- Docker 容器:dgraph_alpha1
- Docker 節點:dg-alpha1
- LXD 容器:alpha2
- Docker 節點:dg-alpha2
- Docker 容器:dgraph_alpha2
- Docker 節點:dg-alpha2
- LXD 容器:alpha3
- Docker 節點:dg-alpha3
- Docker 容器:dgraph_alpha3
- Docker 節點:dg-alpha3
- LXD容器:零
這些都透過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。