前面介紹了Docker管理工具-Swarm部署記錄,下面重點說下Swarm基于多主機容器通信的覆寫網絡
在Docker版本1.12之後swarm模式原生支援覆寫網絡(overlay networks),可以先建立一個覆寫網絡,然後啟動容器的時候啟用這個覆寫網絡,
這樣隻要是這個覆寫網絡内的容器,不管在不在同一個主控端上都能互相通信,即跨主機通信!不同覆寫網絡内的容器組之間是互相隔離的(互相ping不通)。
swarm模式的覆寫網絡包括以下功能:
1)可以附加多個服務到同一個網絡。
2)預設情況下,service discovery為每個swarm服務配置設定一個虛拟IP位址(vip)和DNS名稱,使得在同一個網絡中容器之間可以使用服務名稱為互相連接配接。
3)可以配置使用DNS輪循而不使用VIP
4)為了可以使用swarm的覆寫網絡,在啟用swarm模式之間你需要在swarm節點之間開放以下端口:
5)TCP/UDP端口7946 – 用于容器網絡發現
6)UDP端口4789 – 用于容器覆寫網絡
執行個體如下:
-----------在Swarm叢集中建立overlay網絡------------
[root@manager-node ~]# docker network create --driver overlay --opt encrypted --subnet 10.10.19.0/24 ngx_net
參數解釋:
–opt encrypted 預設情況下swarm中的節點通信是加密的。在不同節點的容器之間,可選的–opt encrypted參數能在它們的vxlan流量啟用附加的加密層。
--subnet 指令行參數指定overlay網絡使用的子網網段。當不指定一個子網時,swarm管理器自動選擇一個子網并配置設定給網絡。
[root@manager-node ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
d7aa48d3e485 bridge bridge local
9e637a97a3b9 docker_gwbridge bridge local
b5a41c8c71e7 host host local
7f4fx3jf4dbr ingress overlay swarm
3x2wgugr6zmn ngx_net overlay swarm
0808a5c72a0a none null local
由上可知,Swarm當中擁有2套覆寫網絡。其中"ngx_net"網絡正是我們在部署容器時所建立的成果。而"ingress"覆寫網絡則為預設提供。
Swarm 管理節點會利用 ingress 負載均衡以将服務公布至叢集之外。
在将服務連接配接到這個建立的網絡之前,網絡覆寫到manager節點。上面輸出的SCOPE為 swarm 表示将服務部署到Swarm時可以使用此網絡。
在将服務連接配接到這個網絡後,Swarm隻将該網絡擴充到特定的worker節點,這個worker節點被swarm排程器配置設定了運作服務的任務。
在那些沒有運作該服務任務的worker節點上,網絡并不擴充到該節點。
------------------将服務連接配接到overlay網絡-------------------
[root@manager-node ~]# docker service create --replicas 5 --network ngx_net --name my-test -p 80:80 nginx
上面名為"my-test"的服務啟動了3個task,用于運作每個任務的容器都可以彼此通過overlay網絡進行通信。Swarm叢集将網絡擴充到所有任務處于Running狀态的節點上。
[root@manager-node ~]# docker service ls
ID NAME REPLICAS IMAGE COMMAND
dsaxs6v463g9 my-test 5/5 nginx
在manager-node節點上,通過下面的指令檢視哪些節點有處于running狀态的任務:
[root@manager-node ~]# docker service ps my-test
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR
8433fuiy7vpu0p80arl7vggfe my-test.1 nginx node2 Running Running 2 minutes ago
f1h7a0vtojv18zrsiw8j0rzaw my-test.2 nginx node1 Running Running 2 minutes ago
ex73ifk3jvzw8ukurl8yu7fyq my-test.3 nginx node1 Running Running 2 minutes ago
cyu73jd8psupfhken23vvmpud my-test.4 nginx manager-node Running Running 2 minutes ago
btorxekfix4hcqh4v83dr0tzw my-test.5 nginx manager-node Running Running 2 minutes ago
可見三個節點都有處于running狀态的任務,是以my-network網絡擴充到三個節點上。
可以查詢某個節點上關于my-network的詳細資訊:
[root@manager-node ~]# docker network inspect ngx_net
[
{
"Name": "ngx_net",
"Id": "3x2wgugr6zmn1mcyf9k1du27p",
"Scope": "swarm",
"Driver": "overlay",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "10.10.19.0/24",
"Gateway": "10.10.19.1"
}
]
},
"Internal": false,
"Containers": {
"00f47e38deea76269eb03ba13695ec0b0c740601c85019546d6a9a17fd434663": {
"Name": "my-test.5.btorxekfix4hcqh4v83dr0tzw",
"EndpointID": "ea962d07eee150b263ae631b8a7f8c1950337c11ef2c3d488a7c3717defd8601",
"MacAddress": "02:42:0a:0a:13:03",
"IPv4Address": "10.10.19.3/24",
"IPv6Address": ""
},
"957620c6f7abb44ad8dd2d842d333f5e5c1655034dc43e49abbbd680de3a5341": {
"Name": "my-test.4.cyu73jd8psupfhken23vvmpud",
"EndpointID": "f33a6e9ddf1dd01bcfc43ffefd19e19514658f001cdf9b2fbe23bc3fdf56a42a",
"MacAddress": "02:42:0a:0a:13:07",
"IPv4Address": "10.10.19.7/24",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.driver.overlay.vxlanid_list": "257"
},
"Labels": {}
}
]
從上面的資訊可以看出在manager-node節點上,名為my-test的服務有一個名為my-test.5.btorxekfix4hcqh4v83dr0tzw和
my-test.4.cyu73jd8psupfhken23vvmpud的task連接配接到名為ngx_net的網絡上(另外兩個節點node1和node2同樣可以用上面指令檢視)
[root@node1 ~]# docker network inspect ngx_net
.......
"Containers": {
"7d9986fad5a7d834676ba76ae75aff2258f840953f1dc633c3ef3c0efd2b2501": {
"Name": "my-test.3.ex73ifk3jvzw8ukurl8yu7fyq",
"EndpointID": "957ca19f3d5480762dbd14fd9a6a1cd01a8deac3e8e35b23d1350f480a7b2f37",
"MacAddress": "02:42:0a:0a:13:06",
"IPv4Address": "10.10.19.6/24",
"IPv6Address": ""
},
"9e50fceada1d7c653a886ca29d2bf2606debafe8c8a97f2d79104faf3ecf8a46": {
"Name": "my-test.2.f1h7a0vtojv18zrsiw8j0rzaw",
"EndpointID": "b1c209c7b68634e88e0bf5e100fe03435b3096054da6555c61e6c207ac651ac2",
"MacAddress": "02:42:0a:0a:13:05",
"IPv4Address": "10.10.19.5/24",
"IPv6Address": ""
}
},
.........
[root@node2 web]# docker network inspect ngx_net
........
"Containers": {
"4bdcce0ee63edc08d943cf4a049eac027719ff2dc14b7c3aa85fdddc5d1da968": {
"Name": "my-test.1.8433fuiy7vpu0p80arl7vggfe",
"EndpointID": "df58de85b0a0e4d128bf332fc783f6528d1f179b0f9f3b7aa70ebc832640d3bc",
"MacAddress": "02:42:0a:0a:13:04",
"IPv4Address": "10.10.19.4/24",
"IPv6Address": ""
}
},
可以通過查詢服務來獲得服務的虛拟IP位址,如下:
[root@manager-node ~]# docker service inspect --format='{{json .Endpoint.VirtualIPs}}' my-test
[{"NetworkID":"7f4fx3jf4dbrp97aioc05pul4","Addr":"10.255.0.6/16"},{"NetworkID":"3x2wgugr6zmn1mcyf9k1du27p","Addr":"10.10.19.2/24"}]
由上結果可知,10.10.19.2其實就是swarm叢集内部的vip,整個網絡結構如下圖所示:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnL2IjN0AzMxUjMtkjN4kzM5ITMwEjM1AzNxAjMtYTO1cDM58CX1AzNxAjMvwlN5UzNwkzLcd2bsJ2Lc12bj5ycn9Gbi52YuUTMwIzcldWYtl2Lc9CX6MHc0RHaiojIsJye.png)
加入ngx_net網絡的容器彼此之間可以通過IP位址通信,也可以通過名稱通信。
[root@node2 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4bdcce0ee63e nginx:latest "nginx -g 'daemon off" 22 minutes ago Up 22 minutes 80/tcp my-test.1.8433fuiy7vpu0p80arl7vggfe
[root@node2 ~]# docker exec -ti 4bdcce0ee63e /bin/bash
root@4bdcce0ee63e:/# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default
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
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
1786: eth0@if1787: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP group default
link/ether 02:42:0a:ff:00:08 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 10.255.0.8/16 scope global eth0
valid_lft forever preferred_lft forever
inet 10.255.0.6/32 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::42:aff:feff:8/64 scope link
valid_lft forever preferred_lft forever
1788: eth1@if1789: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:12:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 1
inet 172.18.0.3/16 scope global eth1
valid_lft forever preferred_lft forever
inet6 fe80::42:acff:fe12:3/64 scope link
valid_lft forever preferred_lft forever
1791: eth2@if1792: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP group default
link/ether 02:42:0a:0a:13:04 brd ff:ff:ff:ff:ff:ff link-netnsid 2
inet 10.10.19.4/24 scope global eth2
valid_lft forever preferred_lft forever
inet 10.10.19.2/32 scope global eth2
valid_lft forever preferred_lft forever
inet6 fe80::42:aff:fe0a:1304/64 scope link
valid_lft forever preferred_lft forever
root@4bdcce0ee63e:/# ping 10.10.19.3
PING 10.10.19.3 (10.10.19.3): 56 data bytes
64 bytes from 10.10.19.3: icmp_seq=0 ttl=64 time=0.890 ms
64 bytes from 10.10.19.3: icmp_seq=1 ttl=64 time=0.622 ms
.....-
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.622/0.756/0.890/0.134 ms
root@4bdcce0ee63e:/# ping 10.10.19.6
PING 10.10.19.6 (10.10.19.6): 56 data bytes
64 bytes from 10.10.19.6: icmp_seq=0 ttl=64 time=0.939 ms
64 bytes from 10.10.19.6: icmp_seq=1 ttl=64 time=0.590 ms
----------------------------使用swarm模式的服務發現--------------------------
預設情況下,當建立了一個服務并連接配接到某個網絡後,swarm會為該服務配置設定一個VIP。此VIP根據服務名映射到DNS。在網絡上的容器共享該服務的DNS映射,
是以網絡上的任意容器可以通過服務名通路服務。
在同一overlay網絡中,不用通過端口映射來使某個服務可以被其它服務通路。Swarm内部的負載均衡器自動将請求發送到服務的VIP上,然後分發到所有的
active的task上。
如下示例:
在同一個網絡中添加了一個centos服務,此服務可以通過名稱my-test通路前面建立的nginx服務:
[root@manager-node ~]# docker service create --name my-centos --network ngx_net centos
查詢centos運作在哪個節點上(上面建立指令執行後,需要一段時間才能完成這個centos服務的建立)
[root@manager-node ~]# docker service ps my-centos
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR
e03pqgkjs3l1qizc6v4aqaune my-centos.1 centos node2 Running Preparing 4 seconds ago
登入centos運作的節點(由上可知是node2節點),打開centos的互動shell:
[root@node2 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS NAMES
e4554490d891 centos:latest "/bin/bash" About an hour ago Up About an hour my-centos.1.9yk5ie28gwk9mw1h1jovb68ki
[root@node2 ~]# docker exec -ti my-centos.1.9yk5ie28gwk9mw1h1jovb68ki /bin/bash
root@4bdcce0ee63e:/# nslookup my-test
Server: 127.0.0.11
Address 1: 127.0.0.11
Name: my-test
Address 1: 10.10.19.2 10.10.19.2
從centos容器内部,使用特殊查詢 查詢DNS,來找到my-test服務的所有容器的IP位址:
root@4bdcce0ee63e:/# nslookup tasks.my-test
Server: 127.0.0.11
Address 1: 127.0.0.11
Name: tasks.my-test
Address 1: 10.10.19.4 my-test.1.8433fuiy7vpu0p80arl7vggfe
Address 2: 10.10.19.5 my-test.2.f1h7a0vtojv18zrsiw8j0rzaw
Address 3: 10.10.19.6 my-test.3.ex73ifk3jvzw8ukurl8yu7fyq
Address 2: 10.10.19.7 my-test.4.cyu73jd8psupfhken23vvmpud
Address 3: 10.10.19.3 my-test.5.btorxekfix4hcqh4v83dr0tzw
從centos容器内部,通過wget來通路my-test服務中運作的nginx網頁伺服器
root@4bdcce0ee63e:/# wget -O- my-test
Connecting to my-test (10.10.19.2:80)
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
Swarm的負載均衡器自動将HTTP請求路由到VIP上,然後到一個active的task容器上。它根據round-robin選擇算法将後續的請求分發到另一個active的task上。
-----------------------------------為服務使用DNS round-robin-----------------------------
在建立服務時,可以配置服務直接使用DNS round-robin而無需使用VIP。這是通過在建立服務時指定 --endpoint-mode dnsrr 指令行參數實作的。
當你想要使用自己的負載均衡器時可以使用這種方式。
如下示例(注意:使用DNS round-robin方式建立服務,不能直接在指令裡使用-p指定端口)
[root@manager-node ~]# docker service create --replicas 3 --name my-dnsrr-nginx --network ngx_net --endpoint-mode dnsrr nginx
[root@manager-node ~]# docker service ps my-dnsrr-nginx
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR
65li2zbhxvvoaesndmwjokouj my-dnsrr-nginx.1 nginx node1 Running Running 2 minutes ago
5hjw7wm4xr877879m0ewjciuj my-dnsrr-nginx.2 nginx manager-node Running Running 2 minutes ago
afo7acduge2qfy60e87liz557 my-dnsrr-nginx.3 nginx manager-node Running Running 2 minutes ago
當通過服務名稱查詢DNS時,DNS服務傳回所有任務容器的IP位址:
root@4bdcce0ee63e:/# nslookup my-dnsrr-nginx
Server: 127.0.0.11
Address 1: 127.0.0.11
Name: my-dnsrr-nginx
Address 1: 10.10.19.10 my-dnsrr-nginx.3.0sm1n9o8hygzarv5t5eq46okn.my-network
Address 2: 10.10.19.9 my-dnsrr-nginx.2.b3o1uoa8m003b2kk0ytl9lawh.my-network
Address 3: 10.10.19.8 my-dnsrr-nginx.1.55za4c83jq9846rle6eigiq15.my-network
需要注意的是:一定要确認VIP的連通性
通常Docker官方推薦使用dig,nslookup或其它DNS查詢工具來查詢通過DNS對服務名的通路。因為VIP是邏輯IP,ping并不是确認VIP連通性的正确的工具。
*************** 當你發現自己的才華撐不起野心時,就請安靜下來學習吧!***************