前面介绍了Docker管理工具-Swarm部署记录,下面重点说下Swarm基于多主机容器通信的覆盖网络
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
|
在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,整个网络结构如下图所示:
|
加入ngx_net网络的容器彼此之间可以通过IP地址通信,也可以通过名称通信。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
[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连通性的正确的工具。
|
***************当你发现自己的才华撑不起野心时,就请安静下来学习吧***************
本文转自散尽浮华博客园博客,原文链接:http://www.cnblogs.com/kevingrace/p/6883750.html,如需转载请自行联系原作者