使用 Docker Swarm 部署高可用(High Availability, HA)集群的核心在于多 Manager 节点架构、Raft 共识算法以及服务的副本调度。Swarm 模式是 Docker 原生的集群管理工具,配置简单且无需额外组件。
以下是构建高可用 Docker Swarm 集群的完整指南:
一、高可用架构设计原则
在开始之前,必须理解高可用的关键要素:
- Swarm 使用 Raft 协议 维护集群状态。
- 需要 3、5 或 7 个 Manager 节点。
- 容错能力:N 个 Manager 节点允许 floor((N-1)/2) 个节点故障。
- 推荐:生产环境至少部署 3 个 Manager(允许 1 个故障)或 5 个 Manager(允许 2 个故障)。
- 负责运行容器任务。
- 数量不限,建议根据负载水平扩展。
- 利用 Swarm 的 Ingress 网络 和 DNS Round Robin 实现服务发现。
- 外部流量通常通过负载均衡器(如 Nginx, HAProxy, AWS ALB)分发到所有 Manager 和 Worker 的 2377 (集群通信) 和 80/443 (服务端口)。
二、环境准备
假设我们有 5 台服务器(3 Manager + 2 Worker):
- Manager 1: 192.168.1.10 (Leader)
- Manager 2: 192.168.1.11
- Manager 3: 192.168.1.12
- Worker 1: 192.168.1.20
- Worker 2: 192.168.1.21
前置条件:
- 所有节点已安装 Docker Engine。
- 节点间网络互通(开放 2377, 7946, 4789 端口)。
- 主机名解析正常(或配置 /etc/hosts)。
三、初始化集群(高可用模式)
1. 初始化第一个 Manager
在 Manager 1 上执行:
docker swarm init \\
–advertise-addr 192.168.1.10 \\
–listen-addr 192.168.1.10:2377
- –advertise-addr: 其他节点连接此 IP。
- 输出会包含加入 Worker 和 Manager 的命令。
2. 添加其他 Manager 节点(关键步骤)
不要使用 Worker 命令,必须使用 –manager-addr 或 –token 中的 manager 命令。
在 Manager 2 和 Manager 3 上分别执行(使用 Manager 1 输出的 token):
# 在 Manager 2 上
docker swarm join \\
–token <MANAGER_TOKEN> \\
–advertise-addr 192.168.1.11 \\
192.168.1.10:2377
# 在 Manager 3 上
docker swarm join \\
–token <MANAGER_TOKEN> \\
–advertise-addr 192.168.1.12 \\
192.168.1.10:2377
注意:–advertise-addr 必须填写当前节点自己的 IP,以便其他节点能联系到它。
3. 添加 Worker 节点
在 Worker 1 和 Worker 2 上执行(使用 Worker token):
docker swarm join \\
–token <WORKER_TOKEN> \\
192.168.1.10:2377
4. 验证集群状态
在任意 Manager 节点执行:
docker node ls
预期输出:
- 3 个节点状态为 Ready 且 Role 为 Manager。
- 2 个节点状态为 Ready 且 Role 为 Worker。
- 其中一个 Manager 标记为 * (Leader)。
四、部署高可用服务
高可用不仅依赖集群,还依赖服务副本(Replicas)和调度策略。
1. 部署多副本服务
创建一个 Nginx 服务,运行 3 个副本,分布在不同的节点上:
docker service create \\
–name web-frontend \\
–replicas 3 \\
–publish 80:80 \\
–constraint 'node.role == worker' \\
nginx:alpine
- –replicas 3: 确保始终有 3 个实例运行。
- –constraint: 强制调度到 Worker 节点(可选,避免占用 Manager 资源)。
2. 实现故障转移(自愈)
- 节点故障:如果 Worker 1 宕机,Swarm 会自动在 Worker 2 或其他可用节点上重新启动一个新的 Nginx 容器。
- 容器故障:如果某个容器崩溃,Swarm 会立即重启它。
3. 全局模式(Global Mode)
如果你希望每个节点都运行一个实例(如日志收集器):
docker service create \\
–name logger \\
–mode global \\
fluent/fluentd
五、外部负载均衡配置
Swarm 的 –publish 模式(Ingress 路由)会在所有节点上监听端口,并通过 IPVS 进行负载均衡。但为了生产环境的高可用,通常需要在集群前部署一个外部负载均衡器。
方案 A:使用云厂商负载均衡器 (推荐)
- 配置负载均衡器监听 80/443。
- 后端服务器组添加所有 Manager 和 Worker 的 IP。
- 健康检查指向容器端口。
- 优点:自动处理节点故障,无需手动配置。
方案 B:自建 Nginx/HAProxy 负载均衡
在集群外部署一个 Nginx,配置 upstream:
upstream docker_swarm {
server 192.168.1.10:80;
server 192.168.1.11:80;
server 192.168.1.12:80;
server 192.168.1.20:80;
server 192.168.1.21:80;
least_conn; # 使用最少连接算法
}
server {
listen 80;
location / {
proxy_pass http://docker_swarm;
}
}
六、高可用维护与灾难恢复
1. 升级 Manager 节点(滚动更新)
不要一次性升级所有 Manager。
# 升级 Manager 2
docker node update –role manager <node_id> # 如果它是 worker
# 实际上,升级 Docker 版本通常直接操作节点
# 1. 将节点标记为 Drain (停止新任务)
docker node update –availability drain <node_id>
# 2. 等待任务迁移
docker node ps <node_id> # 确认无任务
# 3. 升级 Docker 软件
# 4. 恢复节点
docker node update –availability active <node_id>
2. 备份 Raft 日志 (关键!)
Swarm 的集群状态存储在 Manager 节点的 Raft 日志中。定期备份至关重要。
# 在 Manager 节点执行
docker run –rm \\
-v /var/lib/docker/swraft:/var/lib/docker/swarm \\
alpine tar czf /tmp/swarm-backup.tar.gz /var/lib/docker/swarm
注意:备份路径可能因 Docker 版本和 OS 而异,通常是 /var/lib/docker/swarm。
3. 恢复集群
如果所有 Manager 节点丢失,需要从备份恢复。
- 在剩余的一个 Manager 上恢复数据。
- 如果所有 Manager 都挂了且无法恢复,可能需要重新初始化集群(数据丢失风险)。
- 最佳实践:使用 docker swarm update –autolock 开启自动锁定,并妥善保存解锁密钥(Unlock Key)。
4. 自动锁定 (Auto-Lock)
防止节点重启后自动加入集群(安全加固):
docker swarm update –autolock
# 输出解锁密钥,务必保存!
docker swarm unlock-key
七、常见故障排查
1. 节点状态为 Down
- 检查网络连通性:ping <node_ip>。
- 检查防火墙:确保 2377 (TCP), 7946 (TCP/UDP), 4789 (UDP) 开放。
- 检查 Docker 日志:journalctl -u docker -f。
2. 服务无法调度
- 检查资源限制:docker node ps 查看是否有 Pending 状态。
- 检查约束条件:docker service inspect <service> 查看 Constraints 是否过于严格。
- 检查磁盘空间:docker system df。
3. Leader 选举失败
- 如果 Manager 节点数量变为偶数(如 3 变 2),集群可能无法选举 Leader。
- 解决:尽快添加一个新的 Manager 节点,或移除一个故障节点。




