Docker 完全指南 / 11 - Swarm 集群
11 - Swarm 集群
使用 Docker Swarm 构建容器集群,实现服务发现、负载均衡与滚动更新。
11.1 Swarm 模式概述
Docker Swarm 是 Docker 内置的集群管理和编排工具,将多台 Docker 主机组成一个虚拟的 Docker 主机。
Swarm 集群架构:
┌────── Manager 节点 ──────┐ ┌────── Manager 节点 ──────┐
│ ┌─────────────────────┐ │ │ ┌─────────────────────┐ │
│ │ Swarm Manager │ │ │ │ Swarm Manager │ │
│ │ (Raft 共识) │ │ │ │ (Raft 共识) │ │
│ └─────────────────────┘ │ │ └─────────────────────┘ │
│ ┌──────┐ ┌──────┐ │ │ ┌──────┐ │
│ │Task 1│ │Task 2│ │ │ │Task 5│ │
│ └──────┘ └──────┘ │ │ └──────┘ │
└──────────────────────────┘ └──────────────────────────┘
│ │
└──────────── VXLAN ─────────────┘
┌────── Worker 节点 ──────┐ ┌────── Worker 节点 ──────┐
│ ┌──────┐ ┌──────┐ │ │ ┌──────┐ ┌──────┐ │
│ │Task 3│ │Task 4│ │ │ │Task 6│ │Task 7│ │
│ └──────┘ └──────┘ │ │ └──────┘ └──────┘ │
└──────────────────────────┘ └──────────────────────────┘
节点角色
| 角色 | 说明 | 推荐数量 |
|---|---|---|
| Manager | 集群管理、任务调度、Raft 共识 | 3 或 5(奇数) |
| Worker | 运行容器任务 | 按需扩展 |
11.2 初始化 Swarm 集群
单节点初始化
# 在主节点上初始化 Swarm
docker swarm init
# 输出:
# Swarm initialized: current node (abc123) is now a manager.
# To add a worker to this swarm, run the following command:
# docker swarm join --token SWMTKN-xxx manager-ip:2377
多节点集群
# Manager 节点初始化
docker swarm init --advertise-addr 192.168.1.100
# 获取 Worker 加入令牌
docker swarm join-token worker
# 获取 Manager 加入令牌
docker swarm join-token manager
# Worker 节点加入集群
docker swarm join --token SWMTKN-xxx 192.168.1.100:2377
# Manager 节点加入集群
docker swarm join --token SWMTKN-yyy 192.168.1.100:2377
集群管理
# 查看集群节点列表
docker node ls
# 查看节点详情
docker node inspect <node-id>
# 查看 Manager 节点
docker node ls --filter "role=manager"
# 提升 Worker 为 Manager
docker node promote <node-id>
# 降级 Manager 为 Worker
docker node drain <node-id> # 先排空任务
docker node demote <node-id>
# 离开集群
docker swarm leave
# 强制解散集群
docker swarm leave --force
11.3 服务管理
创建服务
# 创建基本服务
docker service create --name web --replicas 3 -p 80:80 nginx:alpine
# 详细配置
docker service create \
--name web \
--replicas 3 \
--publish published=80,target=80 \
--network my-net \
--env NODE_ENV=production \
--limit-cpu 0.5 \
--limit-memory 256M \
--reserve-cpu 0.25 \
--reserve-memory 128M \
--restart-condition on-failure \
--update-parallelism 1 \
--update-delay 10s \
nginx:alpine
服务管理命令
# 列出所有服务
docker service ls
# 查看服务详情
docker service inspect web
# 查看服务的任务(容器实例)
docker service ps web
# 查看服务日志
docker service logs web
docker service logs -f web
# 扩缩容
docker service scale web=5
# 更新服务(滚动更新)
docker service update --image nginx:1.25-alpine web
# 更新配置
docker service update --limit-memory 512M web
# 回滚
docker service rollback web
# 删除服务
docker service rm web
11.4 滚动更新
滚动更新过程 (replicas=3, parallelism=1):
第 1 步: 更新 Task 1 (Task 2, Task 3 继续服务)
第 2 步: 等待 delay 时间
第 3 步: 更新 Task 2 (Task 1(新), Task 3 继续服务)
第 4 步: 等待 delay 时间
第 5 步: 更新 Task 3 (Task 1(新), Task 2(新) 继续服务)
完成: 所有 Task 已更新到新版本
# 配置滚动更新策略
docker service create \
--name web \
--replicas 6 \
--update-parallelism 2 \
--update-delay 30s \
--update-failure-action rollback \
--update-order start-first \
--rollback-parallelism 1 \
--rollback-delay 10s \
-p 80:80 \
nginx:1.24-alpine
# 执行更新
docker service update --image nginx:1.25-alpine web
# 监控更新进度
docker service ps web
# 自动回滚(如果更新失败)
# 由 --update-failure-action rollback 控制
# 手动回滚
docker service rollback web
更新配置参数
| 参数 | 默认值 | 说明 |
|---|---|---|
--update-parallelism | 1 | 同时更新的任务数 |
--update-delay | 0s | 更新间隔 |
--update-failure-action | pause | 失败动作:pause/rollback/continue |
--update-order | stop-first | 更新顺序:stop-first/start-first |
--update-max-failure-ratio | 0 | 允许失败的比例 |
--rollback-parallelism | 1 | 回滚并行度 |
--rollback-delay | 0s | 回滚间隔 |
11.5 服务发现与负载均衡
内部负载均衡(Routing Mesh)
Swarm 路由网格:
任何节点:80 → ingress 网络 → VIP → 后端 Task
Client → 任意节点:80
↓
ingress overlay 网络
↓
虚拟 IP (VIP) → IPVS 负载均衡
↓
分发到具体的 Task 容器
# 服务发布端口后,集群中任意节点都可以访问
docker service create --name web --replicas 3 -p 80:80 nginx:alpine
# 在任意节点访问(即使该节点没有运行该服务的容器)
curl http://any-node-ip:80
DNS 服务发现
# 同一网络中的服务可通过服务名访问
docker service create --name api --network my-net my-api:v1
docker service create --name db --network my-net postgres:16
# api 服务中可以通过 db 服务名访问数据库
# 解析结果会轮询所有 db 任务的 IP
端口发布模式
# ingress 模式(默认):集群级负载均衡
docker service create -p 80:80 nginx:alpine
# host 模式:直接绑定宿主机端口
docker service create --publish published=80,target=80,mode=host nginx:alpine
# 不发布端口(仅内部访问)
docker service create --network my-net my-internal-service:v1
11.6 网络与存储
Overlay 网络
# 创建 overlay 网络
docker network create --driver overlay my-overlay
# 创建可被独立容器加入的 overlay 网络
docker network create --driver overlay --attachable my-attachable
# 在服务中使用
docker service create --name web --network my-overlay nginx:alpine
数据卷
# 使用全局存储卷(需要所有节点都有相同名称的卷)
docker service create \
--name db \
--mount type=volume,source=pg-data,target=/var/lib/postgresql/data \
postgres:16
# 使用 bind mount
docker service create \
--name web \
--mount type=bind,source=/opt/html,target=/usr/share/nginx/html \
nginx:alpine
注意: Swarm 模式下,Volume 不会自动跟随任务迁移。建议使用集中存储(NFS、云存储等)。
11.7 节点管理与约束
# 标记节点
docker node update --label-add zone=east node-1
docker node update --label-add zone=west node-2
docker node update --label-add disk=ssd node-3
# 排空节点(迁移所有任务)
docker node drain node-1
# 恢复节点
docker node update --availability active node-1
# 设置节点不可用
docker node update --availability pause node-2
放置约束
# 只在特定标签的节点上运行
docker service create \
--name web \
--constraint 'node.labels.zone == east' \
--constraint 'node.role == worker' \
nginx:alpine
# 要求 SSD 磁盘
docker service create \
--constraint 'node.labels.disk == ssd' \
my-io-intensive-app:v1
放置偏好(Placement Preferences)
# 按标签均匀分布(跨区域高可用)
docker service create \
--replicas 6 \
--placement-pref 'spread=node.labels.zone' \
nginx:alpine
# 会尽量将 6 个副本均匀分布在不同 zone
11.8 Stack 部署
Stack 允许使用 Compose 文件在 Swarm 中部署完整应用栈。
# stack.yaml
version: "3.8"
services:
web:
image: nginx:alpine
ports:
- "80:80"
deploy:
replicas: 3
update_config:
parallelism: 1
delay: 10s
restart_policy:
condition: on-failure
networks:
- frontend
api:
image: my-api:v1
ports:
- "8080:3000"
deploy:
replicas: 2
networks:
- frontend
- backend
db:
image: postgres:16
volumes:
- pg-data:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD_FILE=/run/secrets/db_pass
secrets:
- db_pass
deploy:
placement:
constraints:
- node.role == manager
networks:
- backend
networks:
frontend:
driver: overlay
backend:
driver: overlay
internal: true
volumes:
pg-data:
secrets:
db_pass:
external: true
# 部署 Stack
docker stack deploy -c stack.yaml my-app
# 列出 Stack
docker stack ls
# 查看 Stack 服务
docker stack services my-app
# 查看 Stack 任务
docker stack ps my-app
# 删除 Stack
docker stack rm my-app
11.9 Swarm 监控与调试
# 查看集群事件
docker events --filter "type=service"
# 查看服务日志
docker service logs -f --tail 100 web
# 检查服务健康
docker service inspect --pretty web
# 查看节点资源
docker node inspect --format '{{.Status.Resources }}' node-1
# 查看任务状态
docker service ps web --filter "desired-state=running"
docker service ps web --filter "desired-state=shutdown" # 查看历史
要点回顾
| 要点 | 核心内容 |
|---|---|
| Swarm 架构 | Manager (Raft) + Worker,推荐 3/5 Manager |
| 服务管理 | docker service create/scale/update/rollback |
| 滚动更新 | 控制并行度、间隔、失败策略 |
| 路由网格 | 任意节点可访问任何服务端口 |
| Stack | 使用 Compose 文件部署完整应用栈 |
注意事项
Manager 数量: 始终使用奇数个 Manager(1、3、5),Raft 共识需要多数节点存活。
数据持久化: Swarm 模式下 Volume 不会自动迁移。生产环境建议使用集中存储(NFS/云存储)。
资源限制: 使用
--limit-cpu和--limit-memory防止单个服务耗尽节点资源。
下一步
→ 12 - 安全加固:了解容器安全机制与最佳实践。