0.Docker Swarm是什么?
单机的Docker资源是有限的,不能方便地进行横向扩展,也难以实现容器的故障恢复,容器中运行的服务做到无中断地更新也比较困难。这一系列的问题下,Docker Swarm这样的容器编排工具就应运而生了。
Docker Swarm是Docker内置的一个容器编排工具,但它不是唯一的容器编排工具。常见的还有Kubernetes,不过Kubernetes比较复杂,上手难度大、学习成本高、开发运维人员的技术要求也相应提高。
所以,中小企业使用Docker Swarm更为合适。
Docker Swarm也是一个Docker的集群,这也符合计算机领域的常规思路:单机无法实现的事情就通过集群来完成。既然是集群,就涉及到集群的架构。Docker Swarm集群中的节点分为manager节点和worker节点,manager节点负责控制集群的配置、服务(task)的运行、查看集群状态等工作,而worker节点只能用来运行服务,也就是容器。
1.准备Docker Swarm环境
1.1 初始化Docker Swarm
在172.18.20.53执行初始化命令
$ docker swarm init
Swarm initialized: current node (j6cm8ajrkzpmy0whc9pk5cvu5) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-4lgkwzzstiqq7u0owwd0cz5lnw8ao6qk62v2siq0usda4o5dph-aw8x1sik3nrrfzg262el2msb6 172.18.20.53:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
初始化完成后,当前节点为manager节点,并且会提示如何将新的节点加入此Docker Swarm集群,其中需要通过--token参数指定token,否则无法成功加入。
如果没有及时加入新的节点,并记住上面的token也没有关系,可以使用以下命令分别查看添加manager和worker节点的token。
$ docker swarm join-token --help
Usage: docker swarm join-token [OPTIONS] (worker|manager)
Manage join tokens
Options:
-q, --quiet Only display token
--rotate Rotate join token
$ docker swarm join-token worker
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-4lgkwzzstiqq7u0owwd0cz5lnw8ao6qk62v2siq0usda4o5dph-aw8x1sik3nrrfzg262el2msb6 172.18.20.53:2377
$ docker swarm join-token manager
To add a manager to this swarm, run the following command:
docker swarm join --token SWMTKN-1-4lgkwzzstiqq7u0owwd0cz5lnw8ao6qk62v2siq0usda4o5dph-as56uu7na38f7uox1py8a4par 172.18.20.53:2377
从以上内容可以看出,Docker Swarm中添加manager和worker节点的命令是一致的,只是不同的token决定了加入的节点是manager节点还是worker节点。
1.2 添加新节点到Docker Swarm中
在172.18.20.54执行以下命令,加入manager节点
$ docker swarm join --token SWMTKN-1-4lgkwzzstiqq7u0owwd0cz5lnw8ao6qk62v2siq0usda4o5dph-as56uu7na38f7uox1py8a4par 172.18.20.53:2377
This node joined a swarm as a manager.
在172.18.20.55执行以下命令,加入worker节点
$ docker swarm join --token SWMTKN-1-4lgkwzzstiqq7u0owwd0cz5lnw8ao6qk62v2siq0usda4o5dph-aw8x1sik3nrrfzg262el2msb6 172.18.20.53:2377
This node joined a swarm as a worker.
1.3 查看集群中的节点
$ docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
j6cm8ajrkzpmy0whc9pk5cvu5 * 172.18.20.53 Ready Active Leader 19.03.8
e1u5wv4x4tfpe9j6kfd1byau6 172.18.20.54 Ready Active Reachable 19.03.8
b5w8u1dprgqk6g5hwgvf21rm4 172.18.20.55 Ready Active 19.03.8
查看节点只能在manager节点下进行,在worker节点下会有如下错误提示
$ docker node ls
Error response from daemon: This node is not a swarm manager. Worker nodes can't be used to view or modify cluster state. Please run this command on a manager node or promote the current node to a manager.
2.Docker Swarm与Overlay Network
首先使用一个whoami的镜像来进行试验
docker pull stefanscherer/whoami
其项目地址为 https://github.com/StefanScherer/whoami
项目主页中可以看到其默认的web服务端口号为8080.
$ docker service create --name whoami -p 9090:8080 stefanscherer/whoami
9va4qq1p05go0q0pr4rppntdd
overall progress: 1 out of 1 tasks
1/1: running [==================================================>]
verify: Service converged
$ docker service ps whoami
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
qdbs2557cu79 whoami.1 stefanscherer/whoami:latest 172.18.20.55 Running Running 2 minutes ago
使用在Docker Swarm中运行一个service,从结果可以看到这个容器被分配到172.18.20.55这个节点运行。
接着使用curl来验证whoami的输出结果
$ curl http://172.18.20.55:9090
I'm 3ce32f72a750 running on linux/amd64
IP: 127.0.0.1
IP: 10.0.0.8
IP: 172.19.0.3
ENV: PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
ENV: HOSTNAME=3ce32f72a750
ENV: HOME=/
GET / HTTP/1.1
Host: 172.18.20.55:9090
User-Agent: curl/7.54.0
Accept: */*
这个结果是预料之中的,容器在该节点运行,那么该节点作为宿主机,其9090端口与容器的8080端口映射,外部能够访问,这是理所当然的。
然后继续使用curl请求其它两个节点的9090端口的时候,“意外”发生了
$ curl http://172.18.20.53:9090
I'm 3ce32f72a750 running on linux/amd64
IP: 127.0.0.1
IP: 10.0.0.8
IP: 172.19.0.3
ENV: PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
ENV: HOSTNAME=3ce32f72a750
ENV: HOME=/
GET / HTTP/1.1
Host: 172.18.20.53:9090
User-Agent: curl/7.54.0
Accept: */*
$ curl http://172.18.20.54:9090
I'm 3ce32f72a750 running on linux/amd64
IP: 127.0.0.1
IP: 10.0.0.8
IP: 172.19.0.3
ENV: PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
ENV: HOSTNAME=3ce32f72a750
ENV: HOME=/
GET / HTTP/1.1
Host: 172.18.20.54:9090
User-Agent: curl/7.54.0
Accept: */*
其它两个节点的9090端口居然也能访问?
使用docker inspect
或docker service inspect
命令可以看出,whoami这个容器使用的是ingress网络(也就是overlay网络)
Docker Swarm默认使用的就是overlay网络。
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
684be8ae630e bridge bridge local
061dd53e57b9 docker_gwbridge bridge local
4cfc45bc4cc7 host host local
4pluvrq8bgsu ingress overlay swarm
0ccda9e2745e none null local
查看ingress的详细信息,可以看到Docker Swarm集群的三个节点都连接了ingress这个overlay网络。
$ docker network inspect ingress
[
{
"Name": "ingress",
"Id": "4pluvrq8bgsu5tkhtbze5m43u",
"Created": "2020-03-17T23:26:45.971433101+08:00",
"Scope": "swarm",
"Driver": "overlay",
...
...
...
"Peers": [
{
"Name": "2254bda5c7e4",
"IP": "172.18.20.53"
},
{
"Name": "5164a5c8f987",
"IP": "172.18.20.54"
},
{
"Name": "7abbc0275f86",
"IP": "172.18.20.55"
}
]
}
]
关于docker overlay network这里不作深入探究,它是基于LVS实现的,对网络原理有兴趣的可以自行拓展阅读。
3.Docker Swarm之负载均衡与弹性伸缩
docker service scale
可以控制服务(容器)运行的的实例数。
将实例数增加到2
$ 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
查看服务运行的节点
$ docker service ps whoami
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
qdbs2557cu79 whoami.1 stefanscherer/whoami:latest 172.18.20.55 Running Running 36 minutes ago
opajqayjgryw whoami.2 stefanscherer/whoami:latest 172.18.20.54 Running Running 54 seconds ago
3.1 负载均衡
此时再通过curl请求whoami服务时,可以看到whoami的输出结果为2个whoami实例交替响应。
$ curl http://172.18.20.53:9090
I'm 23031bbc1772 running on linux/amd64
$ curl http://172.18.20.53:9090
I'm 3ce32f72a750 running on linux/amd64
$ curl http://172.18.20.53:9090
I'm 23031bbc1772 running on linux/amd64
$ curl http://172.18.20.53:9090
I'm 3ce32f72a750 running on linux/amd64
这样实际上也就实现了负载均衡效果。
3.2 弹性伸缩
将whoami实例数扩展到5个
$ docker service scale whoami=5
whoami scaled to 5
overall progress: 5 out of 5 tasks
1/5: running [==================================================>]
2/5: running [==================================================>]
3/5: running [==================================================>]
4/5: running [==================================================>]
5/5: running [==================================================>]
verify: Service converged
$ docker service ps whoami
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
qdbs2557cu79 whoami.1 stefanscherer/whoami:latest 172.18.20.55 Running Running 44 minutes ago
opajqayjgryw whoami.2 stefanscherer/whoami:latest 172.18.20.54 Running Running 9 minutes ago
5krem5omr02v whoami.3 stefanscherer/whoami:latest 172.18.20.53 Running Running 50 seconds ago
yx77vjfmhc0j whoami.4 stefanscherer/whoami:latest 172.18.20.53 Running Running 50 seconds ago
xlsgmzyzodl1 whoami.5 stefanscherer/whoami:latest 172.18.20.55 Running Running 15 seconds ago
将whoami实例数缩减到2个
$ 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
$ docker service ps whoami
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
qdbs2557cu79 whoami.1 stefanscherer/whoami:latest 172.18.20.55 Running Running 46 minutes ago
opajqayjgryw whoami.2 stefanscherer/whoami:latest 172.18.20.54 Running Running 11 minutes ago
停止全部的whoami实例
$ docker service scale whoami=0
whoami scaled to 0
overall progress: 0 out of 0 tasks
verify: Service converged
$ docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
9va4qq1p05go whoami replicated 0/0 stefanscherer/whoami:latest *:9090->8080/tcp
$ docker service ps whoami
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
在Docker Swarm中实现扩容和所容,只需要一行命令就能完成,免去了传统方式准备操作系统和运行环境的痛苦。
4.Docker Stack
version: "3.8"
services:
wordpress:
image: wordpress
ports:
- "8080:80"
networks:
- overlay
deploy:
mode: replicated
replicas: 2
endpoint_mode: vip
mysql:
image: mysql
volumes:
- db-data:/var/lib/mysql/data
networks:
- overlay
deploy:
mode: replicated
replicas: 2
endpoint_mode: dnsrr
volumes:
db-data:
networks:
overlay:
https://docs.docker.com/compose/compose-file/#deploy
5.Service更新
docker service update --image
6.展望: CI & CD
Jenkins vs Gitlab CI