docker集成nacos微服務的註冊地址問題

環境說明:

docker版本:20.10.3

nacos版本:1.3,而nacos鏡像是基於此版本自己製作的,並沒有拉取官方的鏡像。

 

如果我們的組件集成了nacos,那麼服務之間的調用都是採用服務名,來進行服務間的通信。所有的服務啓動的時候會向nacos註冊自己的地址。我們假設有下面的服務:

服務A---pmadmin

服務B---gateway

服務C---athena

 

問題描述

 容器內的服務A在啓動的時候,需要去訪問服務gateway進行路由註冊,結果出現連接超時,報錯日誌:

從日誌中,看出,服務A-pmadmin 取訪問 gateway,實際是先去nacos拿到了gateway的地址:10.0.0.7:65,然後通過此地址訪問gateway,但是出現了連接超時,日誌如下:

 

 

問題排查

確認gateway的地址

去nacos查詢gateway的地址,發現確實是10.0.0.7:65,地址是沒有問題,那是不是網絡的問題?

 

查看docker網絡

docker network ls
NETWORK ID     NAME              DRIVER    SCOPE
52561b34842f   bridge            bridge    local
0f0904683e30   docker_gwbridge   bridge    local
3273b79adf49   host              host      local
yuggnzybujkt   iam_default       overlay   swarm
1yl193gp08xc   ingress           overlay   swarm
45c9f5d126c9   none              null      local

iam_default這個網絡是我啓動iam 這個stack時,自動創建的網絡,我們看下這個網絡中有哪些容器

docker network inspect iam_default
[
    {
        "Name": "iam_default",
        "Id": "yuggnzybujktpkkutkf0110pu",
        "Created": "2021-03-10T16:52:56.364889741+08:00",
        "Scope": "swarm",
        "Driver": "overlay",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "10.0.1.0/24",
                    "Gateway": "10.0.1.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
             ......
            "c4d4ce1fc5330d791b8fbdf2869bfc40bd64535f5ae6d5ad51531227c5c87472": {
                "Name": "iam_nacosserver.1.o8ccif1ktcaoh7pj21qnrsyql",
                "EndpointID": "076e8d35347afe3fb5980629837d2008d1d9affe138e5dcb07c1646e4f4008c1",
                "MacAddress": "02:42:0a:00:01:06",
                "IPv4Address": "10.0.1.6/24",
                "IPv6Address": ""
            },
"fae43956f124d19248d7d00dfc1be4bb615ccde82b5875c15f8ffa4193ece218": {
                "Name": "iam_gateway.1.z40ua51l1wlhrsxdol1v35o32",
                "EndpointID": "8fc8443b9f7d19d5cb4854b6424c4178dcabf92fd7a4a955fc908dafe820f859",
                "MacAddress": "02:42:0a:00:01:0c",
                "IPv4Address": "10.0.1.12/24",
                "IPv6Address": ""
            },
"lb-iam_default": {
                "Name": "iam_default-endpoint",
                "EndpointID": "f5ecad6250919d7730a3d4bb588eb2d710d673964dd839052e2d89644cbf52a6",
                "MacAddress": "02:42:0a:00:01:04",
                "IPv4Address": "10.0.1.4/24",
                "IPv6Address": ""
            }

 

注意到iam_default這個網絡中的所有容器都在10.0.1.0/24這個網段中,並且裏面有個gateway的地址爲10.0.1.12,省略其他無關的容器詳情。

問題來了,那10.0.0.7這個地址也是gateway的地址啊,這個是從nacos的頁面確認的

我們知道,swarm集羣正常工作需要兩個overlay網絡,在現在這個環境裏,除了iam_default之外,還有一個ingress的網絡,這個網絡的主要目的是將外部流量導到我們的集羣服務,也就是iam-default網絡的服務。

那確認一下10.0.0.7這個地址是屬於 ingress網絡的。查看ingress網絡中的容器地址:發現所有的容器 在 10.0.0.0/24 這個網絡中

 

 docker network inspect ingress
[
    {
        "Name": "ingress",
        "Id": "1yl193gp08xc48ogm5l2qnf8q",
        "Created": "2021-03-10T16:52:56.364392994+08:00",
        "Scope": "swarm",
        "Driver": "overlay",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "10.0.0.0/24",
                    "Gateway": "10.0.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": true,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "344903fbfd671c51bbe4ca379a29ddcdd1b970555229caca57fdb89a8b7fe56c": {
                "Name": "iam_pmadmin.1.oqtdd8wo0rhff813a2fjjmtoq",
                "EndpointID": "f2fc565d0ceb7df1fe80a031523e324a2bef33f909d2faa5ad3f58af6f9f2f36",
                "MacAddress": "02:42:0a:00:00:c9",
                "IPv4Address": "10.0.0.201/24",
                "IPv6Address": ""
            },
          
            "c4d4ce1fc5330d791b8fbdf2869bfc40bd64535f5ae6d5ad51531227c5c87472": {
                "Name": "iam_nacosserver.1.o8ccif1ktcaoh7pj21qnrsyql",
                "EndpointID": "7582d63054303734363d7b9d8dd7d69d5a733ca31cf39b00aaafcc1968a8c5d0",
                "MacAddress": "02:42:0a:00:00:04",
                "IPv4Address": "10.0.0.4/24",
                "IPv6Address": ""
            },


            "fae43956f124d19248d7d00dfc1be4bb615ccde82b5875c15f8ffa4193ece218": {
                "Name": "iam_gateway.1.z40ua51l1wlhrsxdol1v35o32",
                "EndpointID": "0e08b11fe06750edb5252b757f464aa07dbb672976066bb69c69917b253468b3",
                "MacAddress": "02:42:0a:00:00:07",
                "IPv4Address": "10.0.0.7/24",
                "IPv6Address": ""
            },
            "ingress-sbox": {
                "Name": "ingress-endpoint",
                "EndpointID": "e0845b4d04150dfda8bb30259a2d2c9516e55b0716bdbc7c03c467e4bceb0395",
                "MacAddress": "02:42:0a:00:00:02",
                "IPv4Address": "10.0.0.2/24",
                "IPv6Address": ""
            }

 

我們確實發現了10.0.0.7這個地址是gateway的。所以,10.0.1.12和10.0.0.7是swarm網絡中 不同網絡的地址,也就是說nacos客戶端採集的地址是ingress網絡中的地址,也就是10.0.0.7這個地址。

那爲什麼服務A去訪問服務B不通呢?難道是網絡不通。

由於服務A沒有啓動,無法進入容器內部,我們進入此集羣中另外一個容器c-athena 內部,看看這個容器的網絡是什麼樣的情況?

cat /etc/hosts
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
10.0.1.8	athena

發現athena這個服務的地址10.0.1.8 此地址恰好在iam-default這個網絡中,也就是說容器裏的ip地址,採用的是集羣服務網絡,而不是ingress網絡,這也是說的通的,ingress網絡主要是用來流量導向的。

 

在此容器內部,我們看下和ingress網絡的聯通性

# ping 10.0.0.7
PING 10.0.0.7 (10.0.0.7) 56(84) bytes of data.
64 bytes from 10.0.0.7: icmp_seq=1 ttl=64 time=0.144 ms
64 bytes from 10.0.0.7: icmp_seq=2 ttl=64 time=0.075 ms
64 bytes from 10.0.0.7: icmp_seq=3 ttl=64 time=0.080 ms
64 bytes from 10.0.0.7: icmp_seq=4 ttl=64 time=0.077 ms
^C
--- 10.0.0.7 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3001ms
rtt min/avg/max/mdev = 0.075/0.094/0.144/0.028 ms

說明iam_default網絡中的容器,訪問ingress網絡中的gateway容器地址可以聯通。

那我們再ping 一下gateway,看下到底返回哪個地址

# ping gateway
PING gateway (10.0.1.12) 56(84) bytes of data.
64 bytes from iam_gateway.1.z40ua51l1wlhrsxdol1v35o32.iam_default (10.0.1.12): icmp_seq=1 ttl=64 time=0.301 ms
64 bytes from iam_gateway.1.z40ua51l1wlhrsxdol1v35o32.iam_default (10.0.1.12): icmp_seq=2 ttl=64 time=0.074 ms
64 bytes from iam_gateway.1.z40ua51l1wlhrsxdol1v35o32.iam_default (10.0.1.12): icmp_seq=3 ttl=64 time=0.065 ms
64 bytes from iam_gateway.1.z40ua51l1wlhrsxdol1v35o32.iam_default (10.0.1.12): icmp_seq=4 ttl=64 time=0.075 ms

iam_default網絡中的所有地址是互通的,都是在10.0.1.0/24網絡中的。gateway的地址是10.0.1.12,這也說明了,容器內部的ipvs服務也是正常工作的。

 

以上實驗說明:

ingress網絡和iam-default網絡互通,

容器內部的地址採用的是iam-default這個集羣服務網絡中地址,在10.0.1.0/24網段中。

 

所以最開始的那個問題,連接超時實際是

10.0.1.0/24中的某個地址去訪問10.0.0.7:65這個服務沒有連接成功。

 實驗

那麼直接通過iam_default網絡訪問gateway能否成功呢?

經過實驗發現,修改服務A配置,讓其直接訪問iam-default中gateway的地址10.0.1.12:65,

也就是說將 https://gateway/xxx改爲 https://10.0.1.12:65/xxx

這樣是可以正常通信的:

同樣,將gateway的地址的地址改爲 物理機ip也是正常啓動的。

 

問題來了:

  • 容器訪問ingress(10.0.0.0/24)不行,訪問iam_default(10.0.1.0/24)是可以的,但是又是可以ping的,那麼爲什麼網絡互通的情況下,到了tcp協議這一層就不通了呢?

 

  • nacos客戶端採集的地址是 ingress網絡中的,爲什麼不是iam-default網絡中的。

 

問題解決

查閱nacos的資料,發現可以讓客戶端自定義註冊的地址,因爲一般容器中會有多個網卡,nacos採集的地址不一定就是我們想要的那個,所以如何讓客戶端採集某個網卡的地址向服務器註冊呢?可以參見下面的解決方案,確實解決我遇到的問題。

如何讓nacos中服務註冊的ip是自定義的網段ip ( docker swarm )

 

好,採用上面方法解決了問題,那遺留的問題就是爲啥:同一網絡中的容器互相訪問的時候,通過ingress網絡無法通信(即使可以ping通ingress網絡中的地址),現在的猜想如下:

 

所謂的端口暴露,應該是物理機和集羣網絡(而不是ingress)之間的映射,容器訪問ingress網絡中的某個地址時,無法根據端口做轉發??

 

擴展知識

在服務c-athena容器內部,查看網卡信息

# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever


37646: eth0@if37647: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP group default 
    link/ether 02:42:0a:00:01:08 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.0.1.8/24 brd 10.0.1.255 scope global eth0
       valid_lft forever preferred_lft forever


37658: eth2@if37659: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:13:00:08 brd ff:ff:ff:ff:ff:ff link-netnsid 2
    inet 172.19.0.8/16 brd 172.19.255.255 scope global eth2
       valid_lft forever preferred_lft forever


37680: eth1@if37681: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP group default 
    link/ether 02:42:0a:00:00:05 brd ff:ff:ff:ff:ff:ff link-netnsid 1
    inet 10.0.0.5/24 brd 10.0.0.255 scope global eth1
       valid_lft forever preferred_lft forev

 

eth0:10.0.1.8 ——iam_default網絡

eth1: 10.0.0.5 —— ingress網絡

eth2: 172.19.0.8 ——docker_gwbridge網絡

 

前面兩個都已經證實了,證實一下eth2網絡,在主機上執行一下命令,發現,docker_gwbridge網絡中的容器地址都在172.19.0.0/24網中,

docker network inspect docker_gwbridge |grep Gateway
                    "Gateway": "172.19.0.1"

所以,以上三個網卡分別對應三個網絡,根據不同ip走不同的網卡,流量默認走docker_gwbridge網絡

# ip route
default via 172.19.0.1 dev eth2 
10.0.0.0/24 dev eth1 proto kernel scope link src 10.0.0.5 
10.0.1.0/24 dev eth0 proto kernel scope link src 10.0.1.8 
172.19.0.0/16 dev eth2 proto kernel scope link src 172.19.0.8

在主機上查看路由,也有三個網絡,默認走ens192網卡,看到最後一個docker_gwbridge,負責172.19.0.0網段。所以容器也可以通過docker_gwbridge和主機通信。

ip route
default via 10.92.4.1 dev ens192 proto static metric 100 
10.92.4.0/24 dev ens192 proto kernel scope link src 10.92.4.126 metric 100 
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 
172.19.0.0/16 dev docker_gwbridge proto kernel scope link src 172.19.0.1 

更多的docker網絡知識:

Docker網絡實戰-Overlay網絡及服務發現

Docker網絡-mesh routing 負載均衡

Docker網絡-overlay網絡驅動架構

Docker網絡-網橋網絡(bridge)驅動架構

https://blog.neuvector.com/article/docker-swarm-container-networking

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章