第二章 创建Swarm集群, scaling out应用

继续上一章的内容, 为了scale out我们的docker币应用, 产生更多的docker币, 我们要搭建一个docker swarm集群.

2.1 docker1.12 Swarm 模式简介

  1. Docker Engine 1.12 集成了Swarm集群工具.
  2. 主要使用三个新的命令行工具创建一个swarm集群:
  • docker swarm 开启swarm模式; 加入Swarm集群; 配置集群参数
  • docker node 查询集群节点信息; 提升/移除一个管理节点; 管理swarm节点主机
  • docker service 创建管理 service

2.2 创建 Swarm集群

node01上初始化swram集群:

注意 你只需要在一个node上初始化swarm集群, 其他node加入这个集群就行了, 所以一下命令只需要在node01上运行.

1
2
3
4
5
6
7
8
9
10
11
12
[root@node01 dockercoins]# docker swarm init --advertise-addr 192.168.33.101
Swarm initialized: current node (7e2vvnlakrrv2p0omxgl2lflz) is now a manager.

To add a worker to this swarm, run the following command:
docker swarm join \
--token SWMTKN-1-4d8z30svnj6wi8y64ttzirpildro5vego1qrrldepj8auwxa6l-4l4b6o7q1wnjyiwsubkpffkkn \
192.168.33.101:2377

To add a manager to this swarm, run the following command:
docker swarm join \
--token SWMTKN-1-4d8z30svnj6wi8y64ttzirpildro5vego1qrrldepj8auwxa6l-3e8p1ojarz8rdq1rx0ves1a9o \
192.168.33.101:2377

--advertise-addr参数, 后面跟你swarm集群的通讯地址, 也就是node01的地址.
根据如上命令的提示:
我们的其他节点服务器,以worker角色加入swarm集群需要登录到服务器运行如下命令:

1
2
3
docker swarm join \
--token SWMTKN-1-4d8z30svnj6wi8y64ttzirpildro5vego1qrrldepj8auwxa6l-4l4b6o7q1wnjyiwsubkpffkkn \
192.168.33.101:2377

manager角色加入swarm集群:

1
2
3
docker swarm join \
--token SWMTKN-1-4d8z30svnj6wi8y64ttzirpildro5vego1qrrldepj8auwxa6l-3e8p1ojarz8rdq1rx0ves1a9o \
192.168.33.101:2377

检查node01docker swarm mode信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root@node01 dockercoins]# docker info
...
Swarm: active
NodeID: 7e2vvnlakrrv2p0omxgl2lflz
Is Manager: true
ClusterID: 0hhbs9vhvnpovil91d6z87txo
Managers: 1
Nodes: 1
Orchestration:
Task History Retention Limit: 5
Raft:
Snapshot interval: 10000
Heartbeat tick: 1
Election tick: 3
Dispatcher:
Heartbeat period: 5 seconds
CA configuration:
Expiry duration: 3 months
Node Address: 192.168.33.101
...

查看swarm集群node列表

1
2
3
[root@node01 ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
7e2vvnlakrrv2p0omxgl2lflz * node01 Ready Active Leader

可以看到,我们的swarm集群中只有一个节点.现在我们把其他节点加入我们的集群中:
node01通过ssh, 在node02-node05上执行上面的加入集群命令:

1
2
3
4
5
6
[root@node01 ~]# for N in $(seq 2 5); \
do ssh node0$N \
docker swarm join \
--token SWMTKN-1-4d8z30svnj6wi8y64ttzirpildro5vego1qrrldepj8auwxa6l-4l4b6o7q1wnjyiwsubkpffkkn \
192.168.33.101:2377 \
;done


如果你不记得上面提示的加入swarm集群的命令和密钥可以使用如下方式查看worker节点和manager节点的加入命令
1
2
[root@node01 ~]# docker swarm join-token worker
[root@node01 ~]# docker swarm join-token manager

再次检查集群节点列表, 我们可以看到所有的服务器都已经加入swarm集群

1
2
3
4
5
6
7
[root@node01 ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
0frlcbt1xp0kggs64k5ktqrwj node02 Ready Active
6o60ktooinsrej8dcwncq8ibc node04 Ready Active
7e2vvnlakrrv2p0omxgl2lflz * node01 Ready Active Leader
bsak0gszy07gh88tmo7lh5033 node05 Ready Active
cmn6f714no0hn7c4xi9l0xs6h node03 Ready Active

不过现在我们的集群只有一个manager节点node01, 为了swarm集群的高可用,和避免单点故障. 我们希望建立多个manager节点集群.
只需要通过如下命令, 提升node02node03节点成manager节点:

1
2
3
4
5
6
7
8
9
10
11
[root@node01 ~]# docker node promote node02 node03
Node node02 promoted to a manager in the swarm.
Node node03 promoted to a manager in the swarm.
# 查看swarm集群node列表
[root@node01 ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
0frlcbt1xp0kggs64k5ktqrwj node02 Ready Active Reachable
6o60ktooinsrej8dcwncq8ibc node04 Ready Active
7e2vvnlakrrv2p0omxgl2lflz * node01 Ready Active Leader
bsak0gszy07gh88tmo7lh5033 node05 Ready Active
cmn6f714no0hn7c4xi9l0xs6h node03 Ready Active Reachable

现在我们可以看到, 已经有2个manager节点了, 一个Leader节点, 两个Reachable节点. 现在你也可以在node02node03上面管理整个swarm集群.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@node01 ~]# ssh node02 docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
0frlcbt1xp0kggs64k5ktqrwj * node02 Ready Active Reachable
6o60ktooinsrej8dcwncq8ibc node04 Ready Active
7e2vvnlakrrv2p0omxgl2lflz node01 Ready Active Leader
bsak0gszy07gh88tmo7lh5033 node05 Ready Active
cmn6f714no0hn7c4xi9l0xs6h node03 Ready Active Reachable
[root@node01 ~]# ssh node03 docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
0frlcbt1xp0kggs64k5ktqrwj node02 Ready Active Reachable
6o60ktooinsrej8dcwncq8ibc node04 Ready Active
7e2vvnlakrrv2p0omxgl2lflz node01 Ready Active Leader
bsak0gszy07gh88tmo7lh5033 node05 Ready Active
cmn6f714no0hn7c4xi9l0xs6h * node03 Ready Active Reachable

好了到此, 我们的swarm集群就搭建完毕了. 超级简单吧~~

2.3 在Swarm集群上运行service

有了Docker Swarm集群 我们如何把我们的应用跑在Swarm集群上呢?

很简单, 基本上原来我们使用docker run的命令, 把前面替换成docker service create就行了.

使用docker service命令去创建容器服务.例如:
在swarm集群上, 启动一个alpine镜像 ping 8.8.8.8

1
2
[root@node01 ~]# docker service create --name ping-google alpine ping 8.8.8.8
9cyy6xrk2n0welrql49hm3ass

查询 swarm service列表, 我们可以看到刚刚创建的service:

1
2
3
[root@node01 ~]# docker service ls
ID NAME REPLICAS IMAGE COMMAND
9cyy6xrk2n0w ping-google 1/1 alpine ping 8.8.8.8

docker service ps <serviceID>命令可以查看服务到底跑在哪个节点服务器上:

1
2
3
4
[root@node01 ~]# docker service ps ping-google
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR
alxkyacovh4ltiklpccjhf2u5 ping-google.1 alpine node03 Running Running 5 minutes ago
15e8v9q83wu3skrz63ieacbkr \_ ping-google.1 alpine node01 Shutdown Rejected 5 minutes ago "No such image: alpine:latest"

上面的输出我们可以看到service当前跑在node03上, 下面有一条node01上的报错是怎么回事呢? 呵呵, 还是因为docker hub的连接问题, 有时候你可能没法pull到image.
swarm集群会不断帮你重试启动容器,直到成功为止.所以下面的是启动失败的日志.

Scale扩展服务

现在我们的ping-google服务只有一个容器, 注意下面的REPLICAS字段.

1
2
3
[root@node01 ~]# docker service ls
ID NAME REPLICAS IMAGE COMMAND
9cyy6xrk2n0w ping-google 1/1 alpine ping 8.8.8.8

如果我们想Scale服务到10个副本容器, 可以使用docker service scale <serivce ID>=<replicas No>

1
2
3
4
5
[root@node01 ~]# docker service scale ping-google=10
ping-google scaled to 10
[root@node01 ~]# docker service ls
ID NAME REPLICAS IMAGE COMMAND
9cyy6xrk2n0w ping-google 1/10 alpine ping 8.8.8.8

注意REPLICAS现在显示1/10表示这个service一共有10个副本,现在成功运行了1个. 集群正在启动其他的副本.

这这时候查看service进程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[root@node01 ~]# docker service ps ping-google
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR
alxkyacovh4ltiklpccjhf2u5 ping-google.1 alpine node03 Running Running about an hour ago
15e8v9q83wu3skrz63ieacbkr \_ ping-google.1 alpine node01 Shutdown Rejected about an hour ago "No such image: alpine:latest"
2x0abay1gtfdj2kposza0cwbc ping-google.2 alpine node03 Running Running 13 seconds ago
evt8fdlph66e1ih9cayrhz1zg ping-google.3 alpine node05 Ready Preparing 2 seconds ago
b9fciqvr90ruq1h0yoeudm54t \_ ping-google.3 alpine node05 Shutdown Rejected 2 seconds ago "No such image: alpine:latest"
10voxosxigfek1yd29u5o5igk \_ ping-google.3 alpine node05 Shutdown Rejected 14 seconds ago "No such image: alpine:latest"
57urifyyjzyqzjgbo8mpuuj3z ping-google.4 alpine node01 Running Running 8 seconds ago
51ttvahuq54xrs64egx1gk4lx ping-google.5 alpine node01 Running Running 11 seconds ago
288uy2wj5pw3gdu5texm1f9hl \_ ping-google.5 alpine node01 Shutdown Rejected 18 seconds ago "No such image: alpine:latest"
6fphqamttmmwztp43d3a2iz8q ping-google.6 alpine node02 Running Preparing 13 seconds ago
82jd8lipbsc4x1i3msd6kqe0x \_ ping-google.6 alpine node02 Shutdown Rejected 18 seconds ago "No such image: alpine:latest"
3l5kv6zwh5nx4piqd983i39nr ping-google.7 alpine node05 Running Preparing 9 seconds ago
bhvwas8un7xwplo4e0r3vv5z7 \_ ping-google.7 alpine node05 Shutdown Rejected 14 seconds ago "No such image: alpine:latest"
64npet8ftxctdvbfjuqn3b7xs ping-google.8 alpine node02 Running Preparing 11 seconds ago
2ydgrctk17btn1dplrc5z53tl \_ ping-google.8 alpine node02 Shutdown Rejected 16 seconds ago "No such image: alpine:latest"
alqhl7r3nmff0h1mrez9iw348 ping-google.9 alpine node04 Running Preparing 13 seconds ago
7facu0tsaqpxiwqwclpz4ir0n \_ ping-google.9 alpine node04 Shutdown Rejected 18 seconds ago "No such image: alpine:latest"
1mt8ucgdjxsxdozqtwclyp11w ping-google.10 alpine node04 Running Preparing 11 seconds ago
e8om0kbqyn2r91v3oz72kx0tb \_ ping-google.10 alpine node04 Shutdown Rejected 16 seconds ago "No such image: alpine:latest"

-_-!!! 因为docker hub连接不稳定原因,pull image失败 你会看到很多Error. 忽略吧, swram集群会自动重试的.
等所有的副本都启动成功了, 你会看到swarm集群会自动编排10个副本在我们的5台dockerVM上. 每个节点会启动2个容器.

1
2
3
4
[root@node01 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS
b440806604e0 alpine:latest "ping 8.8.8.8" 10 seconds ago Up 8 seconds
6b217e23fee6 alpine:latest "ping 8.8.8.8" 10 seconds ago Up 8 seconds

暴露一个服务端口

跟我们在单机使用docker一样, 你可以将你容器的端口暴露到主机网络中.swarm集群的service端口暴露还有如下特性:

  • 公共的端口会暴露在每一个swarm集群中的节点服务器上.
  • 请求进如公共端口后会负载均衡到所有的sevice实例上.

发布端口的参数跟单机环境一样是-p, 就是把docker run -p替换成docker service create -p.

下面我们创建一个 elasticsearch服务, 发布9200端口:

1
[root@node01 ~]# docker service create --name search --publish 9200:9200 --replicas 7 elasticsearch

使用一下命令监控 service 创建过程:

1
[root@node01 ~]# watch docker service ps search

注意DESIRED STATE列, 一个service副本的创建过程,会经历以下几个状态:

  • accepted 任务已经被分配到某一个节点执行
  • preparing 准备资源, 现在来说一般是从网络拉取image
  • running 副本运行成功
  • shutdown 呃, 报错,被停止了…

当一个任务被终止stoped or killed.., 任务不能被重启, 但是一个替代的任务会被创建.

测试服务端口:

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@node01 ~]# curl localhost:9200
{
"name" : "Rachel Grey",
"cluster_name" : "elasticsearch",
"version" : {
"number" : "2.3.4",
"build_hash" : "e455fd0c13dceca8dbbdbb1665d068ae55dabe3f",
"build_timestamp" : "2016-06-30T11:24:31Z",
"build_snapshot" : false,
"lucene_version" : "5.5.0"
},
"tagline" : "You Know, for Search"
}

反复执行这个命令, 你会看到name会改变, 请求会被分发到不通的service副本.

删除服务

下一章我们要将docker币应用, 跑在swarm集群上,开始之前, 清理我们的service.

你可以使用docker service rm <service ID or Name> 命令删除服务.

删除所有servcie 可以使用如下命令;

1
2
3
[root@node01 ~]# docker service ls -q | xargs docker service rm
4iwtgcfnovd2uzcyp5w57qd0e
bnfutusm7qide08ihurxmucis