我尝试了Docker Swarm模式
起初 (Zuì chū)
因为它使用了Raft分布式共识算法/协议,所以如果有超过3台管理器,它似乎能够成为一个更强大的群集以应对故障,但这次我们不考虑这个。
如果你感兴趣的话,也许可以看看etcd的总选举,或者读一下这篇文章可能会有所帮助。(我受益匪浅)
我非常参考这一篇。
https://docs.docker.com/engine/swarm/
执行环境
将终端1用作node-01的命令执行用途。
$ docker-machine create -d virtualbox node-01
$ eval $(docker-machine env node-01)
将第二个终端用于执行node-02的命令。
$ docker-machine create -d virtualbox node-02
$ eval $(docker-machine env node-02)
初始化
首先,对经理进行初始化。
$ docker swarm init --advertise-addr $(docker-machine ip node-01)
Swarm initialized: current node (61p7kfvmw4m4nbfz3vodgc2y6) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join \
--token SWMTKN-1-0ue65cw4x1k6j2hys2n6hgzpqy0ckv8du7v88e6drkoylh1snm-d7uhyzmofmli2mxa9n93jwepd \
192.168.99.100:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
当执行以上操作时,将会生成带有令牌的命令,用于使工作者参与其中。如果在打算将该命令投射到工作者节点 node-02 上执行,则可以加入集群。
在参加之前,先确认当前群集的状态。
$ docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
61p7kfvmw4m4nbfz3vodgc2y6 * node-01 Ready Active Leader
可以使用以下命令来确认令牌:
$ docker swarm join-token worker
To add a worker to this swarm, run the following command:
docker swarm join \
--token SWMTKN-1-0ue65cw4x1k6j2hys2n6hgzpqy0ckv8du7v88e6drkoylh1snm-d7uhyzmofmli2mxa9n93jwepd \
192.168.99.100:2377
如果要将其作为管理者加入到集群中,请运行 docker swarm join-token manager 命令,即可查看作为管理者加入的令牌。
让节点-02以工作者的身份参与进来。
$ docker swarm join \
--token SWMTKN-1-0ue65cw4x1k6j2hys2n6hgzpqy0ckv8du7v88e6drkoylh1snm-d7uhyzmofmli2mxa9n93jwepd \
192.168.99.100:2377
This node joined a swarm as a worker.
确认集群的状态
$ docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
61p7kfvmw4m4nbfz3vodgc2y6 * node-01 Ready Active Leader
cu9p6rego36d4hhtn2653bacj node-02 Ready Active
顺便提一下,工人方面无法确认状态等。
$ 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.
创建服务
创建Redis服务(尚未确认能否生成Redis集群,请将副本数设置为1以进行调查)
$docker service create --replicas 1 --name redis -p 6379:6379 redis:3.2.0-alpine
7vurzloshshm2wn5vezxuexku
只要不停地点击确认服务,就可以确认REPLICAS变成了1/1。
$ docker service ls
ID NAME REPLICAS IMAGE COMMAND
ac3iz5deljd1 redis 0/1 redis:3.2.0-alpine
$ docker service ls
ID NAME REPLICAS IMAGE COMMAND
ac3iz5deljd1 redis 1/1 redis:3.2.0-alpine
$ docker service ps redis
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR
25g7igyki966vlljtv9lktywx redis.1 redis:3.2.0-alpine node-01 Running Preparing 7 seconds ago
只需要一个选项,以下是对原句的汉语本地化释义:
可以先确认无论从哪个节点都可以进行连接。
顺便在节点1上设置foo为bar,然后在节点2上也确认一下是否能看到。
$ redis-cli -h $(docker-machine ip node-01)
192.168.99.100:6379> set foo bar
OK
192.168.99.100:6379> get foo
"bar"
192.168.99.100:6379> exit
$ redis-cli -h $(docker-machine ip node-02)
192.168.99.101:6379> get foo
"bar"
192.168.99.101:6379> exit
关于服务的扩展、缩小和自动恢复。
要将Redis容器数量增加到2个,需要执行下面的scale命令。
$ docker service scale redis=2
redis scaled to 2
$ docker service ps redis
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR
25g7igyki966vlljtv9lktywx redis.1 redis:3.2.0-alpine node-01 Running Running 27 minutes ago
73f8jbhknsqu2xo4czq3ng7r0 redis.2 redis:3.2.0-alpine node-02 Running Running less than a second ago
$ docker service ls
ID NAME REPLICAS IMAGE COMMAND
ac3iz5deljd1 redis 2/2 redis:3.2.0-alpine
可以简单地扩展上述的容器,但是在自动进行负载均衡时,如果是使用redis等容器的情况,如果不在容器端进行集群化,那么在设置和引用值时可能无法查看。因此,我们将它恢复为一个容器。
$ docker service scale redis=1
redis scaled to 1
$ docker service ps redis
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR
25g7igyki966vlljtv9lktywx redis.1 redis:3.2.0-alpine node-01 Running Running 32 minutes ago
73f8jbhknsqu2xo4czq3ng7r0 redis.2 redis:3.2.0-alpine node-02 Shutdown Shutdown 3 seconds ago
$ docker service ls
ID NAME REPLICAS IMAGE COMMAND
ac3iz5deljd1 redis 1/1 redis:3.2.0-alpine
如果减少上面的复制品数量,容器将不会被删除,而只是停止运行,因此如果尝试多次,将会留下垃圾。
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a18235283c81 redis:3.2.0-alpine "docker-entrypoint.sh" 6 minutes ago Exited (0) About a minute ago redis.2.73f8jbhknsqu2xo4czq3ng7r0
据需要进行验证,被删除的容器似乎是根据其名称中的数字按照从大到小的顺序进行删除,而不是按照时间先后。
增加到大约20个并缩小到一个选项后,结果只剩下 Redis 13 存活下来,看起来很随机。
dcjg438wipqsw6lsi0vw67f5a redis.11 redis:3.2.0-alpine node-01 Shutdown Shutdown about a minute ago
09a4j1fwxb91tkqioz4bti3sz redis.12 redis:3.2.0-alpine node-01 Shutdown Shutdown 3 seconds ago
064hpn2v6jwpy0p8kbpryzwn7 redis.13 redis:3.2.0-alpine node-01 Running Running 3 minutes ago
8lu1d4qwtyb1wz050fjccnbtm redis.14 redis:3.2.0-alpine node-01 Shutdown Shutdown about a minute ago
c9740i08ndi7dte16wsri9ev0 redis.15 redis:3.2.0-alpine node-01 Shutdown Shutdown about a minute ago
099mt2ha487pafhufc37hiutv redis.16 redis:3.2.0-alpine node-02 Shutdown Shutdown 3 seconds ago
如果通过docker stop等命令导致容器进入休眠状态,则会自动执行,使其数量与replicas相同。
我也在考虑是否可以利用这一功能,实现容器的方便替换。
滚动更新
只需进行以下设置即可进行滚动更新。
--update-delay
--update-parallelism
如果每个容器需要等待5秒进行更新,以下是相应的命令。
$ docker service update --update-delay 5s --update-parallelism 1 --image redis:3.2.5-alpine redis
redis
暂时将比例设为20进行试验的结果
840x553ujrfghnbqhqi9s0zx5 redis.7 redis:3.2.5-alpine node-02 Running Running 55 seconds ago
3qoj8jpmcfj1ji20aa2hgx1by \_ redis.7 redis:3.2.0-alpine node-01 Shutdown Shutdown 58 seconds ago
844vrpbzjs29q9kua2b3n9r3p \_ redis.7 redis:3.2.0-alpine node-01 Shutdown Shutdown 17 minutes ago
db6k0he84jv9xp0az3r8sqd4z redis.8 redis:3.2.0-alpine node-01 Running Running 3 minutes ago
31ict01zi3l0spo05a4gjixwi \_ redis.8 redis:3.2.0-alpine node-01 Shutdown Shutdown 16 minutes ago
bssq36i1fq20e5a2a629n83bz redis.9 redis:3.2.0-alpine node-01 Running Running 3 minutes ago
e7sea97hqpd5d1pjaugxb33pv \_ redis.9 redis:3.2.0-alpine node-02 Shutdown Shutdown 17 minutes ago
52e7l8s5ossbq6nndbwfrbxxq redis.10 redis:3.2.5-alpine node-02 Running Running 6 seconds ago
8jozd1yew7vou0g8x458t0t9e \_ redis.10 redis:3.2.0-alpine node-01 Shutdown Shutdown 9 seconds ago
21hlsx81oruek4p8de0ujztxb \_ redis.10 redis:3.2.0-alpine node-01 Shutdown Shutdown 16 minutes ago
03mtra8s2zw2tomwgqsqz4sxa redis.11 redis:3.2.5-alpine node-02 Running Running 25 seconds ago
移除服务
非常棒的服务,一旦删除,将一并删除与其相关的所有容器!
$ docker service rm nginx
nginx
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
总结
太厉害了
总结部分二。
目前的swarm无需准备etcd等后端,这让人感到高兴。尽管可能会有一些麻烦,因为无法通过文件管理节点,但一旦构建完成,就不再需要,所以问题不大。
我是说用像Nginx这样易于扩展的工具来进行尝试。当我想要尝试时,我随意从Docker Hub上选择了它。
赠品
我對REPLICAS進行了一番詳細的描述,但其實還有一個全球模式。(如果我有興趣的話,我會在文章中追加一些資訊。)如果你對此感到好奇,請自行查找相關資料。