浅述 Docker 的容器编排

杰哥的IT之旅

共 12209字,需浏览 25分钟

 ·

2022-05-10 21:41

在下方公众号后台回复:JGNB,可获取杰哥原创的 PDF 手册。

概述

作为容器引擎,Docker为容器化的应用程序提供了开放标准,使得开发者可以用管理应用程序的方式来管理基础架构,实现快速交付、测试和部署代码。随着容器的大量使用,又产生了如何协调、调度和管理容器的问题,Docker的容器编排应运而生。所谓容器编排,通俗一点可以理解为集群管理。

Docker的容器编排工具有很多,最出名的当属Compose、Machine和Swarm,合称Docker三剑客。其中Compose和Machine是第三方的,而Swarm则是Docker官方的容器编排工具,已经被集成在Docker中了。

Swarm由三大部分组成:

  • swarm:集群管理

  • node:节点管理

  • service:服务管理

集群与节点管理

使用 docker swarm 命令,可以创建或加入集群,Docker集群中的节点分为manager和worker两种。这两种节点,都可以运行Docker容器,但只有manager节点,拥有管理功能。

一个集群中,即便只有manager节点也可以正常的工作。

2.1 创建集群

我测试的环境有两台机器,ip地址分别为192.168.1.220和192.168.1.116。下面在192.168.1.220上创建集群:

# docker swarm init
Swarm initialized: current node (ppmurem8j7mdbmgpdhssjh0h9) is now a manager.

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

    docker swarm join --token SWMTKN-1-3e4l8crbt04xlqfxwyw6nuf9gtcwpw72zggtayzy8clyqmvb5h-7o6ww4ftwm38dz7ydbolsz3kd 192.168.1.220:2377

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

执行 docker swarm init 后,集群就被创建好了。当前的机器,自动成为集群的manager节点,并且输出了其他机器加入集群的方式,

即:

docker swarm join --token SWMTKN-1-3e4l8crbt04xlqfxwyw6nuf9gtcwpw72zggtayzy8clyqmvb5h-7o6ww4ftwm38dz7ydbolsz3kd 192.168.1.220:2377。

使用这个token加入的节点,是worker节点,如果想加入一个新的manager节点,可以执行 docker swarm join-token manager,它也会输出一串类似的命令,执行就可以以manager的方式加入。如果忘记加入的命令,也可以使用docker swarm join-token worker 进行查看。

2.2 加入集群

下面在192.168.1.116上执行加入命令:

docker swarm join --token SWMTKN-1-12dlq70adr3z38mlkltc288rdzevtjn73xse7d0qndnjmx45zs-b1kwenzmrsqb4o5nvni5rafcr 192.168.1.220:2377
This node joined a swarm as a worker.

这里发生了一个小插曲,在我创建集群的两台机器的时区不一致,导致在加入worker节点时报错:

Error response from daemon: error while validating Root CA Certificate: x509: certificate has expired or is not yet valid

在更新了220的时区后,依然无法加入。于是,我删除了集群又重新创建,就可以了。没有尝试使用docker swarm update是不是也可以。

加入了集群后,可以在manager节点上,查询集群的节点:

docker node ls
ID                            HOSTNAME                  STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
9b4cmakc4hpc9ra4rruy5x5yo *   localhost.localdomain     Ready     Active         Leader           20.10.3
hz50cnwrbk4vxa7h0g23ccil9     zhangmh-virtual-machine   Ready     Active                          20.10.1

2.3 退出集群

在192.168.1.116上执行下面命令,可以退出集群:

# docker swarm leave                                                                                                           
Node left the swarm.

再次查看节点:

docker node ls
ID                            HOSTNAME                  STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
9b4cmakc4hpc9ra4rruy5x5yo *   localhost.localdomain     Ready     Active         Leader           20.10.3
hz50cnwrbk4vxa7h0g23ccil9     zhangmh-virtual-machine   Down      Active                          20.10.1

发现刚退出的这个节点还在,只是状态变成了Down。需要在manager节点中删除:

docker node rm hz50cnwrbk4vxa7h0g23ccil9
hz50cnwrbk4vxa7h0g23ccil9
docker node ls
ID                            HOSTNAME                  STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
9b4cmakc4hpc9ra4rruy5x5yo *   localhost.localdomain     Ready     Active         Leader           20.10.3
xby86ffkqw3axyfkwd4s7nubz     zhangmh-virtual-machine   Ready     Active                          20.10.1

这样才真正删除了节点。

如果退出的节点是manager节点,需要强制退出,即:docker swarm leave -f。

2.4 将节点提升为 manager 节点

只有一个manager的集群是不稳定的,当manager节点崩溃时,整个集群就群龙无首了。Docker认为,一个集群中应该至少有三个manager节点,并且有一半以上的manager节点是可达的,才能保证集群的正常运行。当集群中只有两个manager节点,且有一个节点出现问题时,整个集群还是处于不可用的状态。

当然,对于我们测试,是没有必要的,我们只需要使用两个manager节点,测试一下是否可以主从切换就可以了。使用下面的命令,可以直接将workder节点提升为manager节点:

docker node promote xby86ffkqw3axyfkwd4s7nubz
Node xby86ffkqw3axyfkwd4s7nubz promoted to a manager in the swarm.
docker node ls
ID                            HOSTNAME                  STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
9b4cmakc4hpc9ra4rruy5x5yo *   localhost.localdomain     Ready     Active         Leader           20.10.3
xby86ffkqw3axyfkwd4s7nubz     zhangmh-virtual-machine   Ready     Active         Reachable        20.10.1

OK,现在有两个manager节点了,192.168.1.220的状态为leader,即当前是领导节点,192.168.1.116的状态为Reachable,是可达的。下面关闭192.168.1.220节点的Docker服务:

# systemctl stop docker
Warning: Stopping docker.service, but it can still be activated by:
  docker.socket

关闭时输出了一个警告,意思是Docker服务已经被关闭了,但它仍然可被docker.socket服务唤醒。再次查看节点状态:

docker node ls
ID                            HOSTNAME                  STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
9b4cmakc4hpc9ra4rruy5x5yo *   localhost.localdomain     Ready     Active         Reachable        20.10.3
xby86ffkqw3axyfkwd4s7nubz     zhangmh-virtual-machine   Ready     Active         Leader           20.10.1

可以看到192.168.1.116已经成为了Leader,并且,192.168.1.220也已经被唤醒。

由此可见,Docker集群的稳定是相当不错的。

服务管理

集群中各节点都配置好后,就可以创建服务了。Docker的服务其实就是启动容器,并且赋予了容器副本和负载均衡的能力。以之前创建的ws:1.0为例,创建5个副本:

# docker service create --replicas 5 --name ws -p 80:8000 ws:1.0
image ws:1.0 could not be accessed on a registry to record
its digest. Each node will access ws:1.0 independently,
possibly leading to different nodes running different
versions of the image.

1nj3o38slbo2zwt5p69l1qi5t
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

服务已经创建并运行了,使用浏览器访问192.168.1.220和192.168.1.116的80端口都可以访问。

使用 docker service ls 命令可以查看ws服务:

# docker service ls
ID             NAME      MODE         REPLICAS   IMAGE     PORTS
1nj3o38slbo2   ws        replicated   5/5        ws:1.0    *:80->8000/tcp

使用 docker service ps ws 命令可查看ws服务的进程:

docker service ps ws
ID             NAME      IMAGE     NODE                      DESIRED STATE   CURRENT STATE           ERROR     PORTS
jpckj0mn24ae   ws.1      ws:1.0    zhangmh-virtual-machine   Running         Running 6 minutes ago             
yrrdn4ntb089   ws.2      ws:1.0    localhost.localdomain     Running         Running 6 minutes ago             
mdjxadbmlmhs   ws.3      ws:1.0    zhangmh-virtual-machine   Running         Running 6 minutes ago             
kqdwfrddbaxd   ws.4      ws:1.0    localhost.localdomain     Running         Running 6 minutes ago             
is2iimz1v4eb   ws.5      ws:1.0    zhangmh-virtual-machine   Running         Running 6 minutes ago 

可以看到有两个进程运行在192.168.1.220上,三个进程运行在192.168.1.116上。我在浏览器上访问了几次之后 ,使用 docker service logs ws 命令查看服务的日志:

# docker service logs ws
ws.5.is2iimz1v4eb@zhangmh-virtual-machine    | [I 210219 01:57:23 web:2239200 GET / (10.0.0.23.56ms
ws.5.is2iimz1v4eb@zhangmh-virtual-machine    | [W 210219 01:57:23 web:2239404 GET /favicon.ico (10.0.0.20.97ms
ws.5.is2iimz1v4eb@zhangmh-virtual-machine    | [I 210219 01:57:28 web:2239200 GET / (10.0.0.40.82ms
ws.5.is2iimz1v4eb@zhangmh-virtual-machine    | [W 210219 01:57:28 web:2239404 GET /favicon.ico (10.0.0.40.79ms
ws.1.jpckj0mn24ae@zhangmh-virtual-machine    | [I 210219 02:01:45 web:2239304 GET / (10.0.0.21.82ms
ws.1.jpckj0mn24ae@zhangmh-virtual-machine    | [I 210219 02:01:59 web:2239304 GET / (10.0.0.20.49ms
ws.1.jpckj0mn24ae@zhangmh-virtual-machine    | [I 210219 02:02:01 web:2239304 GET / (10.0.0.22.05ms
ws.1.jpckj0mn24ae@zhangmh-virtual-machine    | [I 210219 02:02:02 web:2239304 GET / (10.0.0.20.89ms
ws.1.jpckj0mn24ae@zhangmh-virtual-machine    | [I 210219 02:02:02 web:2239304 GET / (10.0.0.21.13ms
ws.1.jpckj0mn24ae@zhangmh-virtual-machine    | [I 210219 02:02:03 web:2239304 GET / (10.0.0.20.92ms
ws.1.jpckj0mn24ae@zhangmh-virtual-machine    | [I 210219 02:02:03 web:2239304 GET / (10.0.0.22.19ms
ws.1.jpckj0mn24ae@zhangmh-virtual-machine    | [I 210219 02:02:20 web:2239304 GET / (10.0.0.21.00ms

可以看到即使我访问的是192.168.1.220,而实际访问的扔然是192.168.1.116上的进程。

如果把192.168.1.116关机,其上运行的进程会自动转移到192.168.1.220的节点中,因为192.168.1.116现在是manager节点,如果停止,集群会进入不可用的状态,所以,需要先将其降级为worker节点:

# docker node demote xby86ffkqw3axyfkwd4s7nubz
Manager xby86ffkqw3axyfkwd4s7nubz demoted in the swarm.

然后,将192.168.1.116关机。

docker service ps ws
ID             NAME       IMAGE     NODE                      DESIRED STATE   CURRENT STATE                ERROR  PORTS
jrj9ben9vr5c   ws.1       ws:1.0    localhost.localdomain     Running         Running 57 minutes ago                         
yrrdn4ntb089   ws.2       ws:1.0    localhost.localdomain     Running         Running about an hour ago                       
opig9zrmp261   ws.3       ws:1.0    localhost.localdomain     Running         Running 57 minutes ago                         
kqdwfrddbaxd   ws.4       ws:1.0    localhost.localdomain     Running         Running about an hour ago
hiz8730pl3je   ws.5       ws:1.0    localhost.localdomain     Running         Running 57 minutes ago                         

可以看到5个进程都转移到192.168.1.220上运行了。

# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED       STATUS       PORTS     NAMES
bc4c457ce769   ws:1.0    "/bin/sh -c 'python …"   3 hours ago   Up 3 hours             ws.5.hiz8730pl3je7qvo2lv6k554b
c846ac1c4d91   ws:1.0    "/bin/sh -c 'python …"   3 hours ago   Up 3 hours             ws.3.opig9zrmp2619t4e1o3ntnj2w
214daa36c138   ws:1.0    "/bin/sh -c 'python …"   3 hours ago   Up 3 hours             ws.1.jrj9ben9vr5c3biuc90xtoffh
17842db9dc47   ws:1.0    "/bin/sh -c 'python …"   3 hours ago   Up 3 hours             ws.4.kqdwfrddbaxd5z78uo3zsy5sd
47185ba9a4fd   ws:1.0    "/bin/sh -c 'python …"   3 hours ago   Up 3 hours             ws.2.yrrdn4ntb089t6i66w8xvq8r9
# docker kill bc4c457ce769
bc4c457ce769

杀死第5个进程后,等待几秒再查看进程:

# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED              STATUS              PORTS     NAMES
416b55e8d174   ws:1.0    "/bin/sh -c 'python …"   About a minute ago   Up About a minute             ws.5.fvpm334t2zqbj5l50tyx5glr6
c846ac1c4d91   ws:1.0    "/bin/sh -c 'python …"   3 hours ago          Up 3 hours                    ws.3.opig9zrmp2619t4e1o3ntnj2w
214daa36c138   ws:1.0    "/bin/sh -c 'python …"   3 hours ago          Up 3 hours                    ws.1.jrj9ben9vr5c3biuc90xtoffh
17842db9dc47   ws:1.0    "/bin/sh -c 'python …"   3 hours ago          Up 3 hours                    ws.4.kqdwfrddbaxd5z78uo3zsy5sd
47185ba9a4fd   ws:1.0    "/bin/sh -c 'python …"   3 hours ago          Up 3 hours                    ws.2.yrrdn4ntb089t6i66w8xvq8r9

第5个进程又被启动。

Docker服务的副本数量是可以动态调整的,比如系统负载过高,需要添加副本时,只需要执行:

# docker service scale ws=6
ws scaled to 6
overall progress: 6 out of 6 tasks 
1/6: running   [==================================================>
2/6: running   [==================================================>
3/6: running   [==================================================>
4/6: running   [==================================================>
5/6: running   [==================================================>
6/6: running   [==================================================>
verify: Service converged

这样,就增加了一个副本。

服务创建好以后,就可以随着Docker的系统服务被启动,只要执行:

systemctl enable docker

刚才创建的集群和服务都会开机启动,不用担心机器重启导致程序运行不正常。

共享数据卷

首先,使用 docker volume create 命令创建一个数据卷:

# docker volume create ws_volume
ws_volume

创建完成后,使用 docker volume ls 命令可查看现有的数据卷:

# docker volume ls
DRIVER    VOLUME NAME
local     ws_volume

使用 docker inspect 命令可查看数据卷的详细信息:

# docker inspect ws_volume
[
    {
        "CreatedAt""2021-02-19T14:09:58+08:00",
        "Driver""local",
        "Labels": {},
        "Mountpoint""/var/lib/docker/volumes/ws_volume/_data",
        "Name""ws_volume",
        "Options": {},
        "Scope""local"
    }
]

在创建service时,可使用 --mount 参数将数据卷挂载到service中:

# docker service create --replicas 2 --name ws -p 80:8000 --mount type=volume,src=ws_volume,dst=/volume ws:1.0
image ws:1.0 could not be accessed on a registry to record
its digest. Each node will access ws:1.0 independently,
possibly leading to different nodes running different
versions of the image.

iiiit9slq9qqwcdwwi0w0mcz5
overall progress: 2 out of 2 tasks 
1/2: running   [==================================================>] 
2/2: running   [==================================================>] 
verify: Service converged 

--mount 有很多的子参数,把它们写成key=value的形式,然后用逗号隔开即可,最简单的,只需要设置type、src、dst三个参数即可。

作者 | 天元浪子

来源 | CSDN博客

推荐阅读

超值一篇分享,Docker:从入门到实战过程全记录


Docker 疑难杂症汇总(二)


Docker 疑难杂症汇总(一)


深入理解 Docker 网络原理


能从入门到精通的 Docker 学习指南


史上讲解最好的 Docker 教程,从入门到精通(建议收藏的教程)

浏览 21
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报