從零開始學習docker(十九)Swarm mode 集羣服務間通訊--RoutingMesh

在上一節中,咱們介紹了經過service create部署了wordpress和mysql,咱們發現了幾個問題:html

不一樣節點之間如何通訊?

經過service建立,將mysql和wordpress部署到cluster中,而後這兩個service位於不一樣的節點上,這兩個節點之間是能夠相互通訊的,而且能夠經過service name進行通訊,這裏面就涉及到一個DNS服務發現的問題。mysql

咱們在以前將docker-compose時講過,咱們經過docker-compose部署一個application,這個application中的service 若是是連在了同一個網絡上,那麼他們之間是能夠經過service name相互訪問的。這個底層是經過DNS服務去實現的。這是docker-compose在單機的狀況下。web

今天咱們在swarm cluster中咱們的service是位於不一樣的節點上面,他們之間也能夠經過service name進行通訊的,因此說這也是DNS的功勞在裏面。對於swarm來說,咱們有內置的DNS服務發現功能,經過swarm建立一個service時,若是是連到了一個overlay上,就能夠爲全部連到這個overlay上的service增長一條DNS記錄,而後經過DNS記錄就能夠獲得IP地址,而後就能夠訪問服務了。以下圖所示:sql

其中DNS的name用service name來表示,而對應的記錄IP並非service所在容器的IP,而是一個虛擬IP(Virtual IP)。docker

爲何會這樣?咱們想想,若是咱們的service有一個橫向的擴展(scale),那麼service就不必定會在哪一個節點上面,有一種狀況是:某個節點的service down掉了,咱們在其餘節點上從新啓動一個service,這時他的IP地址發生了變化;還有一種狀況:有多個service,所以會對應多個IP地址。若是咱們在DNS中經過實際的容器地址去表示IP地址,那麼這會產生不穩定的現象,由於IP地址有可能發生變化。這時咱們若是經過虛擬IP來解決這個問題。咱們經過service來分配一個虛擬IP,而這個虛擬IP是不會變化的,也就是說一旦咱們的service建立以後,IP就不會發生變化。可是這個虛擬IP地址背後,它所指的是實際IP(也就是容器IP),這時經過LVS實現的。服務器

下面咱們經過實驗來具體演示一下。網絡

準備環境

建立一個overlay類型的網絡,名稱叫my-demoapp

iie4bu@hostdocker:~$ docker network create -d overlay my-demo
cojus8blvkdozz8ykefozf7ml

建立一個service:這個service使用一個whoami的image,這個image會提供一個web服務的,若是咱們訪問他的8000端口的話,它會返回容器的hostname。負載均衡

iie4bu@hostdocker:~$ docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE                   PORTS
9i6wz6cg4koc        whoami              replicated          1/1                 jwilder/whoami:latest   *:8000->8000/tcp

查看whoami 運行在哪一個節點:curl

iie4bu@swarm-manager:~$ docker service ps whoami
ID                  NAME                IMAGE                   NODE                DESIRED STATE       CURRENT STATE             ERROR               PORTS
6hhuf528spdw        whoami.1            jwilder/whoami:latest   swarm-manager       Running             Running 23 minutes ago

能夠看到運行在swarm-manager節點上,能夠經過docker container ls 看到這個容器:

iie4bu@swarm-manager:~$ docker container ls
CONTAINER ID        IMAGE                   COMMAND             CREATED             STATUS              PORTS               NAMES
cc9f97cc5056        jwilder/whoami:latest   "/app/http"         23 minutes ago      Up 23 minutes       8000/tcp            whoami.1.6hhuf528spdw9j9pla7l3tv3t

監聽了本地的8000端口,

iie4bu@swarm-manager:~$ curl 127.0.0.1:8000
I'm cc9f97cc5056

返回了hostname。

而後咱們再建立一個service,也連到這個my-demo上面,這個service是busyboxservice。

iie4bu@swarm-manager:~$ docker service create --name client -d --network my-demo busybox sh -c "while true; do sleep 3600; done"
jsj6euq2qlwljg421bet1d8cr

而後查看service:

iie4bu@swarm-manager:~$ docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE                   PORTS
jsj6euq2qlwl        client              replicated          1/1                 busybox:latest          
9i6wz6cg4koc        whoami              replicated          1/1                 jwilder/whoami:latest   *:8000->8000/tcp

當client的REPLICAS變爲1/1以後,說明已經啓動成功。

查看client位於哪一個節點:

iie4bu@swarm-manager:~$ docker service ps client
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE                ERROR               PORTS
czotxqi6bi5k        client.1            busybox:latest      swarm-worker2       Running             Running about a minute ago

能夠看到是位於swarm-worker2節點上。

進入到swarm-worker2節點中,查看client的容器:

iie4bu@swarm-worker2:~$ docker container ls
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
f84e7570ee1c        busybox:latest      "sh -c 'while true; …"   4 minutes ago       Up 4 minutes                            client.1.czotxqi6bi5k8uwkgzxcrwp1r

實驗

進入swarm-worker2的client容器中,而後去ping whoami

iie4bu@swarm-worker2:~$ docker exec -it f84e sh
/ # ping whoami
PING whoami (10.0.2.5): 56 data bytes
64 bytes from 10.0.2.5: seq=0 ttl=64 time=0.085 ms
64 bytes from 10.0.2.5: seq=1 ttl=64 time=0.078 ms
64 bytes from 10.0.2.5: seq=2 ttl=64 time=0.077 ms
^C
--- whoami ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.077/0.080/0.085 ms

發現是能夠ping通whoami的,而且是ping的10.0.2.5這個IP地址。而咱們是在swarm-worker2節點中,去ping swarm-manager節點。說明是能夠經過name訪問到service,可是這個ip 10.0.2.5地址並非whoami容器的ip地址。

思考:咱們將whoami服務scale變成多個,那麼在ping whoami的時候地址會不會變呢?

擴展whoami:

iie4bu@swarm-manager:~$ docker service scale whoami=2
whoami scaled to 2
overall progress: 2 out of 2 tasks 
1/2: running   [==================================================>] 
2/2: running   [==================================================>] 
verify: Service converged

而後咱們查看whoami這個服務:

iie4bu@swarm-manager:~$ docker service ps whoami
ID                  NAME                IMAGE                   NODE                DESIRED STATE       CURRENT STATE               ERROR               PORTS
6hhuf528spdw        whoami.1            jwilder/whoami:latest   swarm-manager       Running             Running about an hour ago                                                
bw90ld3onwya        whoami.2            jwilder/whoami:latest   swarm-worker1       Running             Running 42 seconds ago

能夠看到,service被分別部署到了swarm-manager和swarm-worker1上。 

在swarm-worker1上查看:

iie4bu@swarm-worker1:~$ docker container ls
CONTAINER ID        IMAGE                     COMMAND             CREATED             STATUS                       PORTS                                                          NAMES
5559895ccaea        jwilder/whoami:latest     "/app/http"         2 minutes ago       Up 2 minutes                 8000/tcp                                                       whoami.2.bw90ld3onwyabn3vv9rfoj9qf

發現確實,在swarm-worker1中有了一個whoami容器。

而後咱們在client中再去ping一下whoami

/ # ping whoami
PING whoami (10.0.2.5): 56 data bytes
64 bytes from 10.0.2.5: seq=0 ttl=64 time=0.083 ms
64 bytes from 10.0.2.5: seq=1 ttl=64 time=0.073 ms
64 bytes from 10.0.2.5: seq=2 ttl=64 time=0.072 ms
64 bytes from 10.0.2.5: seq=3 ttl=64 time=0.072 ms
64 bytes from 10.0.2.5: seq=4 ttl=64 time=0.072 ms
64 bytes from 10.0.2.5: seq=5 ttl=64 time=0.072 ms

能夠看到:咱們在ping whoami 的時候能夠ping通,並且地址仍是10.0.2.5 是否是很奇怪?咱們如今有兩個whoami,它ping的一個地址究竟是誰的呢?

其實ip地址10.0.2.5並非咱們任何一個whoami service容器的地址,而是一個VIP(虛擬IP)。如何證實?

使用nslookup命令能夠證實。這個命令就是用來查詢DNS的。能夠去DNS服務器上查詢一個DNS name。

 例如經過nslookup查詢百度的IP地址:

iie4bu@swarm-manager:~$ nslookup www.baidu.com
Server:		8.8.8.8
Address:	8.8.8.8#53

Non-authoritative answer:
www.baidu.com	canonical name = www.a.shifen.com.
www.a.shifen.com	canonical name = www.wshifen.com.
Name:	www.wshifen.com
Address: 103.235.46.39

而後咱們在client容器中運行nslookup。

/ # nslookup whoami
Server:		127.0.0.11
Address:	127.0.0.11:53

Non-authoritative answer:

*** Can't find whoami: No answer

/ #

127.0.0.11爲DNS服務器的地址,這個DNS服務器是有cluster維護的,而咱們如今並無返回正確結果,緣由是新版busybox鏡像的問題,使用舊版本便可,如1.28.3版。
刪除busybox服務後,從新運行:

iie4bu@swarm-manager:~$ docker service rm client
client
iie4bu@swarm-manager:~$ docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE                   PORTS
9i6wz6cg4koc        whoami              replicated          2/2                 jwilder/whoami:latest   *:8000->8000/tcp
iie4bu@swarm-manager:~$ docker service create --name client -d --network my-demo busybox:1.28.3 sh -c "while true; do sleep 3600; done"
h4wlczp85sw5ez5op51plfazn
overall progress: 1 out of 1 tasks 
1/1: running   [==================================================>] 
verify: Service converged

再次進入到容器中:

iie4bu@swarm-worker2:~$ docker container ls
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
633ddfc082b9        busybox:1.28.3      "sh -c 'while true; …"   53 seconds ago      Up 52 seconds                           client.1.3iv3gworpyr5vdo0h9eortlw0
iie4bu@swarm-worker2:~$ docker exec -it 633 sh
/ #

而後執行nslookup:

iie4bu@swarm-worker2:~$ docker exec -it 633 sh
/ # nslookup whoami
Server:    127.0.0.11
Address 1: 127.0.0.11

Name:      whoami
Address 1: 10.0.2.5

返回了whoami的IP地址是10.0.2.5,可是這個地址既不是swarm-manager上的ip又不是swarm-worker1上面的ip。

看一下swarm-manager上面的whoami 的 ip:

iie4bu@swarm-manager:~$ docker container ls
CONTAINER ID        IMAGE                   COMMAND             CREATED             STATUS              PORTS               NAMES
cc9f97cc5056        jwilder/whoami:latest   "/app/http"         About an hour ago   Up About an hour    8000/tcp            whoami.1.6hhuf528spdw9j9pla7l3tv3t
iie4bu@swarm-manager:~$ docker exec -it cc9f97cc5056 sh
/app # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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
    inet 10.255.0.168/32 brd 10.255.0.168 scope global lo
       valid_lft forever preferred_lft forever
    inet 10.0.2.5/32 brd 10.0.2.5 scope global lo
       valid_lft forever preferred_lft forever
18: eth0@if19: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1450 qdisc noqueue state UP 
    link/ether 02:42:0a:ff:00:05 brd ff:ff:ff:ff:ff:ff
    inet 10.255.0.5/16 brd 10.255.255.255 scope global eth0
       valid_lft forever preferred_lft forever
20: eth1@if21: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP 
    link/ether 02:42:ac:12:00:03 brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.3/16 brd 172.18.255.255 scope global eth1
       valid_lft forever preferred_lft forever
23: eth2@if24: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1450 qdisc noqueue state UP 
    link/ether 02:42:0a:00:02:07 brd ff:ff:ff:ff:ff:ff
    inet 10.0.2.7/24 brd 10.0.2.255 scope global eth2
       valid_lft forever preferred_lft forever
/app #

在swarm-worker2上面查看一下whoami的ip:

iie4bu@swarm-worker1:~$ docker exec -it 5559895ccaea sh
/app # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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
20: eth0@if21: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1450 qdisc noqueue state UP 
    link/ether 02:42:0a:ff:00:06 brd ff:ff:ff:ff:ff:ff
    inet 10.255.0.6/16 brd 10.255.255.255 scope global eth0
       valid_lft forever preferred_lft forever
22: eth2@if23: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP 
    link/ether 02:42:ac:13:00:03 brd ff:ff:ff:ff:ff:ff
    inet 172.19.0.3/16 brd 172.19.255.255 scope global eth2
       valid_lft forever preferred_lft forever
24: eth1@if25: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1450 qdisc noqueue state UP 
    link/ether 02:42:0a:00:02:0a brd ff:ff:ff:ff:ff:ff
    inet 10.0.2.10/24 brd 10.0.2.255 scope global eth1
       valid_lft forever preferred_lft forever
/app #

發現都沒有10.0.2.5IP地址。

而後在client中使用命令nslookup tasks.whoami

/ # nslookup tasks.whoami
Server:    127.0.0.11
Address 1: 127.0.0.11

Name:      tasks.whoami
Address 1: 10.0.2.10 whoami.2.bw90ld3onwyabn3vv9rfoj9qf.my-demo
Address 2: 10.0.2.7 whoami.1.6hhuf528spdw9j9pla7l3tv3t.my-demo
/ #

咱們看到tasks.whoami一共有兩個地址,一個是10.0.2.7,一個是10.0.2.10,跟咱們上面的container中查看的一致。這纔是真正的ip地址。因此經過tasks.whoami能夠查看到真正的容器地址。

若是咱們把whoami橫向擴展成3個,會怎麼樣?

在swarm-manager中設置scale whoami=3

iie4bu@swarm-manager:~$ docker service scale whoami=3
whoami scaled to 3
overall progress: 3 out of 3 tasks 
1/3: running   [==================================================>] 
2/3: running   [==================================================>] 
3/3: running   [==================================================>] 
verify: Service converged
iie4bu@swarm-manager:~$ docker service ps whoami
ID                  NAME                IMAGE                   NODE                DESIRED STATE       CURRENT STATE               ERROR               PORTS
6hhuf528spdw        whoami.1            jwilder/whoami:latest   swarm-manager       Running             Running 2 hours ago                                                       
bw90ld3onwya        whoami.2            jwilder/whoami:latest   swarm-worker1       Running             Running about an hour ago                       
9idgk9jbrlcm        whoami.3            jwilder/whoami:latest   swarm-worker2       Running             Running 49 seconds ago

如今whoami位於三個容器,分別位於swarm-manager、swarm-worker一、swam-worker2。

這時返回到client,在執行nslookup tasks.whoami

/ # nslookup tasks.whoami
Server:    127.0.0.11
Address 1: 127.0.0.11

Name:      tasks.whoami
Address 1: 10.0.2.10 whoami.2.bw90ld3onwyabn3vv9rfoj9qf.my-demo
Address 2: 10.0.2.13 whoami.3.9idgk9jbrlcm3ufvkmbmvv2t8.my-demo
Address 3: 10.0.2.7 whoami.1.6hhuf528spdw9j9pla7l3tv3t.my-demo

能夠看到又多了一條記錄。

新增的10.0.2.13就是新增的service的地址,能夠驗證一下,在swarm-worker:

iie4bu@swarm-worker2:~$ docker exec -it f47e05019fd9 sh
/app # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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
    inet 10.255.0.168/32 brd 10.255.0.168 scope global lo
       valid_lft forever preferred_lft forever
    inet 10.0.2.5/32 brd 10.0.2.5 scope global lo
       valid_lft forever preferred_lft forever
24: eth2@if25: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1450 qdisc noqueue state UP 
    link/ether 02:42:0a:00:02:0d brd ff:ff:ff:ff:ff:ff
    inet 10.0.2.13/24 brd 10.0.2.255 scope global eth2
       valid_lft forever preferred_lft forever
26: eth1@if27: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP 
    link/ether 02:42:ac:12:00:04 brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.4/16 brd 172.18.255.255 scope global eth1
       valid_lft forever preferred_lft forever
28: eth0@if29: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1450 qdisc noqueue state UP 
    link/ether 02:42:0a:ff:00:07 brd ff:ff:ff:ff:ff:ff
    inet 10.255.0.7/16 brd 10.255.255.255 scope global eth0
       valid_lft forever preferred_lft forever

能夠看到10.0.2.13。

實際上任何一個連到my-demo網絡上的容器執行nslookup都會的到這個結果。

總結:

    在client中ping whoami,返回的ip是10.0.2.5

    而使用命令nslookup tasks.whoami 返回的ip並無10.0.2.5。

 ip:10.0.2.5就是虛擬ip。

這個虛擬IP是不會變的。由於service的數量會有變化的。而虛擬的ip與實際的container ip有一個map關係。經過這個map關係去找到了這個虛擬ip

訪問whoami這個service具體狀況 

由於咱們的busybox沒有裝curl,因此咱們用wget模擬請求。

在client container中訪問whoami:8000

/ # wget whoami:8000
Connecting to whoami:8000 (10.0.2.5:8000)
index.html           100% |*******************************|    17   0:00:00 ETA
/ # more index.html 
I'm f47e05019fd9
/ #

能夠正常訪問到。其中f47e05019fd9是container的id。

將index.html刪掉,而後在訪問一遍whoami:

/ # wget whoami:8000
Connecting to whoami:8000 (10.0.2.5:8000)
index.html           100% |*******************************|    17   0:00:00 ETA
/ # more index.html 
I'm cc9f97cc5056
/ #

發現container的id變爲cc9f97cc5056。

能夠說每次訪問whoami:8000返回內容都是不同的,也就是說咱們作了一個負載均衡。也就是說10.0.2.5背後實際上是 10.0.2.十、10.0.2.13和10.0.2.7這三個web服務器。每次訪問10.0.2.5,都會作一個負載均衡。第一次是 10.0.2.10給的響應,第二次是10.0.2.13依次循環。

這些負載均衡、VIP都是經過LVS幫咱們實現的。

簡單總結一下:

咱們這節講的其實就是Routing Mesh。這一節講的是Internal 網絡。

Internal網絡:咱們在swarm中鏈接到同一個overlay網絡中的容器是經過service name通訊的,而後這個service name對應的ip地址並非容器的具體ip地址,而是一個虛擬ip,並且若是容器作了scale,那麼經過VIP去訪問服務的時候Internal會幫咱們作負載均衡。

Ingress網絡:若是service有綁定端口,好比說咱們本節的whoami綁定的8000端口,上一節的wordpress綁定的80端口,雖然這個service在cluster中的部分節點中運行,可是能夠在swarm的任何節點經過對應的端口訪問到服務,這就是Ingress Routing Mesh。

下一節詳細介紹Ingress網絡。

相關文章
相關標籤/搜索