强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

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-parallelism1同时更新的任务数
--update-delay0s更新间隔
--update-failure-actionpause失败动作:pause/rollback/continue
--update-orderstop-first更新顺序:stop-first/start-first
--update-max-failure-ratio0允许失败的比例
--rollback-parallelism1回滚并行度
--rollback-delay0s回滚间隔

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 - 安全加固:了解容器安全机制与最佳实践。