使用DockerSwarm管理容器

image-20200114150517739

我们在之前的学习都是操作一台主机上的一个或者多个容器,但是在实际场景中可能一个服务需要多台主机,多个容器,那这时候怎么办呢?

我们可以通过一套容器编排系统区解决。 Swarm Mode 并不是唯一可以做容器编排的工具

Swarm是内置在Docker中的

image-20200114150656018

上面是Docker Swarm的结构设计,Docker Swarm是一种集群的架构,里面有各种节点,节点的角色分为ManagerWorker

Manager节点是整个Docker Swarm集群的大脑,至少有两个。

当存在多个Manger的时候就需要涉及到同步(通过一个Manager做的事情如何同步到另一个Manager上?)同步使用到了一个内置的分布式存储的数据库,这个数据库是通过Raft协议进行同步。Raft协议能够确保Manager节点之间的信息数据是对称的,同步的,防止脑裂情况发生。

Worker节点实际上就是干活的节点,大部分容器部署到集群中都会运行在Worker节点上。(Manager也是可以运行干活的,但是大部分还是运行在Worker上,因为Worker的节点比较多一点)Worker节点之间通过Gossip network进行信息同步。

image-20200114150717603

docker swarm中,service的概念和docker compose中的service概念是差不多的。一个service其实就代表了一个容器。

replicas是在service的基础上做横向扩展,例如,一个nginxswevice中有三个nginx的容器,其中每一个容器就可以理解为一个replica

swarm中通过manager节点去部署一个service的时候,我们事先是不知道这个service最终会运行在哪些swarmcluster节点上的,swarmscheduler会根据一定的调度算法去计算(比如会根据每台cluster节点的资源使用率等),将容器调度在相应的节点上。

任务 (Task)Swarm 中的最小的调度单位,目前来说就是一个单一的容器。

服务 (Services) 是指一组任务的集合,服务定义了任务的属性。

服务有两种模式:

  1. replicated services 按照一定规则在各个工作节点上运行指定个数的任务。

  2. global services 强制在每个 node 上都运行一个且最多一个容器。

image-20200114150757539

上图是Docker Swarm创建Service的调度过程。

我们在Swarm Manager做决策,最终结果要把Service部署到哪个Node上面,然后执行实际操作。

创建一个三节点的Swarm的集群

我们使用play-with-docker创建三台主机

image-20200114150819741

我们将192.168.0.48这台作为Manager其他两台作为Worker

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
[node1] (local) root@192.168.0.48 ~ 

$ docker swarm --help

Usage: docker swarm COMMAND

Manage Swarm

Commands:

ca Display and rotate the root CA

init Initialize a swarm

join Join a swarm as a node and/or manager

join-token Manage join tokens

leave Leave the swarm

unlock Unlock swarm

unlock-key Manage the unlock key

update Update the swarm

Run 'docker swarm COMMAND --help' for more information on a command.

查看初始化Swarm的参数

1
2
3
4
5
6
7
8
9
10
11
12
13
[node1] (local) root@192.168.0.48 ~ 

$ docker swarm init --help

Usage: docker swarm init [OPTIONS]

Initialize a swarm

Options:

--advertise-addr string Advertised address (format: <ip|interface>[:port])

--task-history-limit int Task history retention limit (default 5)

初始化的时候 通过advertise-addr来宣告本地地址的存在

初始化创建一个Swarm集群

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[node1] (local) root@192.168.0.48 ~ 

$ docker swarm init --advertise-addr=192.168.0.48

Swarm initialized: current node (tmcx3ft8twi83tigoxqcflbgm) is now a manager.

\# 让其他节点作为 `worker` 加入这个 `swarm`

To add a worker to this swarm, run the following command:

docker swarm join --token SWMTKN-1-5uhqepdgt0gh34j0uoleu5yfv6hbtik1mz9oiqustpghthj2w1-2ifimume7kw26kq3sldj6hy07 192.1

68.0.48:2377

\# 如我我们想让加入的节点作为 `manager `加入这个 `swarm` 可以执行 然后执行下面输出的命令

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

我们执行这个命令,来启用 swarm,我们当前主机作为管理节点

它还创建了 swarm 根证书,还创建了 join token,用来让其他节点加入这个 Swarm

还创建了 raft 数据库。

我们在剩下的两台机子上执行加入集群的命令

1
2
3
4
5
[node2] (local) root@192.168.0.47 ~ 

$ docker swarm join --token SWMTKN-1-5uhqepdgt0gh34j0uoleu5yfv6hbtik1mz9oiqustpghthj2w1-2ifimume7kw26kq3sldj6hy07 192.168.0.48:2377

This node joined a swarm as a worker.
1
2
3
4
5
6
7
[node3] (local) root@192.168.0.46 ~ 

$ docker swarm join --token SWMTKN-1-5uhqepdgt0gh34j0uoleu5yfv6hbtik1mz9oiqustpghthj2w1-2ifimume7kw26kq3sldj6hy07 192.168

.0.48:2377

This node joined a swarm as a worker.

\

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

\```powershell

查看当前集群的节点有哪些`docker node ls`

```powershell
[node1] (local) root@192.168.0.48 ~

$ docker node ls

ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERS

ION

tmcx3ft8twi83tigoxqcflbgm * node1 Ready Active Leader 19.03.4

ffv6izyiia3zrvtdg6n4efaz5 node2 Ready Active 19.03.4

hvz2ylt57ann8uvad0un2001f node3 Ready Active 19.03.4

Service的创建维护和水平扩展

创建service

创建Service类似单机创建Docker,但是具体Service是部署到哪个节点是不一定的。

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
[node1] (local) root@192.168.0.48 ~ 

$ docker service

Usage: docker service COMMAND

Manage services

Commands:

create Create a new service

inspect Display detailed information on one or more services

logs Fetch the logs of a service or task

ls List services

ps List the tasks of one or more services

rm Remove one or more services

rollback Revert changes to a service's configuration

scale Scale one or multiple replicated services

update Update a service

Run 'docker service COMMAND --help' for more information on a command.
1
2
3
4
5
6
7
8
9
$ docker service create 

"docker service create" requires at least 1 argument.

See 'docker service create --help'.

Usage: docker service create [OPTIONS] IMAGE [COMMAND] [ARG...]

Create a new service

创建一个demoService

1
2
3
4
5
6
7
8
9
10
11
[node1] (local) root@192.168.0.48 ~ 

$ docker service create --name demo busybox sh -c "while true;do sleep 3600;done"

msjj914g1xozqsui460k6i2m8

overall progress: 1 out of 1 tasks

1/1: running [==================================================>]

verify: Service converged

查看已有的service使用docker service ls

1
2
3
4
5
6
7
[node1] (local) root@192.168.0.48 ~ 

$ docker service ls

ID NAME MODE REPLICAS IMAGE PORTS

msjj914g1xoz demo replicated 1/1 busybox:latest

通过上面的信息我们不知道demo这个服务的容器运行在哪一台服务器上,但是,可以通过docker service ps service_name来查看:

1
2
3
4
5
6
7
8
9
[node1] (local) root@192.168.0.48 ~ 

$ docker service ps demo

ID NAME IMAGE NODE DESIRED STATE CURRENT STATE

ERROR PORTS

mcewsjl5ekuw demo.1 busybox:latest node1 Running Running 3 minutes ago

可以发现,demo这个service运行在node1这个管理节点上。

这里的MODEreplicated表示是可以水平扩展的

node1节点上通过`docker ps查看:

1
2
3
4
5
6
7
8
9
10
11
[node1] (local) root@192.168.0.48 ~ 

$ docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS

NAMES

a0172318fd26 busybox:latest "sh -c 'while true;d…" 4 minutes ago Up 4 minutes

demo.1.mcewsjl5ekuwzr07sbveix3iy

service 扩展

我们看到有一个容器,名字为demo.1.mcewsjl5ekuwzr07sbveix3iy

我们通过之前的demo这个service可以看到有一个REPLICAS显示的是1/1,这就说明demo这个service是可以横向扩展的,service的扩展类似于docker compose。也是通过参数scale来实现:

1
2
3
4
5
6
7
8
9
10
11
[node1] (local) root@192.168.0.48 ~ 

$ docker service scale

"docker service scale" requires at least 1 argument.

See 'docker service scale --help'.

Usage: docker service scale SERVICE=REPLICAS [SERVICE=REPLICAS...]

Scale one or multiple replicated services

进行扩展

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[node1] (local) root@192.168.0.48 ~ 

$ docker service scale demo=5

demo 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

查看demo服务

1
2
3
4
5
6
7
[node1] (local) root@192.168.0.48 ~ 

$ docker service ls

ID NAME MODE REPLICAS IMAGE PORTS

msjj914g1xoz demo replicated 5/5 busybox:latest

可以发现REPLICAS已经由1/1变成了5/5

分母的5表示scale是5,分子是指多少是准别就绪的

再次查看这5个容器分别运行在哪些节点之上:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[node1] (local) root@192.168.0.48 ~ 

$ docker service ps demo

ID NAME IMAGE NODE DESIRED STATE CURRENT STATE

ERROR PORTS

mcewsjl5ekuw demo.1 busybox:latest node1 Running Running 12 minutes ag

o

obbts01y3k0s demo.2 busybox:latest node2 Running Running 2 minutes ago

uyqnj0q2521a demo.3 busybox:latest node3 Running Running 2 minutes ago

m9qdf13h41zq demo.4 busybox:latest node3 Running Running 2 minutes ago

s1iofxqhr3pi demo.5 busybox:latest node1 Running Running 2 minutes ago

我们看到容器变成了5个,并且是平均分配到各个节点上。

通过docker swarm scale创建的横向扩展(比如scale demo=5),那么,无论在哪个节点上强制删除其中一个或者多个该service的容器(dockerd服务必须在运行),docker swarm scale都会自动在当前的集群中的其他容器重新启动相应个数的容器,保持scale指定的数量。这样就可以确保系统稳定,不会出现业务停止的情况。

在一个Worker节点上删除一个容器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[node2] (local) root@192.168.0.47 ~ 

$ docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

25d9430caea0 busybox:latest "sh -c 'while true;d…" 37 seconds ago Up 31 seconds demo.4.xmp8xwcc9p2rg4m1f3d98mw1o

07065d04234b busybox:latest "sh -c 'while true;d…" 6 minutes ago Up 6 minutes demo.2.obbts01y3k0sz1i86p8e4yh53

[node2] (local) root@192.168.0.47 ~

$ docker rm -f 25d9430caea0

25d9430caea0

Manager节点上面查看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[node1] (local) root@192.168.0.48 ~ 

$ docker service ls

ID NAME MODE REPLICAS IMAGE PORTS

msjj914g1xoz demo replicated 4/5 busybox:latest

[node1] (local) root@192.168.0.48 ~

$ docker service ls

ID NAME MODE REPLICAS IMAGE PORTS

msjj914g1xoz demo replicated 5/5 busybox:latest

我们看到会先变成4/5然后重新变为5/5

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[node1] (local) root@192.168.0.48 ~ 

$ docker service ps demo

ID NAME IMAGE NODE DESIRED STATE CURRENT STATE

ERROR PORTS

mcewsjl5ekuw demo.1 busybox:latest node1 Running Running 19 minutes ag

o

obbts01y3k0s demo.2 busybox:latest node2 Running Running 9 minutes ago

uyqnj0q2521a demo.3 busybox:latest node3 Running Running 9 minutes ago

m6kp0rhjihof demo.4 busybox:latest node2 Running Running 2 minutes ago

xmp8xwcc9p2r \_ demo.4 busybox:latest node2 Shutdown Failed 3 minutes ago

"task: non-zero exit (137)"

s1iofxqhr3pi demo.5 busybox:latest node1 Running Running 9 minutes ago

删除service

删除一个service只需要通过docker service rm service_name即可,在删除service之后,docker swarm会自动从当前swarm集群中删除该服务之前运行的所有容器(有一定的延时):

1
2
3
4
5
6
7
8
9
10
11
[node1] (local) root@192.168.0.48 ~ 

$ docker service rm demo

demo

[node1] (local) root@192.168.0.48 ~

$ docker service ps demo

no such service: demo

参考文章:

Docker Swarm 零基础入门

知识就是财富
如果您觉得文章对您有帮助, 欢迎请我喝杯水!