本篇内容主要讲解“docker中Swarm mode集群服务间通信RoutingMesh分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“docker中Swarm mode集群服务间通信RoutingMesh分析”吧!
通过service create部署了wordpress和mysql,我们发现了几个问题:
通过service创建,将mysql和wordpress部署到cluster中,然后这两个service位于不同的节点上,这两个节点之间是可以相互通信的,并且可以通过service name进行通信,这里面就涉及到一个DNS服务发现的问题。
我们在之前将docker-compose时讲过,我们通过docker-compose部署一个application,这个application中的service 如果是连在了同一个网络上,那么他们之间是可以通过service name相互访问的。这个底层是通过DNS服务去实现的。这是docker-compose在单机的情况下。
今天我们在swarm cluster中我们的service是位于不同的节点上面,他们之间也可以通过service name进行通信的,所以说这也是DNS的功劳在里面。对于swarm来讲,我们有内置的DNS服务发现功能,通过swarm创建一个service时,如果是连到了一个overlay上,就可以为所有连到这个overlay上的service增加一条DNS记录,然后通过DNS记录就可以得到IP地址,然后就可以访问服务了。如下图所示:
其中DNS的name用service name来表示,而对应的记录IP并不是service所在容器的IP,而是一个虚拟IP(Virtual IP)。
为什么会这样?我们想一想,如果我们的service有一个横向的扩展(scale),那么service就不一定会在哪个节点上面,有一种情况是:某个节点的service down掉了,我们在其他节点上重新启动一个service,这时他的IP地址发生了变化;还有一种情况:有多个service,因此会对应多个IP地址。如果我们在DNS中通过实际的容器地址去表示IP地址,那么这会产生不稳定的现象,因为IP地址有可能发生变化。这时我们如果通过虚拟IP来解决这个问题。我们通过service来分配一个虚拟IP,而这个虚拟IP是不会变化的,也就是说一旦我们的service创建之后,IP就不会发生变化。但是这个虚拟IP地址背后,它所指的是实际IP(也就是容器IP),这时通过LVS实现的。
下面我们通过实验来具体演示一下。
创建一个overlay类型的网络,名称叫my-demo
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 运行在哪个节点:
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" h5wlczp85sw5ez5op51plfazn 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: eth2@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 eth2 valid_lft forever preferred_lft forever 23: eth3@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 eth3 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: eth3@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 eth3 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:0a brd ff:ff:ff:ff:ff:ff inet 10.0.2.10/24 brd 10.0.2.255 scope global eth2 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可以查看到真正的容器地址。
在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-worker1、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: eth3@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 eth3 valid_lft forever preferred_lft forever 26: eth2@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 eth2 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
因为我们的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、10.0.2.13和10.0.2.7这三个web服务器。每次访问10.0.2.5,都会做一个负载均衡。第一次是 10.0.2.10给的响应,第二次是10.0.2.13依次循环。
这些负载均衡、VIP都是通过LVS帮我们实现的。
简单总结一下:
到此,相信大家对“docker中Swarm mode集群服务间通信RoutingMesh分析”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。