1. Swarm 简介
Docker Swarm 是 Docker 官方推出的容器集群管理工具,基于 Go 语言实现。代码开源在:https://github.com/docker/swarm 使用它可以将多个 Docker 主机封装为单个大型的虚拟 Docker 主机,快速打造一套容器云平台。
Docker Swarm 是生产环境中运行 Docker 应用程序最简单的方法。作为容器集群管理器,Swarm 最大的优势之一就是 100% 支持标准的 Docker API。各种基于标准 API 的工具比如 Compose、docker-py、各种管理软件,甚至 Docker 本身等都可以很容易的与 Swarm 进行集成。大大方便了用户将原先基于单节点的系统移植到 Swarm 上,同时 Swarm 内置了对 Docker 网络插件的支持,用户可以很容易地部署跨主机的容器集群服务。
Docker Swarm 和 Docker Compose 一样,都是 Docker 官方容器编排工具,但不同的是,Docker Compose 是一个在单个服务器或主机上创建多个容器的工具,而 Docker Swarm 则可以在多个服务器或主机上创建容器集群服务,对于微服务的部署,显然 Docker Swarm 会更加适合。
1.1 Swarm 核心概念
1.1.1 Swarm
Docker Engine 1.12 引入了 Swarm 模式,一个 Swarm 由多个 Docker 主机组成,它们以 Swarm 集群模式运行。Swarm 集群由 Manager 节点(管理者角色,管理成员和委托任务)和 Worker 节点(工作者角色,运行 Swarm 服务)组成。这些 Docker 主机有些是 Manager 节点,有些是 Worker 节点,或者同时扮演这两种角色。
Swarm 创建服务时,需要指定要使用的镜像、在运行的容器中执行的命令、定义其副本的数量、可用的网络和数据卷、将服务公开给外部的端口等等。与独立容器相比,群集服务的主要优势之一是,你可以修改服务的配置,包括它所连接的网络和数据卷等,而不需要手动重启服务。还有就是,如果一个 Worker Node 不可用了,Docker 会调度不可用 Node 的 Task 任务到其他 Nodes 上。
1.1.2 Nodes
Swarm 集群由 Manager 节点(管理者角色,管理成员和委托任务)和 Worker 节点(工作者角色,运行 Swarm 服务)组成。一个节点就是 Swarm 集群中的一个实例,也就是一个 Docker 主机。你可以运行一个或多个节点在单台物理机或云服务器上,但是生产环境上,典型的部署方式是:Docker 节点交叉分布式部署在多台物理机或云主机上。节点名称默认为机器的 hostname。
- Manager:负责整个集群的管理工作包括集群配置、服务管理、容器编排等所有跟集群有关的工作,它会选举出一个 leader 来指挥编排任务;
- Worker:工作节点接收和执行从管理节点分派的任务(Tasks)运行在相应的服务(Services)上
1.1.3 Services and Tasks
服务(Service)是一个抽象的概念,是对要在管理节点或工作节点上执行的任务的定义。它是集群系统的中心结构,是用户与集群交互的主要根源。Swarm 创建服务时,可以为服务定义以下信息:
- 服务名称;
- 使用哪个镜像来创建容器;
- 要运行多少个副本;
- 服务的容器要连接到哪个网络上;
- 要映射哪些端口。
将服务部署到 swarm 时,swarm 管理器会接受您的服务定义作为服务的所需状态。然后,它将群中的节点上的服务调度为一个或多个副本任务。这些任务在群中的节点上彼此独立运行。
例如,假设您希望在 HTTP 侦听器的三个实例之间进行负载平衡。下图显示了具有三个副本的 HTTP 侦听器服务。侦听器的三个实例中的每一个都是群中的一个任务。
容器是一个隔离的进程。在群模式模型中,每个任务只调用一个容器。任务类似于调度程序放置容器的“槽”。容器处于活动状态后,计划程序会识别出任务处于运行状态。如果容器未通过运行状况检查或终止,则任务将终止。
任务(Task)包括一个 Docker 容器和在容器中运行的命令。任务是一个集群的最小单元,任务与容器是一对一的关系。管理节点根据服务规模中设置的副本数量将任务分配给工作节点。一旦任务被分配到一个节点,便无法移动到另一个节点。它只能在分配的节点上运行或失败。
1.1.4 Replicated and global services
Swarm 不只是提供了优秀的高可用性,同时也提供了节点的弹性扩容和缩容的功能。可以通过以下两种类型的 Services 部署实现:
- Replicated Services:当服务需要动态扩缩容时,只需通过 scale 参数或者 --replicas n 参数指定运行相同任务的数量,即可复制出新的副本,将一系列复制任务分发至各节点当中,这种操作便称之为副本服务(Replicate)。
- Global Services:我们也可以通过 --mode global 参数将服务分发至全部节点之上,这种操作我们称之为全局服务(Global)。在每个节点上运行一个相同的任务,不需要预先指定任务的数量,每增加一个节点到 Swarm 中,协调器就会创建一个任务,然后调度器把任务分配给新节点。
下图用黄色表示拥有三个副本服务 Replicated Service,用灰色表示拥有一个全局服务 Global Service。
1.1.5 Swarm 工作流程
Swarm Manager:
- API:接受命令并创建 service 对象(创建对象)
- orchestrator:为 service 对象创建的 task 进行编排工作(服务编排)
- allocater:为各个 task 分配 IP 地址(分配 IP)
- dispatcher:将 task 分发到 nodes(分发任务)
- scheduler:安排一个 worker 节点运行 task(运行任务)
Worker Node:
- worker:连接到调度器,检查分配的 task(检查任务)
- executor:执行分配给 worker 节点的 task(执行任务)
1.1.6 Swarm 默认的网络问题
网络概述|Docker 文档 暂时不了解,留个疑问。
2. Docker Swarm 环境搭建
2.1 环境准备
- 五台安装了 Docker 的 CentOS 机器或者虚拟机
- Docker Engine 1.12+(最低要求 1.12,本文使用 20.10.14)
- 防火墙开启固定的端口或者关闭防火墙:
Linux云服务器怎样关闭防火墙、添加例外端口
2.2 机器分布
角色 | IP | HOSTNAME | Docker版本 |
Manager | 192.168.117.128 | manager1 | 20.10.14 |
Manager | 192.168.117.129 | manager2 | 20.10.14 |
Manager | 192.168.117.130 | manager3 | 20.10.14 |
Worker | 192.168.117.131 | worker1 | 20.10.14 |
Worker | 192.168.117.132 | worker2 | 20.10.14 |
- 可以通过 hostname 主机名
- 或者 hostnamectl set-hostname 主机名
- 或者 vi /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 manager1
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
注意:
基于 Raft 协议:保证大多数节点存活才可以用。只要 > 1 ,集群至少大于3台。
我们现在是 3主2从,如果是 2主2从 当一个 Manager 节点 down 机,那么另外一个主节点也不能用了。感兴趣可以试验一下。
例如:1.1.2 中的示例图。
2.3 创建集群
当您运行命令以创建群时,Docker 引擎将开始在群模式下运行。
运行 docker swarm init
- 将当前节点切换到群模式。
- 创建一个名为 的群。default
- 将当前节点指定为群的领导者管理器节点。
- 使用计算机主机名命名节点。
- 将管理中心配置为侦听端口 2377 上的活动网络接口。
- 将当前节点设置为可用性,这意味着它可以从计划程序接收任务。Active
- 为参与群的引擎启动内部分布式数据存储,以保持群和在其上运行的所有服务的一致视图。
- 默认情况下,为群生成自签名根 CA。
- 默认情况下, 为工作节点和管理器节点生成令牌以加入 swarm。
- 创建一个覆盖网络,该网络名为发布群外部的服务端口。ingress
- 为网络创建覆盖默认 IP 地址和子网掩码
在任意节点下通过 docker swarm init 命令创建一个新的 Swarm 集群并加入,且该节点会默认成为 Manager 节点。根据我们预先定义的角色,在 128 - 131 的任意一台机器上运行该命令即可。
通常,第一个加入集群的管理节点将成为 Leader ,后来加入的管理节点都是 Reachable 。当前的 Leader 如果挂掉,所有的 Reachable 将重新选举一个新的 Leader。
# --help
[root@CentOS7 ~]# 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 # 创建或者叫获取一个新的 token
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 集群
[root@CentOS7 ~]# docker swarm init
Swarm initialized: current node (zka7r9aes22mnxu91r8x8qedz) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-4tu4iappu58z1xhjg4me3fm1loeucz9udccm2npoh6qqd0re84-9bmhyx62gjoulqeftgtnsg6tf 192.168.117.128:2377 # 通过该命令添加一个工作节点
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions. # 添加 管理节点
# 初始化后查看网络
[root@CentOS7 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
7759facf2bb6 bridge bridge local
767f114c1d6a host host local
m1w3aqqlbz1d ingress overlay swarm # 新增的 swarm 网络
239984d23cb5 none null local
2.4 加入集群
介绍
Docker 中内置的群模式公钥基础结构 (PKI) 系统使安全部署容器编排系统变得简单。群中的节点使用相互传输层安全性 (TLS) 对与群中其他节点的通信进行身份验证、授权和加密。
当您通过运行来创建一个群时,Docker 将自己指定为管理器节点。缺省情况下,管理器节点会生成一个新的根证书颁发机构 (CA) 以及一个密钥对,用于保护与加入该群的其他节点的通信。如果您愿意,可以使用 docker swarm init 命令的标志指定自己的外部生成的根 CA。
管理器节点还会生成两个令牌,以便在将其他节点加入 swarm 时使用:一个工作线程令牌和一个管理器令牌。每个令牌都包含根 CA 证书的摘要和随机生成的机密。当节点加入群时,加入节点将使用摘要来验证来自远程管理器的根 CA 证书。远程管理器使用密钥来确保加入节点是已批准的节点。
每次新节点加入群时,管理器都会向该节点颁发证书。证书包含随机生成的节点 ID,用于标识证书公用名 (CN) 下的节点和组织单位 (OU) 下的角色。节点 ID 用作当前群中节点生存期内的加密安全节点标识。
下图说明了管理器节点和工作节点如何使用最低 TLS 1.2 加密通信。
2.4.1 Manager 管理节点
若要向该集群添加 Manager 节点,管理节点先运行 docker swarm jointoken manager 命令查看管理节点的令牌信息。
这个命令在我们 init 初始化的时候已经提供给我们了
# 查看管理节点的令牌信息
[root@CentOS7 ~]# docker swarm join-token manager
To add a manager to this swarm, run the following command:
docker swarm join --token SWMTKN-1-5aq4qwdyuif24reg3d8oew19v6fi323c96do95wd4k7uaqjv35-0vsf7n6xmsuo8wjo4ba12e5gi 192.168.117.128:2377
# 然后在 02、03 节点上运行 docker swarm join 并携带令牌参数加入 Swarm 集群,该节点角色为 Manager。如下图:
[root@centos7-02 ~]# docker swarm join --token SWMTKN-1-5aq4qwdyuif24reg3d8oew19v6fi323c96do95wd4k7uaqjv35-0vsf7n
This node joined a swarm as a manager.
[root@CentOS7-03 ~]# docker swarm join --token SWMTKN-1-5aq4qwdyuif24reg3d8oew19v6fi323c96do95wd4k7uaqjv35-0vsf7n
This node joined a swarm as a manager.
2.4.2 Worker 工作节点
通过创建集群时返回的结果可以得知,要向这个集群添加一个 Worker 节点,运行下图中的命令即可。或者管理节点先运行 docker swarm join-token worker
# 查看工作节点的令牌信息
[root@CentOS7 ~]# docker swarm join-token worker
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-5aq4qwdyuif24reg3d8oew19v6fi323c96do95wd4k7uaqjv35-bie9myc2oxapy108itqt6n1xe 192.168.117.128:2377
# 然后在 04、05 节点上运行 docker swarm join 并携带令牌参数加入 Swarm 集群,该节点角色为 Worker。如下图:
[root@CentOS7-04 ~]# docker swarm join --token SWMTKN-1-5aq4qwdyuif24reg3d8oew19v6fi323c96do95wd4k7uaqjv35-bie9myc2oxapy108itqt6n1xe 192.168.117.128:2377
This node joined a swarm as a worker.
[root@CentOS7-05 ~]# docker swarm join --token SWMTKN-1-5aq4qwdyuif24reg3d8oew19v6fi323c96do95wd4k7uaqjv35-bie9myc2oxapy108itqt6n1xe 192.168.117.128:2377
This node joined a swarm as a worker.
2.5 查看集群信息
在任意 Manager 节点中运行 docker info 可以查看当前集群的信息。
2.6 查看集群节点
在任意 Manager 节点中运行 docker node ls 可以查看当前集群节点信息。
*
代表当前节点 现在的环境为 3 个管理节点构成 1 主 2 从,以及 2 个工作节点。
节点 MANAGER STATUS 说明:表示节点是属于 Manager 还是 Worker,没有值则属于 Worker 节点。
- Leader :该节点是管理节点中的主节点,负责该集群的集群管理和编排决策;
- Reachable :该节点是管理节点中的从节点,如果 Leader 节点不可用,该节点有资格被选为新的 Leader;
- Unavailable :该管理节点已不能与其他管理节点通信。如果管理节点不可用,应该将新的管理节点加入群集,或者将工作节点升级为管理节点。
节点 AVAILABILITY 说明:表示调度程序是否可以将任务分配给该节点。
- Active :调度程序可以将任务分配给该节点;
- Pause :调度程序不会将新任务分配给该节点,但现有任务仍可以运行;
- Drain :调度程序不会将新任务分配给该节点,并且会关闭该节点所有现有任务,并将它们调度在可用的节点上。
2.7 删除节点
删除节点之前需要先将该节点的 AVAILABILITY 改为 Drain 。其目的是为了将该节点的服务迁移到其他可用节点上,确保服务正常。最好检查一下容器迁移情况,确保这一步已经处理完成再继续往下。
# 1. 将该节点的 AVAILABILITY 改为 Drain
docker node update --availability drain 节点名称|节点ID
# 2. 将该 Manager 节点进行降级处理,降级为 Worker 节点。
docker node demote 节点名称|节点ID
# 3. 在已经降级为 Worker 的节点中运行以下命令,离开集群。
docker swarm leave
# 4. 在管理节点中对刚才离开的节点进行删除。
docker node rm 节点名称|节点ID
删除节点,Manager 和 Worker 不同的地方是 Manager 需要做一个降级处理。例如:步骤2。
# 或者我们查看 docker swarm leave --help 命令
[root@CentOS7 ~]# docker swarm leave --help
Usage: docker swarm leave [OPTIONS]
Leave the swarm
Options:
-f, --force Force this node to leave the swarm, ignoring warnings
# 可以看到 leave 有一个 -f 的参数,可以通过该参数:强制此节点离开群,忽略警告,然后执行删除命令 删除节点
docker swarm leave -f
其他命令也可以通过 --help 来了解详细的用法
3. 服务部署
注意:跟集群管理有关的任何操作,都是在 Manager 节点上操作的。
首先 docker service --help 查看一下关于 service 命令
[root@CentOS7 ~]# docker service --help
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.
3.1 创建服务
可以通过 docker sercice create --help 自行查看具体的 create 命令参数。
下面这个案例,使用 nginx 镜像创建了一个名为 mynginx 的服务,该服务会被随机指派给一个工作节点运行。
[root@CentOS7 ~]# docker service create --replicas 1 --name my-nginx -p 80:80 nginx
rmytesrvv0ojbred5qm2j5rv6
overall progress: 1 out of 1 tasks
1/1: running [==================================================>]
verify: Service converged
[root@CentOS7 ~]#
- docker service create
- --replicas
- --name
3.2 查看服务
可以通过 docker service ls
[root@CentOS7 ~]# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
rmytesrvv0oj my-nginx replicated 1/1 nginx:latest *:80->80/tcp
可以通过 docker service inspect 服务名称|服务ID
可以通过 docker service ps 服务名称|服务ID
[root@CentOS7 ~]# docker service ps rmytesrvv0oj
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
zdmv65r877h3 my-nginx.1 nginx:latest CentOS7-04 Running Running 4 minutes ago
在对应的任务节点上运行 docker ps
[root@CentOS7-04 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2cf69a4432e9 nginx:latest "/docker-entrypoint.…" 4 minutes ago Up 4 minutes 80/tcp my-nginx.1.zdmv65r877h3t0hgrlqkug1pe
3.3 调用服务
接下来测试一下服务是否能被正常访问,并且该集群下任意节点的 IP 地址都要能访问到该服务才行。
3.4 弹性服务
将 service 部署到集群以后,可以通过命令弹性扩缩容 service 中的容器数量。在 service 中运行的容器被称为 task(任务)。
通过 docker service scale 服务名称|服务ID=n
通过 docker service update --replicas n 服务名称|服务ID
将 mynginx service 运行的任务扩展为 5 个:
[root@CentOS7 ~]# docker service scale my-nginx=5
my-nginx 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
通过 docker service ps 服务名称|服务ID 查看服务运行在哪些节点上。
我们再来一波缩容的操作,命令如下:
[root@CentOS7 ~]# docker service update --replicas 3 my-nginx
my-nginx
overall progress: 3 out of 3 tasks
1/3: running [==================================================>]
2/3: running [==================================================>]
3/3: running [==================================================>]
verify: Service converged
通过 docker service ps 服务名称|服务ID 查看服务运行在哪些节点上。
在 Swarm 集群模式下真正意义实现了所谓的弹性服务,动态扩缩容一行命令搞定,简单、便捷、强大。
3.5 删除服务
通过 docker service rm 服务名称|服务ID
[root@CentOS7 ~]# docker service rm my-nginx
my-nginx
[root@CentOS7 ~]# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
4. 滚动更新及回滚
通过以下案例演示 Redis 版本如何滚动升级至更高版本再回滚至上一次的操作。
4.1 创建5个 Redis 服务副本,版本为5
创建 5 个副本,每次更新 2 个,更新间隔 10s,20% 任务失败继续执行,超出 20% 执行回滚,每次回滚 2 个 详细命令如下:
[root@centos7-02 ~]# docker service create --replicas 5 --name redis \
> --update-delay 10s \
> --update-parallelism 2 \
> --update-failure-action continue \
> --rollback-monitor 20s \
> --rollback-parallelism 2 \
> --rollback-max-failure-ratio 0.2 \
> redis:5
- --update-delay
- --update-parallelism
- --update-failure-action
- --rollback-monitor
- --rollback-parallelism
- --rollback-max-failure-ratio
如下图:
4.2 滚动更新
然后通过以下命令实现服务的滚动更新。
docker service update --image redis:6 redis
4.3 回滚服务
回滚服务,只能回滚到上一次操作的状态,并不能连续回滚到指定操作。
docker service update --rollback redis
5. 常用命令
5.1 docker swarm
命令 | 说明 |
docker swarm init | 初始化集群 |
docker swarm join-token worker | 查看工作节点的 token |
docker swarm join-token manager | 查看管理节点的 token |
docker swarm join | 加入集群 |
5.2 docker node
命令 | 说明 |
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 | 更新节点 |
5.3 docker service
命令 | 说明 |
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 update 服务名称 / 服务ID | 更新服务 |