Docker Swarm 完全指南:从原理到实战

424 阅读8分钟

Docker Swarm 完全指南:从原理到实战

前言

在现代应用部署中,单机容器化已经无法满足大规模应用的需求。Docker Swarm 作为 Docker 原生的集群管理和编排工具,提供了一个简单 yet 强大的方式来部署和管理跨多主机的容器化应用。本文将深入探讨 Docker Swarm 的各个方面,从核心概念到实战部署,帮助你掌握生产级的容器编排技术。

一、Docker Swarm 是什么?

1.1 核心定义

Docker Swarm 是 Docker 原生的集群管理和编排工具,它允许用户将多个 Docker 主机聚合成一个虚拟的单一系统,提供高可用性、负载均衡和弹性扩展能力。

1.2 Swarm 模式 vs 单机 Docker

特性单机 DockerDocker Swarm
主机数量单台多台(集群)
高可用性内置支持
服务发现手动配置自动服务发现
负载均衡需要外部工具内置负载均衡
扩展性手动扩展一键扩展
滚动更新手动操作自动滚动更新

1.3 Swarm 在容器编排生态中的位置

  • Docker Swarm:轻量级、易上手、Docker 原生
  • Kubernetes:功能强大、生态丰富、学习曲线陡峭
  • Nomad:灵活、多云支持、相对简单

二、Docker Swarm 架构与工作原理

2.1 集群架构

┌─────────────────────────────────────────────────┐
│                   Swarm Cluster                 │
│                                                 │
│  ┌─────────────┐    ┌─────────────┐            │
│  │  Manager    │    │  Manager    │            │
│  │   Node      │    │   Node      │            │
│  │ (Leader)    │    │ (Replica)   │            │
│  └─────────────┘    └─────────────┘            │
│          │               │                     │
│          ├───────────────┤                     │
│          ▼               ▼                     │
│  ┌─────────────┐    ┌─────────────┐            │
│  │  Worker     │    │  Worker     │            │
│  │   Node      │    │   Node      │            │
│  └─────────────┘    └─────────────┘            │
│                                                 │
└─────────────────────────────────────────────────┘

2.2 核心组件

Raft 一致性算法

  • 用于 Manager 节点间的状态一致性
  • 需要多数节点在线才能进行集群管理操作
  • 推荐使用 3 或 5 个 Manager 节点实现高可用

Dispatcher

  • 负责将任务分配给合适的节点
  • 监控任务状态并处理故障

Scheduler

  • 根据策略决定任务在哪个节点运行
  • 支持多种调度策略

Node

  • 每个节点都有唯一的 ID 和角色
  • 节点间通过 TLS 进行安全通信

2.3 工作流程

  1. 服务创建:用户通过 Manager 节点创建服务
  2. 调度决策:Scheduler 根据策略选择运行节点
  3. 任务分配:Dispatcher 将任务分配给 Worker 节点
  4. 状态同步:所有节点通过 gossip 协议同步状态
  5. 健康检查:Manager 监控节点和服务状态

三、核心概念详解

3.1 节点(Nodes)

Manager 节点

  • 负责集群管理任务
  • 维护集群状态
  • 调度服务
  • 提供 API 端点

Worker 节点

  • 执行容器任务
  • 接收 Manager 节点的指令
  • 报告任务状态
# 查看节点信息
docker node ls

# 查看节点详情
docker node inspect <node-name>

# 提升节点角色
docker node promote <node-name>

# 降级节点角色
docker node demote <node-name>

3.2 服务(Services)

服务是 Swarm 的核心概念,定义了要运行的任务:

# 创建服务
docker service create --name web --replicas 3 nginx:latest

# 查看服务
docker service ls

# 查看服务详情
docker service ps web

# 扩展服务
docker service scale web=5

# 更新服务
docker service update --image nginx:1.23 web

3.3 任务(Tasks)

任务是调度的最小单元,对应一个运行的容器:

# 查看任务列表
docker service ps <service-name>

# 任务状态包括:New, Pending, Assigned, Preparing, Running, Complete, Failed, Shutdown, Rejected, Orphaned

3.4 集群(Cluster)

集群是一组节点的集合:

# 初始化集群
docker swarm init --advertise-addr <MANAGER-IP>

# 加入集群
docker swarm join --token <TOKEN> <MANAGER-IP>:2377

# 查看集群信息
docker info

四、调度策略与模式

4.1 内置调度策略

Spread 策略(默认)

  • 将任务均匀分布 across 所有节点
  • 避免单节点过载
  • 最大化可用性
# 使用spread策略(默认)
docker service create --name web --replicas 5 nginx:latest

BinPack 策略

  • 尽可能将任务打包到少数节点
  • 节省资源,提高利用率
  • 可能降低可用性
# 使用binpack策略
docker service create --name web --replicas 5 --placement-pref spread=node.labels.zone nginx:latest

Random 策略

  • 随机选择节点
  • 主要用于测试

4.2 高级调度约束

节点标签约束

# 给节点添加标签
docker node update --label-add zone=east node1
docker node update --label-add zone=west node2

# 使用标签约束
docker service create \
  --name web \
  --replicas 3 \
  --constraint 'node.labels.zone == east' \
  nginx:latest

资源约束

# 基于节点角色
docker service create \
  --name web \
  --constraint 'node.role == manager' \
  nginx:latest

# 基于主机名
docker service create \
  --name web \
  --constraint 'node.hostname != node3' \
  nginx:latest

4.3 放置偏好(Placement Preferences)

# 多个放置偏好
docker service create \
  --name web \
  --replicas 6 \
  --placement-pref 'spread=node.labels.datacenter' \
  --placement-pref 'spread=node.labels.rack' \
  nginx:latest

五、Docker Swarm 核心特性

5.1 高可用性

服务副本

# 创建高可用服务
docker service create \
  --name database \
  --replicas 3 \
  --update-parallelism 1 \
  --update-delay 10s \
  postgres:13

节点故障转移

  • 自动检测节点故障
  • 在健康节点上重新调度任务
  • 保持期望的副本数量

5.2 滚动更新

# 配置滚动更新策略
docker service create \
  --name web \
  --replicas 5 \
  --update-parallelism 2 \
  --update-delay 10s \
  --update-failure-action rollback \
  nginx:1.20

# 触发滚动更新
docker service update \
  --image nginx:1.21 \
  --update-parallelism 1 \
  --update-delay 30s \
  web

5.3 服务回滚

# 自动回滚配置
docker service create \
  --name web \
  --replicas 5 \
  --rollback-parallelism 1 \
  --rollback-delay 10s \
  --rollback-max-failure-ratio 0.2 \
  nginx:latest

# 手动回滚
docker service rollback web

5.4 配置和密钥管理

# 创建配置
echo "database_url: postgresql://user:pass@db:5432/app" | docker config create app-config -

# 创建密钥
echo "secret-password" | docker secret create db-password -

# 使用配置和密钥
docker service create \
  --name app \
  --config source=app-config,target=/app/config.yaml \
  --secret source=db-password,target=/run/secrets/db-password \
  my-app:latest

六、Swarm 网络管理

6.1 网络架构

Overlay 网络

# 创建overlay网络
docker network create \
  --driver overlay \
  --subnet 10.0.0.0/24 \
  --attachable \
  my-overlay-net

Ingress 网络

  • 默认的 overlay 网络
  • 处理入站流量
  • 提供负载均衡

docker_gwbridge 网络

  • 连接 overlay 网络和物理网络
  • 处理出站流量

6.2 服务发现和负载均衡

内部负载均衡

# 服务间通过服务名自动发现和负载均衡
docker service create \
  --name web \
  --network my-overlay-net \
  --replicas 3 \
  nginx:latest

# 在另一个服务中可以通过"web"主机名访问
docker service create \
  --name app \
  --network my-overlay-net \
  my-app:latest  # 可以在代码中访问 http://web:80

外部负载均衡

# 发布端口到外部
docker service create \
  --name web \
  --publish published=8080,target=80 \
  --replicas 3 \
  nginx:latest

6.3 网络隔离和安全

# 创建内部网络(不对外暴露)
docker network create \
  --driver overlay \
  --internal \
  internal-net

# 网络加密
docker network create \
  --driver overlay \
  --opt encrypted \
  secure-net

七、安装和部署实战

7.1 环境准备

准备 3 台 Linux 主机(1 Manager + 2 Workers):

  • Manager: 192.168.1.10
  • Worker1: 192.168.1.11
  • Worker2: 192.168.1.12

7.2 初始化 Swarm 集群

在 Manager 节点上

# 初始化Swarm
docker swarm init --advertise-addr 192.168.1.10

# 输出示例:
Swarm initialized: current node (xyz) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-0xxx 192.168.1.10:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

获取加入令牌

# 获取worker加入令牌
docker swarm join-token worker

# 获取manager加入令牌
docker swarm join-token manager

在 Worker 节点上

# 加入Swarm集群
docker swarm join --token SWMTKN-1-0xxx 192.168.1.10:2377

7.3 验证集群状态

# 在Manager节点查看集群状态
docker node ls

# 输出示例:
ID                            HOSTNAME   STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
x1y2z3 *   manager1   Ready     Active         Leader           20.10.7
a2b3c4      worker1    Ready     Active                          20.10.7
d4e5f6      worker2    Ready     Active                          20.10.7

八、实战案例:部署高可用 Web 应用

8.1 部署架构

┌─────────────────────────────────────────────────┐
│                 Swarm Cluster                   │
│                                                 │
│  ┌─────────────┐    ┌─────────────┐            │
│  │  Manager    │    │   Worker    │            │
│  │   Node      │    │   Node      │            │
│  │             │    │             │            │
│  │  ▢ Web      │    │  ▢ Web      │            │
│  │  ▢ Redis    │    │  ▢ Web      │            │
│  │  ▢ Nginx    │    │             │            │
│  └─────────────┘    └─────────────┘            │
│          │               │                     │
│          └───────────────┘                     │
│                  │                             │
│  ┌─────────────┐ │                             │
│  │   Worker    │ │                             │
│  │   Node      │ │                             │
│  │             │ │                             │
│  │  ▢ Web      │ │                             │
│  │  ▢ Redis    │ │                             │
│  └─────────────┘ │                             │
│                  ▼                             │
│            Load Balancer                       │
│                 │                              │
│                 ▼                              │
│            External Users                      │
└─────────────────────────────────────────────────┘

8.2 创建 Overlay 网络

# 创建用于应用通信的overlay网络
docker network create \
  --driver overlay \
  --subnet 10.0.1.0/24 \
  --attachable \
  app-network

8.3 部署 Redis 服务

# 创建Redis服务
docker service create \
  --name redis \
  --network app-network \
  --replicas 2 \
  --update-parallelism 1 \
  --update-delay 10s \
  --restart-condition any \
  --health-cmd "redis-cli ping" \
  --health-interval 5s \
  --health-timeout 3s \
  --health-retries 3 \
  redis:6-alpine

8.4 部署 Web 应用服务

# 创建Web应用服务
docker service create \
  --name webapp \
  --network app-network \
  --replicas 4 \
  --update-parallelism 2 \
  --update-delay 15s \
  --restart-condition any \
  --env REDIS_HOST=redis \
  --env NODE_ENV=production \
  --limit-memory 512M \
  --reserve-memory 256M \
  my-webapp:latest

8.5 部署 Nginx 负载均衡器

# 创建Nginx配置
docker config create nginx-config ./nginx.conf

# 创建Nginx服务
docker service create \
  --name nginx \
  --network app-network \
  --publish published=80,target=80,mode=host \
  --publish published=443,target=443,mode=host \
  --config source=nginx-config,target=/etc/nginx/nginx.conf \
  --mode global \
  nginx:alpine

8.6 监控和运维

# 查看服务状态
docker service ls

# 查看详细任务状态
docker service ps webapp

# 扩展Web服务
docker service scale webapp=6

# 滚动更新Web服务
docker service update \
  --image my-webapp:2.0 \
  --update-parallelism 1 \
  --update-delay 30s \
  webapp

# 查看服务日志
docker service logs -f webapp

# 监控节点资源
docker node ps $(docker node ls -q)

九、高级部署模式

9.1 全局服务(Global Services)

# 在每个节点上运行监控代理
docker service create \
  --name node-exporter \
  --mode global \
  --mount type=bind,source=/proc,target=/host/proc \
  --mount type=bind,source=/sys,target=/host/sys \
  prom/node-exporter:latest

9.2 多架构部署

# 部署多架构服务
docker service create \
  --name multi-arch-app \
  --placement-pref 'spread=node.labels.arch' \
  --constraint 'node.labels.arch == x86_64' \
  --constraint 'node.labels.arch == arm64' \
  multi-arch-app:latest

9.3 金丝雀发布

# 第一步:部署新版本的部分实例
docker service create \
  --name webapp-canary \
  --network app-network \
  --replicas 2 \
  my-webapp:2.0

# 第二步:验证金丝雀版本
# 第三步:逐步替换旧版本
docker service update \
  --image my-webapp:2.0 \
  --update-parallelism 1 \
  --update-delay 30s \
  webapp

十、故障排查和维护

10.1 常见问题排查

# 查看集群健康状态
docker node ls

# 检查服务状态
docker service ls
docker service ps <service-name>

# 查看节点资源使用情况
docker node ps --format pretty $(docker node ls -q)

# 检查网络连接
docker network inspect app-network

# 查看容器日志
docker service logs <service-name>

10.2 集群维护

# 排空节点(准备维护)
docker node update --availability drain node1

# 恢复节点
docker node update --availability active node1

# 备份Swarm状态
docker swarm init --force-new-cluster

# 安全离开集群
docker swarm leave --force

10.3 安全最佳实践

# 轮换加入令牌
docker swarm join-token --rotate worker
docker swarm join-token --rotate manager

# 使用TLS加密
docker swarm init --advertise-addr <ip> --tlsverify

# 限制管理节点访问
iptables -A DOCKER-USER -p tcp --dport 2377 -j DROP
iptables -A DOCKER-USER -s <trusted-ip> -p tcp --dport 2377 -j ACCEPT

总结

Docker Swarm 提供了一个强大 yet 简单的容器编排解决方案,特别适合中小型企业和刚刚开始容器化旅程的团队。通过本文的深入学习,你应该能够:

  1. 理解 Swarm 的核心架构和工作原理
  2. 掌握关键概念:节点、服务、任务、集群
  3. 配置高级调度策略和放置约束
  4. 部署生产级应用 with 高可用性和滚动更新
  5. 管理 Swarm 网络和安全配置
  6. 进行故障排查和日常维护

Swarm 的优势在于其与 Docker 生态系统的无缝集成和较低的学习曲线,让你能够快速构建和管理生产级的容器化应用。

记住,选择编排工具时应该基于团队的技术水平、应用规模和业务需求。对于大多数场景,Docker Swarm 提供了一个完美的平衡点 between 功能复杂性和易用性。