完整教程:42.Docker Swarm 核心内容整理
文章目录
Docker Swarm

一、Docker Swarm 中重要的概念
1. 集群化(Clustering)
定义:服务器集群由一组网络上相互连接的服务器组成,协同工作,能像单个系统那样运行,同时提供高可用、负载均衡和并行处理能力。
集群与独立服务器的区别:
独立服务器部署应用:资源整体利用率难达最优,无法灵活应对资源使用波动,服务器宕机需手工迁移应用,缺乏业务弹性。
集群部署应用:无需关注单个服务器,只需考虑应用所需的内存、CPU 等资源,由集群管理程序(如 Docker Swarm)分配部署;通过添加 / 删除主机节点调整集群整体容量,集群始终保持整体属性。
后续操作:将创建 Docker Swarm 集群、部署应用、伸缩扩展应用及执行滚动升级。
二、Docker Swarm Mode
版本里程碑:Docker v1.12 是重要版本,重新实现集群编排方式。此前,Docker Swarm 是单独软件,依赖外部数据库(如 Consul、etcd、Zookeeper);从 v1.12 开始,Docker Swarm 功能完全与 Docker Engine 集成,启动 Swarm Mode 即可管理集群,无需额外安装外部数据库,服务发现功能内置。
与 Kubernetes 对比:创建集群简单,无需额外安装软件和配置,适合作为学习容器编排引擎的起点。
三、重要概念
1. swarm
定义:由运行 Docker Engine 的多个主机组成的集群。
模式启动:从 v1.12 开始,集群管理和编排功能集成进 Docker Engine;当 Docker Engine 初始化 swarm 或加入已存在的 swarm 时,启动 swarm mode。
功能差异:未启动 swarm mode 时,Docker 执行容器命令;启动 swarm mode 后,Docker 新增编排 service 的能力,且允许同一 Docker 主机同时运行 swarm service 和单独容器。
2. node
定义:swarm 中的每个 Docker Engine 都是一个 node,分为两种类型:manager(管理节点)和 worker(工作节点)。
角色职责:
manager node:执行部署命令,将部署任务拆解分配给 worker node;负责编排和集群管理,维护 swarm 期望状态;多个 manager node 会自动协商选举 leader 执行编排任务。默认配置下,manager node 同时也是 worker node,可配置为 manager-only node,专职负责编排和集群管理。
worker node:接受并执行 manager node 派发的任务;定期向 manager node 报告自身状态和执行任务的状态,便于 manager 维护集群状态。
3. service
定义:定义 worker node 上要执行的任务,swarm 的主要编排任务是保证 service 处于期望状态。
示例:在 swarm 中启动 http 服务,使用 httpd:latest 镜像,副本数为 3。manager node 创建该 service 后,分析需启动 3 个 httpd 容器,根据各 worker node 状态分配任务(如 worker1 运行 2 个、worker2 运行 1 个);若 worker2 宕机,manager 会立即在 worker3 上启动新的 httpd 容器,确保 service 保持 3 个副本的期望状态。
四、部署 swarm 集群
1. 集群节点规划
| 节点名称 | IP 地址 | 节点类型 |
|---|---|---|
| swarm-manager | 192.168.108.30 | manager node |
| swarm-worker1 | 192.168.108.31 | worker node |
| swarm-worker2 | 192.168.108.32 | worker node |
- 环境准备:通过 docker 教案中安装的 docker 虚拟机,完整克隆出上述三个节点,修改 IP 地址与主机名;所有节点 Docker 版本不低于 v1.12,实验环境节点操作系统为 centos-stream-8(其他 Linux 系统也可)。
2. 初始化 manager node(在 swarm-manager 上操作)
[root@swarm-manager ~]# docker swarm init --advertise-addr 192.168.108.30
initialid crrent node puyqojjavzuajzyo) is now a manager
To add a worker to this swarm, run the following command:
docker swarm join --token SMTKN-1-5it8t4f2tbrmxuhahkwp7i4jzh7q14135tkjotbilnebztrzw-mvlgmv1inatgmlhp11739ncy 192.168.108.30:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions
参数说明:
--advertise-addr指定与其他 node 通信的地址。输出解读:
swarm 创建成功,swarm-manager 成为 manager node。
提供添加 worker node 需执行的命令。
提示添加 manager node 需执行的命令(运行
docker swarm join-token manager查看详情)。

3. 查看当前 swarm 节点(在 swarm-manager 上操作)
[root@swarm-manager ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
bpuyqqwojwjz9avzuaeyjszyo * swarm-manager Ready Active Leader 26.1.3
- 此时仅显示 swarm-manager 一个 manager node。
4. 添加 worker node(在 swarm-worker1 和 swarm-worker2 上操作)
(1)设置防火墙 zone
三个节点均执行以下命令,将防火墙 zone 设置为 trust:
[root@swarm-manager ~]# firewall-cmd --set-default-zone=trusted
[root@swarm-worker1 ~]# firewall-cmd --set-default-zone=trusted
[root@swarm-worker2 ~]# firewall-cmd --set-default-zone=trusted
#也可以防火墙放行2377端口
`firewall-cmd --add-port=2377/tcp`
(2)加入 swarm 集群
在 swarm-worker1 和 swarm-worker2 上分别执行初始化 manager node 时输出的docker swarm join命令:
# swarm-worker1上执行
[root@swarm-worker1 ~]# docker swarm join --token SWMTKN-1-5it8t4f2tbrmxuhahkwp7i4jzhq7q14l35tkjotbiln0bztrzw-bmwlgmv1inatgm1hpl1739ncy 192.168.108.30:2377
This node joined a swarm as a worker.
# swarm-worker2上执行
[root@swarm-worker2 ~]# docker swarm join --token SWMTKN-1-5it8t4f2tbrmxuhahkwp7i4jzhq7q14l35tkjotbiln0bztrzw-bmwlgmv1inatgm1hpl1739ncy 192.168.108.30:2377
This node joined a swarm as a worker.
5. 验证 worker node 添加结果(在 swarm-manager 上操作)
[root@swarm-manager ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
bpuyqqwojwjz9avzuaeyjszyo * swarm-manager Ready Active Leader 26.1.3
mdudczt56hzbaw7aum3smrula swarm-worker2 Ready Active 26.1.3
s3o9n5wkkbiyc21ehmk3xecvk swarm-worker1 Ready Active 26.1.3
- 可看到两个 worker node 已成功添加到 swarm 集群。
6. 查看添加 worker node 的命令(在 manager node 上操作)
若未记录初始化时的docker swarm join命令,可通过以下命令查看:
[root@swarm-manager ~]# docker swarm join-token worker
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-5it8t4f2tbrmxuhahkwp7i4jzhq7q14l35tkjotbiln0bztrzw-bmwlgmv1inatgm1hpl1739ncy 192.168.108.30:2377
- 注:该命令仅能在 manager node 上执行。
五、运行第一个 Service
1. 部署 service(在 swarm-manager 上操作)
部署运行 httpd 镜像的 service,命令如下:
[root@swarm-manager ~]# docker service create --name web_server httpd
1ntzbsmbu3q3d4f969gpu0a8c
overall progress: 1 out of 1 tasks
1/1: running [ >]
verify: Service 1ntzbsmbu3q3d4f969gpu0a8c converged
- 命令说明:
--name为 service 命名,httpd为使用的镜像名,命令形式与docker run类似。
2. 查看 swarm 中的 service(在 swarm-manager 上操作)
[root@swarm-manager ~]# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
1ntzbsmbu3q3 web_server replicated 1/1 httpd:latest
- 解读:
REPLICAS显示副本信息,1/1表示 web_server service 期望的容器副本数量为 1,当前已启动的副本数量为 1,即 service 部署完成。
3. 查看 service 副本状态(在 swarm-manager 上操作)
[root@swarm-manager ~]# docker service ps web_server
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
lfwcnkg6pgth web_server.1 httpd:latest swarm-worker2 Running Running 56 seconds ago
- 结果:service 唯一的副本被分派到 swarm-worker2,当前状态(CURRENT STATE)为 Running,达到期望状态(DESIRED STATE)。
4. 在 worker node 上验证容器运行状态(在 swarm-worker2 上操作)
[root@swarm-worker2 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bef3b50af9ea httpd:latest "httpd-foreground" 2 minutes ago Up 2 minutes 80/tcp web_server.1.lfwcnkg6pgthdkqno2pu4w8n3
- 可看到 httpd 容器已在 swarm-worker2 上成功运行。

六、如何实现 Service 伸缩?
1. 扩展副本数
(1)增加副本数(在 swarm-manager 上操作)
将 web_server service 的副本数增加到 5,命令如下:
[root@swarm-manager ~]# docker service scale web_server=5
web_server 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 web_server converged
(2)查看扩展后的 service 信息(在 swarm-manager 上操作)
# 查看service基本信息
[root@swarm-manager ~]# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
1ntzbsmbu3q3 web_server replicated 5/5 httpd:latest
# 查看副本详细分布
[root@swarm-manager ~]# docker service ps web_server
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
lfwcnkg6pgth web_server.1 httpd:latest swarm-worker2 Running Running 4 minutes ago
q4006zahgaqm web_server.2 httpd:latest swarm-worker1 Running Running 53 seconds ago
ug6dgvoycg91 web_server.3 httpd:latest swarm-worker2 Running Running about a minute ago
324xfyww2awh web_server.4 httpd:latest swarm-manager Running Running about a minute ago
v4btzz1lr69q web_server.5 httpd:latest swarm-worker1 Running Running 53 seconds ago
- 结果:5 个副本分布在 swarm 的三个节点上(默认 manager node 也是 worker node,故 swarm-manager 上也运行了副本)。

2. 配置 manager node 不运行 service
(1)修改 manager node 可用性(在 swarm-manager 上操作)
[root@swarm-manager ~]# docker node update --availability drain swarm-manager
swarm-manager
(2)查看节点状态变化(在 swarm-manager 上操作)
[root@swarm-manager ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
bpuyqqwojwjz9avzuaeyjszyo * swarm-manager Ready Drain Leader 26.1.3
s3o9n5wkkbiyc21ehmk3xecvk swarm-worker1 Ready Active 26.1.3
mdudczt56hzbaw7aum3smrula swarm-worker2 Ready Active 26.1.3
- 解读:
Availability变为Drain,表示 swarm-manager 不再负责运行 service。
(3)查看副本调整结果(在 swarm-manager 上操作)
[root@swarm-manager ~]# docker service ps web_server
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
lfwcnkg6pgth web_server.1 httpd:latest swarm-worker2 Running Running 8 minutes ago
q4006zahgaqm web_server.2 httpd:latest swarm-worker1 Running Running 4 minutes ago
ug6dgvoycg91 web_server.3 httpd:latest swarm-worker2 Running Running 4 minutes ago
732oh5htny76 web_server.4 httpd:latest swarm-worker2 Running Running 49 seconds ago
324xfyww2awh _web_server.4 httpd:latest swarm-manager Shutdown Shutdown 50 seconds ago
v4btzz1lr69q web_server.5 httpd:latest swarm-worker1 Running Running 4 minutes ago
- 结果:swarm-manager 上的副本 web_server.4 已 Shutdown,为保持 5 个副本数,在 swarm-worker2 上新增了副本 web_server.4。

3. 缩减副本数
(1)减少副本数(在 swarm-manager 上操作)
将 web_server service 的副本数减少到 3,命令如下:
[root@swarm-manager ~]# docker service scale web_server=3
web_server scaled to 3
overall progress: 3 out of 3 tasks
1/3:
2/3: running [==================================================]
3/3: running [==================================================>]
verify: Service web_server converged
(2)查看缩减后的 service 信息(在 swarm-manager 上操作)
# 查看service基本信息
[root@swarm-manager ~]# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
1ntzbsmbu3q3 web_server replicated 3/3 httpd:latest
# 查看副本详细状态
[root@swarm-manager ~]# docker service ps web_server
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
lfwcnkg6pgth web_server.1 httpd:latest swarm-worker2 Running Running 10 minutes ago
q4006zahgaqm web_server.2 httpd:latest swarm-worker1 Running Running 6 minutes ago
ug6dgvoycg91 web_server.3 httpd:latest swarm-worker2 Running Running 7 minutes ago
324xfyww2awh web_server.4 httpd:latest swarm-manager Shutdown Shutdown 2 minutes ago
- 结果:web_server.4 和 web_server.5 两个副本已被删除,仅保留 3 个副本。

七、Swarm 如何实现 Failover?
1. Failover 原理
Swarm 内置 Failover 策略,创建 service 时无需额外配置故障处理规则,只需指定期望状态(如副本数),Swarm 会尽力维持该期望状态,应对容器崩溃、Docker Host 宕机等故障。
2. 故障测试(以 3 个副本的 web_server service 为例)
(1)初始副本分布
3 个副本分布在 swarm-worker1 和 swarm-worker2 上(swarm-manager 已配置为 Drain,不运行 service)。
(2)模拟节点故障(关闭 swarm-worker1)
[root@swarm-worker1 ~]# shutdown now
(3)查看节点状态变化(在 swarm-manager 上操作)
[root@swarm-manager ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
bpuyqqwojwjz9avzuaeyjszyo * swarm-manager Ready Drain Leader 26.1.3
s3o9n5wkkbiyc21ehmk3xecvk swarm-worker1 Down Active 26.1.3
mdudczt56hzbaw7aum3smrula swarm-worker2 Ready Active 26.1.3
- 结果:swarm-worker1 被标记为
Down。
(4)查看副本 Failover 结果(在 swarm-manager 上操作)
[root@swarm-manager ~]# docker service ps web_server
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
lfwcnkg6pgth web_server.1 httpd:latest swarm-worker2 Running Running 41 minutes ago
gx95mteiiaq1 web_server.2 httpd:latest swarm-worker2 Running Running about a minute ago
q4006zahgaqm _web_server.2 httpd:latest swarm-worker1 Shutdown Shutdown 37 minutes ago
ug6dgvoycg91 web_server.3 httpd:latest swarm-worker2 Running Running 38 minutes ago
324xfyww2awh web_server.4 httpd:latest swarm-manager Shutdown Shutdown 34 minutes ago
- 结果:原运行在 swarm-worker1 上的 web_server.2 副本已 Shutdown,Swarm 在 swarm-worker2 上重新启动了 web_server.2 副本,维持 3 个副本的期望状态。(不是将容纳迁移,而是重新生成)
将swarm-worker2 开机后,副本分配没有发生变化

八、如何访问 Service?
1. 重新部署 web_server service(在 swarm-manager 上操作)
(1)删除原有 service
[root@swarm-manager ~]# docker service rm web_server
web_server
(2)创建新 service(指定 2 个副本)
[root@swarm-manager ~]# docker service create --name web_server --replicas=2 httpd
izro3jrl6e09czc0iz08q9p44
overall progress: 2 out of 2 tasks
1/2: running [
2/2: running [ >]
verify: Service izro3jrl6e09czc0iz08q9p44 converged
(3)查看副本分布(在 swarm-manager 上操作)
[root@swarm-manager ~]# docker service ps web_server
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
9zve246nlqed web_server.1 httpd:latest swarm-worker1 Running Running 12 seconds ago
yvker0qkyfe2 web_server.2 httpd:latest swarm-worker2 Running Running 13 seconds ago
- 结果:每个 worker node 上各运行 1 个副本。
2. 容器层面的访问(仅 Docker 主机内部可访问)
(1)查看容器网络配置(在 swarm-worker1 上操作)
# 查看容器ID
[root@swarm-worker1 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
22973a0645e2 httpd:latest "httpd-foreground" About a minute ago Up About a minute 80/tcp web_server.1.9zve246nlqedn272fgtddepok
# 查看容器IP
[root@swarm-worker1 ~]# docker inspect web_server.1.9zve246nlqedn272fgtddepok
[
{
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"MacAddress": "02:42:ac:11:00:02",
"NetworkID": "325e2b265f380ba7278c32b3a6a0def045452e684b23eae5341b494d864a262a",
"EndpointID": "8e3002fa399c0b412ae04a12481d9824db22bc0c54e6c2bd7b5c47e6705d5344",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2"
}
}
}
]
- 结果:容器 IP 为 172.17.0.2,连接 Docker 默认 bridge 网络,监听 80 端口,但未映射到 Docker Host。
(2)在 Docker 主机上访问容器服务(在 swarm-worker1 上操作)
[root@swarm-worker1 ~]# curl 172.17.0.2
<html><body><h1>It works!</h1></body></html>
- 注:该访问方式仅局限于 Docker 主机内部,外部网络无法访问。
3. 从外部访问 service
(1)更新 service,添加端口映射(在 swarm-manager 上操作)
[root@swarm-manager ~]# docker service update --publish-add 8080:80 web_server
web_server
overall progress: 2 out of 2 tasks
1/2: running [ >]
2/2: running [
verify: Service web_server converged
- 命令说明:
--publish-add 8080:80将容器的 80 端口映射到主机的 8080 端口,使外部网络可访问 service。
(2)新建 service 时直接指定端口映射(在 swarm-manager 上操作)
[root@swarm-manager ~]# docker service create --name web_server --publish 8080:80 --replicas=2 httpd
(3)验证外部访问(在任意可访问集群节点的机器上操作)
[root@swarm-manager ~]# curl http://192.168.108.30:8080
<html><body><h1>It works!</h1></body></html>
[root@swarm-manager ~]# curl http://192.168.108.31:8080
<html><body><h1>It works!</h1></body></html>
[root@swarm-manager ~]# curl http://192.168.108.32:8080
<html><body><h1>It works!</h1></body></html>
- 结果:访问集群中任意节点的 8080 端口,均可成功访问 web_server service,该功能由 routing mesh 实现。
九、神奇的 routing mesh
1. routing mesh 作用
当外部请求访问 swarm 集群中任意节点的映射端口(如 8080)时,swarm 内部的负载均衡器会将请求转发给 service 的任意一个副本,实现外部网络对 service 的访问,即使请求的节点上未运行 service 副本。

2. 外部负载均衡器配置(以 HAProxy 为例)
可配置外部负载均衡器(如 HAProxy),将请求路由到 swarm service,例如将 HAProxy 的请求分发到集群各节点的 8080 端口,架构如下:
HAProxy(http://192.168.108.100)
|
├─> swarm-manager(192.168.108.30:8080)
├─> swarm-worker1(192.168.108.31:8080)
└─> swarm-worker2(192.168.108.32:8080)

3. swarm 中的关键网络
(1)网络查看(在任意节点上操作)
[root@swarm-worker1 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
325e2b265f38 bridge bridge local
06615073d3f0 docker_gwbridge bridge local
77d2734d1c55 host host local
t2ie77rl777k ingress overlay swarm
a0663936827d none null local
(2)核心网络说明
ingress 网络:swarm 创建时 Docker 自动创建,基于 overlay 驱动,作用是让运行在不同主机上的容器相互通信,每个 swarm node 均可使用。
docker_gwbridge 网络:作用是让容器能够访问到外网。
(3)添加端口映射后的容器网络变化
添加--publish-add 8080:80后,swarm 会重新配置 service,原副本会 Shutdown 并启动新副本,新副本会使用 ingress 网络(而非默认 bridge 网络),示例如下:
# 查看新副本的网络配置(在swarm-worker1上操作)
[root@swarm-worker1 ~]# docker inspect web_server.1.lwfdj841ph0glbrwwjucmckex
[
{
"Networks": {
"ingress": {
"IPAMConfig": {
"IPv4Address": "10.0.0.15"
}
}
}
}
]
- 原理:通过 overlay 网络实现主机与容器、容器与容器之间的通信,结合 routing mesh 将外部请求路由到不同主机的容器,最终实现外部网络对 service 的访问。
浙公网安备 33010602011771号