本文主要演示如何通过swarm构建一个集群环境,以及服务的弹性部署。
Docker Swarm 和 Docker Compose 一样,都是 Docker 官方容器编排工具,但不同的是,Docker Compose 是一个在单个服务器或主机上创建多个容器的工具,而 Docker Swarm 则可以在多个服务器或主机上创建容器集群服务,对于微服务的部署,显然 Docker Swarm 会更加适合。
Swarm 由多个 Docker 主机组成,它们以 Swarm 集群模式运行,主要包含 Manager 节点(管理者角色,管理成员和委托任务)和 Worker 节点(工作者角色,运行 Swarm 服务)。这些 Docker 主机有些是 Manager 节点,有些是 Worker 节点,或者同时扮演这两种角色。
Swarm 集群由 Manager 节点(管理者角色,管理成员和委托任务)和 Worker 节点(工作者角色,运行 Swarm 服务)组成,每个节点对应着 Swarm 集群中的一个实例。在生产环境进行部署时,会将节点交叉分布式部署在多台物理机或云主机上,而每个节点的名称默认为机器的 hostname。
服务(Service)是一个抽象的概念,是对集群环境中同一类型的任务的集合的统称,是集群系统的中心结构。Swarm 创建服务时,可以为服务定义以下信息等:
任务(Task)包括一个 Docker 容器和在容器中运行的命令,是一个集群的最小单元。
任务与容器是一对一的关系。管理节点根据服务规模中设置的副本数量将任务分配给工作节点。一旦任务被分配到一个节点,便无法移动到另一个节点。它只能在分配的节点上运行或失败。
Swarm 不只是提供了优秀的高可用性,同时也提供了节点的弹性扩容和缩容的功能。可以通过以下两种类型的 Services 部署实现:
scale
参数或者 --replicas n
参数指定运行相同任务的数量,即可复制出新的副本,将一系列复制任务分发至各节点当中,这种操作便称之为副本服务(Replicate)。--mode global
参数将服务分发至全部节点之上,这种操作我们称之为全局服务(Global)。在每个节点上运行一个相同的任务,不需要预先指定任务的数量,每增加一个节点到 Swarm 中,协调器就会创建一个任务,然后调度器把任务分配给新节点。下图用黄色表示拥有三个副本服务 Replicated Service,用灰色表示拥有一个全局服务 Global Service。
Swarm Manager:
Worker Node:
主要搭建由一个manager和两个worker构成的集群环境
docker 版本1.12以上
防火墙开启以下端口或者关闭防火墙:
角色 | IP | HOSTNAME | |
---|---|---|---|
Manager | 192.168.174.159 | docker1 | |
Worker | 192.168.174.162 | worker1 | |
Worker | 192.168.174.163 | worker2 |
由于每个节点名默认为主机名hostname,因此,这里需要修改每台虚拟机的主机名,修改方式如下:
- 可以通过
hostname 主机名
修改机器的主机名(立即生效,重启后失效);- 或者
hostnamectl set-hostname 主机名
修改机器的主机名(立即生效,重启也生效);- 或者
vi /etc/hosts
编辑 hosts 文件,给 127.0.0.1 添加主机名(重启生效)。
在192.168.174.159机器上执行docker swarm init指令,初始化一个新的swarm集群,该节点会默认初始化为一个manager节点。
通常,第一个加入集群的管理节点将成为Leader,后来加入的管理节点都是Reachable。当前的Leader如果挂掉,所有的Reachable将重新选举一个新的Leader。
[root@docker01 ~]# docker swarm init --advertise-addr=192.168.174.159
Swarm initialized: current node (ntc6ylh1tbw5m17w19ptswfo8) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-2bzts7ixfjma7fg4d81etljp0i7tls299975t6x7xq2wgn5wph-82jgyj6xv4h4cuqnv3vujbmew 192.168.174.159:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
这里可以看到,我们以159节点为leader建立了一个swarm集群,且仅存在159一个manager节点
Docker 中内置的集群模式自带了公钥基础设施(PKI)系统,使得安全部署容器变得简单。集群中的节点使用传输层安全协议(TLS)对集群中其他节点的通信进行身份验证、授权和加密。
Manager 节点会生成两个令牌,供其他节点加入集群时使用:一个 Worker 令牌,一个 Manager 令牌。每个令牌都包括根 CA 证书的摘要和随机生成的密钥。当节点加入群集时,加入的节点使用摘要来验证来自远程管理节点的根 CA 证书。远程管理节点使用密钥来确保加入的节点是批准的节点。
Manager
若要向该集群添加 Manager 节点,管理节点先运行 docker swarm join-token manager
命令查看管理节点的令牌信息。
由于机器原因,只提供了一台机器作为manager节点,因此,不做演示,只需按照上述方式,获取加入manager集群的token令牌,然后在需要加入的机器上执行上述指令,即可作为从节点加入到manager集群中
Worker
在初始化集群后,在其返回的结果中,会提供如何加入worker节点的指令,用户只需在对应机器上执行上述指令即可。
或者,通过docker swarm join-token worker来获取相应的token令牌。
紧接着,在worker1和worker2节点上分比执行上述命令
通过docker info可以看到每个节点的docker相关信息(服务、网络、镜像等)和swarm集群信息等
docker node ls
可以在manager节点通过上述指令查看集群环境下各个节点的信息
Manager status解析
表示节点是属于 Manager 还是 Worker,没有值则属于 Worker 节点。
Leader
:该节点是管理节点中的主节点,负责该集群的集群管理和编排决策;Reachable
:该节点是管理节点中的从节点,如果 Leader 节点不可用,该节点有资格被选为新的 Leader;Unavailable
:该管理节点已不能与其他管理节点通信。如果管理节点不可用,应该将新的管理节点加入群集,或者将工作节点升级为管理节点。Availability解析
表示调度程序是否可以将任务分配给该节点。
Active
:调度程序可以将任务分配给该节点;Pause
:调度程序不会将新任务分配给该节点,但现有任务仍可以运行;Drain
:调度程序不会将新任务分配给该节点,并且会关闭该节点所有现有任务,并将它们调度在可用的节点上。Manager
删除节点之前需要先将该节点的 AVAILABILITY
改为 Drain
。其目的是为了将该节点的服务迁移到其他可用节点上,确保服务正常。
docker node update --availability drain 节点名称|节点ID
然后,将该 Manager 节点进行降级处理,降级为 Worker 节点。
docker node demote 节点名称|节点ID
由于我们这里只创建了一个manager节点,如果降级为worker节点的话,就没有manager节点了,会导致swarm集群不可用,因此,执行上述命令时,会抛出以下异常
然后,在已经降级为 Worker 的节点中运行以下命令,离开集群。(在移除worker节点中演示执行过程)
docker swarm leave
最后,在管理节点中对刚才离开的节点进行删除。
docker node rm 节点名称|节点ID
Worker
同理,worker节点也需要将Availability改为Drain
docker node update --availability drain 节点名称|节点ID
需要注意在manager节点上才能进行管理功能,否则就会出现以下报错
然后,在已经降级为 Worker 的节点中运行以下命令,离开集群。(需切换到worker节点)
docker swarm leave
最后,在管理节点中对刚才离开的节点进行删除。(需切换到manager节点)
docker node rm 节点名称|节点ID
至此,swarm集群的基础操作就完成了,接下来介绍如何在当前集群中部署服务
注意:跟集群管理有关的任何操作,都是在 Manager 节点上操作的。
注意事项:该操作均只能在manager节点执行
接下来,我们创建一个nginx的服务,改服务会由manager随机分配到某个集群的节点上进行部署启动
docker service create --replicas 1 --name mynginx -p 80:80 nginx
可以通过docker service ls查看运行的服务。
可以通过 docker service inspect 服务名称|服务id 查看服务详细信息
可以通过docker service ps 服务名|服务id 查看服务运行在哪些节点上。
在对应的任务节点上运行docker ps 可以查看该服务对应容器的相关信息。
接下来我们测试一下服务是否能被正常访问,并且该集群下任意节点的 IP 地址都要能访问到该服务才行。
有关集群下为何任意节点都能访问该服务请参见:
https://blog.csdn.net/weixin_43762303/article/details/123618916
注意事项:该操作均只能在manager节点执行
将 service 部署到集群以后,可以通过命令弹性扩缩容 service 中的容器数量。在 service 中运行的容器被称为 task(任务)。
通过 docker service scale 服务名称|服务ID=n
可以将 service 运行的任务扩缩容为 n 个。
通过 docker service update --replicas n 服务名称|服务ID
也可以达到扩缩容的效果。
接下来,演示一波缩容的操作
注意事项:该操作均只能在manager节点执行
通过docker service rm 服务名|服务id即可删除服务。(需在manager节点上执行)
注意事项:该操作均只能在manager节点执行
这里我们已redis版本更迭,以及版本回滚为例,来讲解服务的滚动更新以及回滚
首先,创建一个单个实例的redis服务
#docker service create --name 服务名 --replicas 1 -p :
[root@docker01 ~]# docker service create --name myredis --replicas 1 -p 6379:6379 redis:latest
dfhac6ddsvdpet3l2g5qvmp3z
overall progress: 1 out of 1 tasks
1/1: running [==================================================>]
verify: Service converged
然后,扩容服务实例数到两个
#扩容服务个数
#docker service update --replicas 2 服务名
#docker service scale 服务名|服务id=2
[root@docker01 ~]# docker service update --replicas 2 myredis
myredis
overall progress: 2 out of 2 tasks
1/2: running [==================================================>]
2/2: running [==================================================>]
verify: Service converged
查看服务部署详情
[root@docker01 ~]# docker service ps myredis
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
6oh52ojs6iml myredis.1 redis:latest worker1 Running Running about a minute ago
inldebtlhvw6 myredis.2 redis:latest worker2 Running Running 15 seconds ago
接下来,我们将redis服务版本由latest更新到6
#滚动更新服务使用镜像
#docker service update --image 镜像名:版本 服务名
[root@docker01 ~]# docker service update --image redis:6 myredis
myredis
overall progress: 2 out of 2 tasks
1/2: running [==================================================>]
2/2: running [==================================================>]
verify: Service converged
这里我们可以看到部署的redis服务版本已经更新到6
[root@docker01 ~]# docker service ps myredis
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
ktz1dpmgx9t4 myredis.1 redis:6 worker1 Running Running 2 minutes ago
6oh52ojs6iml \_ myredis.1 redis:latest worker1 Shutdown Shutdown 2 minutes ago
b33btvotf83w myredis.2 redis:6 worker2 Running Running 2 minutes ago
inldebtlhvw6 \_ myredis.2 redis:latest worker2 Shutdown Shutdown 2 minutes ago
此时,我们再讲解如何进行服务的回滚
注意:回滚仅能回滚至最近一次的操作,无法连续回滚到指定操作(回滚两次只会取消当前的回滚操作)
#服务回滚(仅能回滚到最近一次的操作,无法连续回滚)
#方法一:docker service rollback
命令 | 说明 |
---|---|
docker swarm init | 初始化集群 |
docker swarm join-token worker | 查看工作节点的 token |
docker swarm join-token manager | 查看管理节点的 token |
docker swarm join | 加入集群 |
命令 | 说明 |
---|---|
docker node ls | 查看集群所有节点 |
docker node ps | 查看当前节点所有任务 |
docker node rm 节点名称|节点ID | 删除节点(-f 强制删除) |
docker node inspect 节点名称|节点ID | 查看节点详情 |
docker node demote 节点名称|节点ID | 节点降级,由管理节点降级为工作节点 |
docker node promote 节点名称|节点ID | 节点升级,由工作节点升级为管理节点 |
docker node update 节点名称|节点ID | 更新节点 |
命令 | 说明 |
---|---|
docker service create | 创建服务 |
docker service ls | 查看所有服务 |
docker service inspect 服务名称|服务ID | 查看服务详情 |
docker service logs 服务名称|服务ID | 查看服务日志 |
docker service rm 服务名称|服务ID | 删除服务(-f 强制删除) |
docker service scale 服务名称|服务ID=n | 设置服务数量 |
docker service rollback 服务名称|服务ID | 服务回滚 |
docker service update 服务名称|服务ID | 更新服务,其中可以支持包含扩缩容,回滚,滚动更新等等功能 详细请通过docker service update --help查看 |