1. Docker Swarm高可用部署的核心价值

在生产环境中,容器编排系统的高可用性不是可选项而是必选项。Docker Swarm作为原生的容器编排工具,其HA方案相比Kubernetes更轻量,学习曲线也更平缓。上周我们团队的核心业务Swarm集群经历了主节点宕机,却因正确的HA部署实现了30秒内自动故障转移,业务流量零中断。这种"无感切换"正是高可用集群的魅力所在。

2. 高可用集群的架构设计

2.1 节点角色规划

典型的Swarm HA集群包含三类节点:

  • Manager节点(3/5/7奇数个) :运行Raft共识算法,建议至少3个节点形成法定人数
  • Worker节点(N个) :运行业务容器,可水平扩展
  • 边缘节点(可选) :专门用于集群入口流量管理

关键经验:Manager节点数量建议3个起步,5个为生产环境推荐值。我们曾用2个Manager节点测试,当1个节点故障时,集群虽然能工作但会持续报"no leader"警告。

2.2 网络拓扑设计

我们的生产环境网络布局如下表所示:

节点类型 物理位置 网络延迟要求 典型配置
Manager-1 机房A-机架1 <2ms互访延迟 32核/64GB内存
Manager-2 机房B-机架2 <2ms互访延迟 32核/64GB内存
Manager-3 机房C-机架3 <2ms互访延迟 32核/64GB内存
Worker-N 任意机房 <5ms到Manager 按业务需求配置

3. 集群部署实操步骤

3.1 初始化第一个Manager节点

# 在首节点执行(假设IP为192.168.1.101)
docker swarm init --advertise-addr 192.168.1.101 \
    --data-path-addr 192.168.1.101 \
    --default-addr-pool 10.10.0.0/16

参数说明:

  • --advertise-addr :集群通信地址
  • --data-path-addr :数据面流量地址(生产环境建议与控制面分离)
  • --default-addr-pool :自定义Overlay网络地址池

3.2 加入其他Manager节点

获取join-token后在其他节点执行:

docker swarm join --token SWMTKN-1-xxxx 192.168.1.101:2377 \
    --advertise-addr 192.168.1.102 \
    --data-path-addr 192.168.1.102

避坑提示:2377端口必须开放且未被占用。我们曾遇到防火墙阻断导致节点无法加入,用 telnet <manager-ip> 2377 测试连通性是个好习惯。

3.3 验证集群状态

# 查看节点状态
docker node ls

# 检查Raft集群健康度
docker swarm inspect | grep -A 10 "Raft"

健康集群应显示类似:

ID                            HOSTNAME   STATUS  AVAILABILITY  MANAGER STATUS
x1y2z *  node-101  Ready   Active        Leader
a2b3c    node-102  Ready   Active        Reachable
p0q9r    node-103  Ready   Active        Reachable

4. 故障恢复实战记录

4.1 模拟Leader节点宕机

我们通过强制停止docker服务模拟故障:

# 在Leader节点执行
systemctl stop docker

观测到以下自动恢复过程:

  1. 30秒后剩余Manager节点检测到心跳超时
  2. 剩余节点发起新Leader选举(基于Raft算法)
  3. 新Leader接管集群控制权(平均耗时45秒)
  4. 所有服务重新调度到健康节点

4.2 关键恢复指标

我们在测试环境收集的典型恢复数据:

指标 平均值 最优值 最差值
故障检测时间 32s 28s 40s
新Leader选举时间 47s 39s 58s
服务完全恢复时间 83s 75s 110s

4.3 节点重新加入流程

修复故障节点后重新加入集群:

# 1. 清理旧集群数据(关键步骤!)
rm -rf /var/lib/docker/swarm

# 2. 重新加入集群
docker swarm join --token SWMTKN-1-xxxx 192.168.1.102:2377

血泪教训:未清理swarm目录直接重新加入会导致集群脑裂。我们曾因此导致整个集群不可用,最终不得不重建集群。

5. 生产环境加固建议

5.1 监控关键指标

通过Prometheus监控这些核心指标:

  • swarm_manager_leader :当前是否为Leader(1/0)
  • swarm_node_state :节点状态(0=不可用, 1=可用)
  • swarm_raft_term :Raft任期编号变化频率

5.2 备份集群状态

定期备份Swarm集群配置:

# 导出集群状态
docker swarm init --force-new-cluster  # 如果是最后一个存活节点
tar czvf swarm-backup-$(date +%s).tar.gz /var/lib/docker/swarm

5.3 滚动升级策略

采用分批次升级Manager节点:

  1. 先升级非Leader节点
  2. 手动转移Leader角色: docker node promote <node-id>
  3. 最后升级原Leader节点
  4. 每个批次间隔至少15分钟

6. 典型故障排查手册

6.1 节点无法加入集群

检查清单:

  1. 防火墙是否开放2377/tcp和7946/udp端口
  2. 节点时间是否同步(NTP服务正常)
  3. Join token是否过期(有效期24小时)

6.2 服务调度异常

常见原因:

  • 节点标签不匹配: docker node update --label-add zone=east <node-id>
  • 资源不足:检查 docker system df 输出
  • 网络分区:检查 docker network inspect ingress

6.3 脑裂场景处理

当出现双Leader时:

  1. 停用所有Manager节点的docker服务
  2. 确认最后一个健康Leader节点
  3. 在该节点执行: docker swarm init --force-new-cluster
  4. 其他节点清理swarm目录后重新加入

7. 性能调优实战

7.1 Raft调优参数

通过 /etc/docker/daemon.json 配置:

{
  "swarm": {
    "raft": {
      "election_tick": 5,
      "heartbeat_tick": 2,
      "snapshot_interval": 20000
    }
  }
}

参数说明:

  • election_tick :心跳丢失多少次后触发选举(默认5)
  • heartbeat_tick :心跳间隔(单位:秒的倍数)
  • snapshot_interval :Raft日志快照间隔(默认10000)

7.2 网络性能优化

对于高频通信服务:

docker service create \
  --network my-overlay \
  --endpoint-mode dnsrr \
  --name my_service \
  nginx:alpine

关键选项:

  • dnsrr :DNS轮询模式,避免IPVS开销
  • 自定义Overlay网络:隔离不同服务流量

8. 灾备演练方案

我们每季度执行的完整演练流程:

  1. 准备阶段

    • 通知相关团队进入观察状态
    • 备份所有Swarm配置和卷数据
  2. 模拟故障

    • 随机选择1个Manager节点强制关机
    • 观察监控系统告警
    • 记录服务恢复时间
  3. 验证阶段

    • 检查所有业务服务状态
    • 验证数据一致性
    • 测试新服务创建能力
  4. 复盘改进

    • 分析恢复时间是否符合SLA
    • 优化自动化恢复脚本
    • 更新应急预案文档

经过三年生产环境验证,这套HA方案在保证99.95%可用性的同时,运维复杂度远低于同规模K8s集群。对于中小规模容器化部署,Swarm仍是平衡功能与复杂度的优选方案。

更多推荐