Docker Swarm 集群

Docker Swarm 集群

本文档介绍了 Docker Swarm 集群的基本概念、工作原理以及相关命令使用示例,包括如何在服务调度中使用自定义标签。本文档适用于需要管理和扩展 Docker 容器化应用程序的生产环境场景。


1. 什么是 Docker Swarm

Docker Swarm 是用于管理 Docker 集群的原生工具,从 Docker 1.12.0 版本开始,Swarm 已经内置于 Docker 引擎中。Swarm 可以将多台 Docker 主机组织成一个统一的虚拟主机,使用户能够轻松部署、管理和扩展容器化应用程序。

官方文档:Docker Swarm Overview


2. 与 Docker Compose 的区别

  • Docker Compose :适用于单节点环境,通过定义 docker-compose.yml 文件快速搭建和调试容器化应用。
  • Docker Swarm:专为生产环境设计,支持多节点集群管理和容器编排,还能实现零宕机滚动更新、弹性伸缩等高级功能。

3. Docker Swarm 的工作原理

3.1 基本概念

  • 节点 (Node)

    集群中的每个 Docker 主机都被称为一个节点。节点分为两种角色:

    • Manager 节点:负责集群的管理与控制,集群中可以有多个 Manager,但只有一个 Manager 被选举为 Leader。
    • Worker 节点:用于运行任务,由 Manager 分配任务后执行相应的容器操作。
  • 多重身份

    一个节点可以同时扮演 Manager 和 Worker 的角色。

  • Raft 协议

    使用 Raft 协议选举 Manager Leader 并同步状态信息,要求至少两个 Manager 参与选举。

3.2 工作流程

  1. 集群初始化

    使用 docker swarm init 命令初始化集群,执行节点自动成为 Manager(通常也是 Leader)。

  2. 节点加入

    其他 Docker 主机通过 Manager 节点分配的 token 加入集群,并被授予 Manager 或 Worker 角色。

  3. 服务定义

    通过定义服务来描述容器应用程序,并由 Manager 将任务分配到合适的节点。任务是 Swarm 中最小的调度单位,而一个服务是多个任务的集合。

  4. 调度策略

    Manager 节点按照调度策略(spread、binpack、random)选择合适的节点部署服务实例。

  5. 容器编排

    Manager 负责执行创建、启动、停止、重启等操作,保证应用程序持续高可用运行。


4. Swarm 集群管理

4.1 集群节点准备

角色 IP Hostname
Manager1 172.16.10.110 manager1
Manager2 172.16.10.111 manager2
Worker1 172.16.10.120 worker1
Worker2 172.16.10.121 worker2

4.2 初始化集群

在 Manager1 上执行以下命令:

bash 复制代码
docker swarm init --advertise-addr 172.16.10.110

执行成功后,输出中会显示用于其他节点加入集群的 token。注意:

  • 参数 --advertise-addr 用于指定通信的 IP 地址(默认端口为 2377),在多网卡环境下建议指定。

查看 token:

复制代码
docker swarm join-token manager   # 查看管理节点 token
docker swarm join-token worker    # 查看工作节点 token

4.3 节点加入

  • 加入 Manager2

    在 Manager2 上执行(请替换 <manager_token> 与对应的广播地址):

    复制代码
    docker swarm join --advertise-addr <Manager2_IP> --token <manager_token> 172.16.10.110:2377
  • 加入 Worker1 和 Worker2

    分别在 Worker 节点上执行:

    复制代码
    docker swarm join --advertise-addr <Worker_IP> --token <worker_token> 172.16.10.110:2377

在 Manager1 上使用 docker node ls 查看当前集群状态。

4.4 集群解散

要将节点退出并从集群移除:

  1. 在目标节点上执行:

    复制代码
    docker swarm leave [--force]   # Manager 节点退出需加 --force
  2. 在 Manager 节点上删除该节点:

    复制代码
    docker node rm <节点名称>

5. 节点管理

以下命令需在 Manager 节点上执行(Worker 节点无操作权限):

  • 查看集群所有节点

    复制代码
    docker node ls
  • 查看指定节点详情

    复制代码
    docker node inspect <节点名称> --pretty
  • 节点升级与降级

    复制代码
    bash复制编辑docker node promote <节点名称>   # 将 Worker 升级为 Manager
    docker node demote <节点名称>     # 将 Manager 降级为 Worker
  • 节点下线(暂停任务调度)

    复制代码
    docker node update --availability drain <节点名称>
  • 节点上线

    复制代码
    docker node update --availability active <节点名称>

6. 服务管理

6.1 服务定义

创建服务时常用的命令格式如下:

复制代码
bash复制编辑docker service create --name <服务名> \
  [-d] [-p] [-e] [--network] [--replicas] [--mount] \
  image:tag
示例
  • 测试 1:指定副本数、端口映射

    复制代码
    docker service create -d --name web-nginx --replicas 2 -p 80:80 nginx
  • 测试 2:传递环境变量

    复制代码
    bash复制编辑docker service create -d --name mysql --replicas=1 \
      -p 3306:3306 \
      -e MYSQL_ROOT_PASSWORD=123456 \
      -e MYSQL_DATABASES=test \
      mysql:5.7

6.2 服务查看

  • 查看所有服务:

    复制代码
    docker service ls
  • 查看指定服务及其任务分布:

    复制代码
    docker service ps <服务名>

示例输出:

复制代码
docker service ls
ID             NAME        MODE         REPLICAS   IMAGE          PORTS
0jlt1yx8dcox   mysql       replicated   1/1        mysql:5.7      *:3306->3306/tcp
fxha9cy659vu   web-nginx   replicated   3/3        nginx:1.24.0   *:80->80/tcp


docker service ps mysql
ID             NAME      IMAGE       NODE      DESIRED STATE   CURRENT STATE           ERROR     PORTS
wit44m5i6plf   mysql.1   mysql:5.7   master    Running         Running 3 minutes ago

6.3 服务移除

复制代码
docker service rm <服务名称>

6.4 服务模式及调度

  • 服务模式

    • Replicated 模式(默认):在指定节点上运行多个副本。
    • Global 模式:在每个节点上都运行一个副本(适合日志收集、监控等场景)。

    示例:

    复制代码
    docker service create --name cadvisor --mode global \
      --mount type=bind,src=/,dst=/rootfs,readonly \
      --mount type=bind,src=/var/run,dst=/var/run \
      --mount type=bind,src=/sys,dst=/sys,readonly \
      --mount type=bind,src=/var/lib/docker/,dst=/var/lib/docker,readonly \
      --publish 8888:8080 \
      gcr.io/cadvisor/cadvisor:latest
  • 调度约束

    通过指定调度约束,可以控制服务任务只在符合要求的节点上运行。

    • 根据节点主机名调度:

      复制代码
      docker service create --name my-service \
        --constraint 'node.hostname == node01' \
        nginx:latest
    • 根据自定义标签调度:

      1. 给节点添加自定义 Label

        在 Manager 节点上执行(假设给 node01 添加 hm=node01):

        复制代码
        docker node update --label-add hm=node01 node01

        查看节点标签:

        复制代码
        docker node inspect node01 --pretty
      2. 使用标签调度创建服务

        复制代码
        docker service create --name my-service \
          --constraint 'node.labels.hm == node01' \
          nginx:latest

      docker-compose.yml 文件中也可通过 deploy.placement.constraints 设置:

      yaml 复制代码
      version: '3.8'
      services:
        web:
          image: nginx:latest
          deploy:
            replicas: 1
            placement:
              constraints:
                - "node.labels.hm == node01"
          ports:
            - "80:80"

      部署命令:

      复制代码
      docker stack deploy -c docker-compose.yml mystack
  • 移除节点标签

    复制代码
    docker node update --label-rm hm node01

6.5 服务日志

查看服务日志:

复制代码
docker service logs <服务名>

7. Swarm 集群的弹性伸缩

弹性伸缩指动态增加或减少服务任务数。

  • 创建服务时指定副本数

    复制代码
    docker service create -d --name mysql --replicas=2 \
      -p 3306:3306 \
      -e MYSQL_ROOT_PASSWORD=123456 \
      mysql:5.7
  • 在线伸缩命令

    • 使用 update 命令:

      复制代码
      docker service update --replicas <新副本数> <服务名>
    • 或者使用 scale 命令:

      复制代码
      docker service scale <服务名>=<副本数>

8. Swarm 集群服务的滚动更新

滚动更新允许在不中断服务的情况下更新服务。常用于灰度发布与镜像升级。

8.1 更新命令示例

例如升级 MySQL 服务镜像版本,从 v5.7 到 v8.0,同时调整副本数量:

复制代码
docker service update --replicas 5 \
  --image mysql:8.0 \
  --update-delay 60s \
  --update-parallelism 5 \
  mysql

参数说明:

  • --update-delay:指定滚动更新每个任务之间的延时(支持秒、分钟、小时)。
  • --update-parallelism:指定同时更新的任务数。

8.2 镜像版本回退

有两种方式:

  • 方式一:使用 rollback 命令

    复制代码
    docker service rollback mysql

    此命令会回滚到上次成功部署的状态。

  • 方式二:手动指定旧版本进行更新

    复制代码
    docker service update --image mysql:5.7 mysql
  • 查看更新状态

    复制代码
    docker service inspect --pretty mysql

    输出中 UpdateConfig 部分会显示当前服务的更新状态,例如 rollback_completed 表示已回滚。


9. 使用 Docker Compose 部署 Swarm 集群

9.1 docker service create 的局限

该命令一次只能创建一个服务,多个服务时较为繁琐,因此推荐使用 Compose 文件配合 docker stack deploy 部署整个应用堆栈。

9.2 Docker Compose 文件中的 Swarm 配置

在 Compose 文件中,可在 deploy 下配置与 Swarm 相关的属性。请注意,使用 docker-compose up 时会忽略 deploy 部分,因此必须通过 docker stack deploy 部署。

示例:

复制代码
yaml复制编辑version: '3.8'
services:
  web:
    image: nginx:latest
    deploy:
      replicas: 2                   # 服务副本数
      mode: replicated              # 服务模式:replicated(默认)或 global
      placement:
        constraints:
          - "node.hostname == node01"      # 根据主机名调度
          - "node.labels.hm == node01"       # 根据自定义标签调度
      restart_policy:
        condition: on-failure     # 仅在容器异常退出时重启
        delay: 10s                # 尝试重启的间隔时间
        max_attempts: 3           # 最大重启尝试次数
    ports:
      - "80:80"

9.3 部署 Stack

使用以下命令部署堆栈:

复制代码
docker stack deploy -c docker-compose.yml mystack
  • 查看堆栈列表:

    复制代码
    docker stack ls
  • 查看堆栈服务:

    复制代码
    docker stack services mystack
  • 查看堆栈任务:

    bash 复制代码
    docker stack ps mystack
  • 删除堆栈:

    bash 复制代码
    docker stack rm mystack
相关推荐
小码过河.1 小时前
CentOS 安装 Docker
linux·docker·centos
laimaxgg3 小时前
Dockerfile
linux·运维·服务器·ubuntu·docker
与passion共存4 小时前
Linux系统下Docker安装
linux·docker
西伯利亚猹4 小时前
Windows系统docker desktop安装(学习记录)
运维·docker·容器
LCY1335 小时前
centOS 安装和配置docker
linux·docker·centos
遇见火星6 小时前
基于Docker容器的CICD项目Jenkins/gitlab/harbor/Maven实战
docker·容器·gitlab·jenkins·maven·harbor·cicd
LCY1336 小时前
k8s 部署spring项目+动态启动pod
spring·容器·kubernetes
Spring_java_gg10 小时前
组件和容器之争?|WebAssembly + Kubernetes:云原生的新组合
云原生·容器·kubernetes·wasm
code@fzk10 小时前
Docker详细使用
linux·运维·docker·容器·shell
三石兄_201016 小时前
wsl中迁移ubuntu24.04后docker后无法启动的问题
docker