2-9-Docker-Swarm

熊 0 阅读 容器

1. 简介

Swarm是Docker官方提供的一款集群管理工具 , 其主要作用是把若干台Docker主机抽象为一个整体 , 并且通过一个入口统一管理这些Docker主机上的各种Docker资源。Swarm和Kubernetes比较类似 , 但是更加轻 , 具有的功能也较kubernetes更少一些。

Swarm提供了标准的Docker API , 所有任何已经与Docker守护程序通信的工具都可以使用Swarm轻松地扩展到多个主机。支持的工具包括Dokku、Docker Compose、Docker Machine和Jenkins等。

compose、machine 和swarm是docker 原生提供的三大编排工具 , 简称docker三剑客。其官网地址 : https://docs.docker.com/engine/swarm/

  • Docker Swarm和Docker Compose

    Docker Swarm和Docker Compose都是Docker官方容器编排项目

    • Docker Compose是一个在单个服务器或主机上创建多个容器的工具 , 可以将组成某个应该的多个docker容器编排在一起 , 同时管理。

      docker-swarm-1
    • Docker Swarm则可以在多个服务器或主机上创建容器集群服务 , 其主要作用是把若干台Docker主机抽象为一个整体 , 并且通过一个入口 ( docker stack ) 统一管理这些Docker主机上的各种Docker资源。

      docker-swarm-2
  • docker stack

    • docker stack是构成特定环境中的service集合, 它是自动部署多个相互关联的服务的简便方法 , 而无需单独定义每个服务。

    • stack file是一种yaml格式的文件 , 类似于docker-compose.yml文件 , 它定义了一个或多个服务 , 并定义了服务的环境变量、部署标签、容器数量以及相关的环境特定配置等。

Docker Swarm就是用来管理Docker集群的 , 但是现在基本上使用的很少 , 一般都是用的K8S,学习K8S之前可以先学习一个Docker Swarm , 将其作为一个容器编排的一个学习基础 , 了解一下即可。

Swarm的基本架构如下图所示

docker-swarm-3

这个图作为一个整体实际上都处于一个所谓的集群中 , 它可能对应了一到多台的实际服务器。每台服务器上都装有Docker并且开启了基于HTTP的DockerAPI。这个集群中有一个SwarmManager的管理者 , 用来管理集群中的容器资源。管理者的管理对象不是服务器层面而是集群层面的 , 也就是说通过Manager , 我们只能笼统地向集群发出指令而不能具体到某台具体的服务器上要干什么 ( 这也是Swarm的根本所在 ) 。至于具体的管理实现方式 , Manager向外暴露了一个HTTP接口 , 外部用户通过这个HTTP接口来实现对集群的管理。对于稍微大一点的集群 , 最好是拿出一台实际的服务器作为专门的管理者 , 作为学习而言 , 也可以把管理者和被管理者放在一台服务器上。

Swarm在Docker 1.12版本之前属于一个独立的项目 , 在Docker 1.12版本发布之后 , 该项目合并到了Docker中 , 成为Docker的一个子命令。目前 , Swarm是Docker社区提供的唯一一个原生支持Docker集群管理的工具。它可以把多个 Docker 主机组成的系统转换为单一的虚拟Docker主机 , 使得容器可以组成跨主机的子网网络。

Docker Swarm是一个为IT运维团队提供集群和调度能力的编排工具。用户可以把集群中所有Docker Engine 整合进一个虚拟 Engine的资源池 , 通过执行命令与单一的主Swarm进行沟通 , 而不必分别和每个Docker Engine沟通。在灵活的调度策略下 , IT 团队可以更好地管理可用的主机资源 , 保证应用容器的高效运行。

2. 相关概念

  • 节点

    运行Docker的主机可以主动初始化一个Swarm集群或者加入一个已存在的Swarm集群 , 这样这个运行Docker的主机就成为一个 Swarm集群的节点 (node) 。节点分为管理 (manager) 节点和工作 (worker) 节点。

    管理节点用于Swarm集群的管理 , docker swarm命令基本只能在管理节点执行 ( 节点退出集群命令docker swarm leave或者加入集群可以在工作节点执行 ) 。一个Swarm集群可以有多个管理节点 , 但只有一个管理节点可以成为leader , leader通过raft协议实现。

    工作节点是任务执行节点 , 管理节点将服务 (service) 下发至工作节点执行。管理节点默认也作为工作节点。你也可以通过配置让服务只运行在管理节点。下图展示了集群中管理节点与工作节点的关系

    docker-swarm-4
  • 服务和任务

    任务(Task ) 是Swarm中的最小的调度单位 , 目前来说就是一个单一的容器。 服务 ( Services ) 是指一组任务的集合 , 服务定义了任务的属性。服务有两种模式 :

    1. replicated services : 按照一定规则在各个工作节点上运行指定个数的任务。

    2. global services : 每个工作节点上运行一个任务

    两种模式通过 docker service create 的 --mode 参数指定。下图展示了容器、任务、服务的关系。

    docker-swarm-5

3. Docker Swarm运行原理

Swarm集群由多个运行在swarm mode的docker主机组成 , docker主机分为管理节点 ( manager ) 和工作节点 ( work node ) 两种类型

  • 管理节点 ( manager ) : 负责整个集群的管理工作包括集群配置、服务管理 , 服务的创建和调度等

  • 工作节点 ( work node ) : 负责运行相应的服务来执行任务 ( 运行容器服务 )

    manager节点也可以运行的容器服务,但是一般不这么做 , 只是让它管理work node

Swarm集群的优点 :

  • 在线修改Service的配置 , 包括networks和volumes , 不需要重启docker服务

  • 可以将其它standalone模式的docker主机加入到Swarm集群

3.1 node

Node是加入到Swarm集群中的Docker实例 , 即是一个docker节点 , 包含上面说的管理节点 ( manager ) 和工作节点 ( work node )

  • 在部署应用到Swarm集群的时候 , 会向管理节点提交service定义 , 管理节点会将这些这些work也就是tasks分发到work节点中。

  • Work节点接收并执行管理节点分配的任务 , work节点也会将当前tasks的状态通知到管理节点以维护节点的状态信息。

docker-swarm-6

  • 管理节点( manager node)

    Manager节点主要通过raft算法实现整个集群和运行的service的内部状态维护 , Docker官方建议一个集群最好使用基数manager节点数 , 最大使用7个manager节点以保证可用性,Manager节点主要工作是完成以下tasks :

    • 维护集群状态

    • scheduling服务

    • 支持service/swarm模式的集群服务

  • 工作节点( work node)

    Work节点是容器实际运行的实例节点 , 在默认情况下manager节点也是work节点 , 而且在在Swarm集群中必须存在manager节点

    manager节点状态、信息的同步根据Raft consensus group(Raft一致性算法)的网络进行通信同步的 , 而worker之间的通信依靠的是Gossip network通信协议实现的。

  • 管理节点与工作节点的切换

    在多节点的Swarm集群中 , 节点有两种模式 : Active模式、Drain模式。

    Swarm调度不会将任务分配到Drain模式 , 只会在Active模式的节点上分配任务。因此可以将manager节点设置为Drain模式( 避免调度任务运行在manager节点 , manager指做管理)

    通过以下命令可以修改节点模式 , 将worker节点变为manager节点 , 也可以将manager节点转换为worker节点。

    docker node promote NODE [NODE...] #将指定节点升级为manager节点
    docker node demote  NODE [NODE...] #将指定节点降级为work节点

3.2 Service与tasks

Service是manage和work节点上执行的task的定义 , 创建service的时候可以指定使用哪个容器镜像以及执行的命令。

当Service部署到Swarm集群的时候 , swarm管理节点会将service识别为标准的容器镜像以及执行的命令 , 然后将service调度到集群的节点上 , 以一个或多个tasks执行 , 这些nodes上运行的tasks之间是相互独立的。

  • 在replicated service模式下 ,swarm管理节点会根据desired state中设置的scale参数决定分发tasks数量

  • 在global service模式 ,swarm集群会向每个可用的节点运行tasks。

docker-swarm-7

如上service中有三个replicas tasks , 每个实例是Swarm集群中的一个task。

Task是Swarm集群中调度的最小单元 , 当创建或更新service时候给定了需要的状态参数 , 集群会调度tasks来实现这种理想状态」。

  • Task是一种单向机制 , 它整个周期过程中会完成一系列的状态(assigned、prepared和running等) , tasks运行失败集群会remove这个tasks并创建新的tasks来替代。

3.3 load balancing

负载均衡 : Swarm集群使用ingress loading balancing提供集群服务 , Swarm集群会自动为service分配PublishedPort , 默认使用30000-32767范围。

4. Docker Swarm安装部署

官方地址 : https://docs.docker.com/engine/swarm/

4.1 环境准备

环境说明

主机名

宿主机IP

安装软件

node01

192.168.194.130/24

docker、harbor、Swarm manager节点

node02

192.168.194.145/24

docker、Swarm Work节点

node03

194.168.194.146

docker、Swarm Work 节点

  • 配置私有仓库(harbor)

    #三个节点同时配置以下内容
    [root@node02 ~]# cat /etc/docker/daemon.json 
    { 
        "insecure-registries" : [
          "192.168.194.130"
         ]
    }
  • 准备两个镜像, 并且上传到harbor仓库中 ,上传两个镜像的版本主要区别是index.html 文件中的内容不一样。

    [root@node01 nginx]# cat Dockerfile 
     FROM centos:latest
     RUN  sed -e "s|^mirrorlist=|#mirrorlist=|g" -e "s|^#baseurl=http://mirror.centos.org/\$contentdir/\$releasever|baseurl=https://mirrors.aliyun.com/centos-vault/8.4.2105|g" -e "s|^#baseurl=http://mirror.centos.org/\$contentdir/\$releasever|baseurl=https://mirrors.aliyun.com/centos-vault/8.4.2105|g"  -i.bak  /etc/yum.repos.d/CentOS-*.repo
    ​
     RUN  yum -y install epel-release
     RUN yum -y install nginx
     ADD index.html /usr/share/nginx/html/
     RUN echo "daemon off;" >> /etc/nginx/nginx.conf
     EXPOSE 80
     CMD /usr/sbin/nginx
    ​
    ​
    [root@node01 nginx]# docker build -t 192.168.194.130/library/centos-nginx:v1 .
    [+] Building 54.4s (11/11) FINISHED                                                                       docker:default
     => [internal] load build definition from Dockerfile                                                                0.0s
     => => transferring dockerfile: 579B                                                                                0.0s
     => [internal] load metadata for docker.io/library/centos:latest                                                    0.0s
     => [internal] load .dockerignore                                                                                   0.0s
     => => transferring context: 2B                                                                                     0.0s
     => CACHED [1/6] FROM docker.io/library/centos:latest                                                               0.0s
     => [internal] load build context                                                                                   0.0s
     => => transferring context: 31B                                                                                    0.0s
     => [2/6] RUN  sed -e "s|^mirrorlist=|#mirrorlist=|g" -e "s|^#baseurl=http://mirror.centos.org/$contentdir/$releas  0.2s
     => [3/6] RUN  yum -y install epel-release                                                                         21.2s
     => [4/6] RUN yum -y install nginx                                                                                 31.8s 
     => [5/6] ADD index.html /usr/share/nginx/html/                                                                     0.0s 
     => [6/6] RUN echo "daemon off;" >> /etc/nginx/nginx.conf                                                           0.2s 
     => exporting to image                                                                                              0.9s 
     => => exporting layers                                                                                             0.8s 
     => => writing image sha256:ee8ab8cd6f76dc4f9f2f133b12478f4b862682e783ac11d0cdb0c361491ef2a6                        0.0s 
     => => naming to 192.168.194.130/library/centos-nginx:v1                                                            0.0s 
    [root@node01 nginx]# docker login 192.168.194.130
    Username: admin
    Password: 
    Error response from daemon: Get "https://192.168.194.130/v2/": dial tcp 192.168.194.130:443: connect: connection refused
    [root@node01 nginx]# vi /etc/docker/daemon.json 
    [root@node01 nginx]# systemctl restart docker
    [root@node01 nginx]# docker login 192.168.194.130
    Username: admin
    Password: 
    WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
    Configure a credential helper to remove this warning. See
    https://docs.docker.com/engine/reference/commandline/login/#credentials-store
    ​
    Login Succeeded
    [root@node01 nginx]# docker push 192.168.194.130/library/centos-nginx:v1 
    The push refers to repository [192.168.194.130/library/centos-nginx]
    b0a1f902d9f6: Pushed 
    66e4d538054a: Pushed 
    db19257c0200: Pushed 
    3abc694316c5: Pushed 
    407ead47ac74: Pushed 
    74ddd0ec08fa: Pushed 
    v1: digest: sha256:ab6daf03ee25c6526f028636978e639fa06b77da341e5101122637681438c813 size: 1576
    [root@node01 nginx]# docker build -t 192.168.194.130/library/centos-nginx:v2 .
    [+] Building 0.4s (11/11) FINISHED                                                                        docker:default
     => [internal] load build definition from Dockerfile                                                                0.0s
     => => transferring dockerfile: 579B                                                                                0.0s
     => [internal] load metadata for docker.io/library/centos:latest                                                    0.0s
     => [internal] load .dockerignore                                                                                   0.0s
     => => transferring context: 2B                                                                                     0.0s
     => [1/6] FROM docker.io/library/centos:latest                                                                      0.0s
     => [internal] load build context                                                                                   0.0s
     => => transferring context: 61B                                                                                    0.0s
     => CACHED [2/6] RUN  sed -e "s|^mirrorlist=|#mirrorlist=|g" -e "s|^#baseurl=http://mirror.centos.org/$contentdir/  0.0s
     => CACHED [3/6] RUN  yum -y install epel-release                                                                   0.0s
     => CACHED [4/6] RUN yum -y install nginx                                                                           0.0s
     => [5/6] ADD index.html /usr/share/nginx/html/                                                                     0.0s
     => [6/6] RUN echo "daemon off;" >> /etc/nginx/nginx.conf                                                           0.2s
     => exporting to image                                                                                              0.1s
     => => exporting layers                                                                                             0.0s
     => => writing image sha256:6297f3fffb4fed7266567bf09e895c3ac256df4c94aefd6d238ad6e3efb12ee0                        0.0s
     => => naming to 192.168.194.130/library/centos-nginx:v2                                                            0.0s
    [root@node01 nginx]# docker push 192.168.194.130/library/centos-nginx:v2 
    The push refers to repository [192.168.194.130/library/centos-nginx]
    a693a7f1ca44: Pushed 
    65cc9260a187: Pushed 
    db19257c0200: Layer already exists 
    3abc694316c5: Layer already exists 
    407ead47ac74: Layer already exists 
    74ddd0ec08fa: Layer already exists 
    v2: digest: sha256:c3f63dc90db7b46f125f00314106161dec7381dad4f511f75de59a6392358934 size: 1576
    ​

4.2 docker swarm 安装

  • 初始化manager管理节点完整命令如下:

    [root@node01 ~]# docker swarm init --listen-addr 192.168.194.130:2377
    Swarm initialized: current node (zm37bg35xt6ux4o0ugwdioh60) is now a manager.
    ​
    To add a worker to this swarm, run the following command:
    ​
        docker swarm join --token SWMTKN-1-4dklz4o6kibrq5a4xl302yrttl91flc8xzvnkv09v2lh8zxj0e-0sesf1f9etggkfqublpybp7e3 192.168.194.130:2377
    ​
    To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
    ​

    执行上面命令后 , 就会初始化swarm集群 , 并且会告诉我们如何增加wrok节点和manager节点

    查看网络情况 , 新增了一个用于集群的网络

    image-20240309174649799
  • 其他节点以work角色加入到Swarm集群中

    [root@node02 ~]# docker swarm join --token SWMTKN-1-4dklz4o6kibrq5a4xl302yrttl91flc8xzvnkv09v2lh8zxj0e-0sesf1f9etggkfqublpybp7e3 192.168.194.130:2377
    This node joined a swarm as a worker.
    [root@node03 ~]# docker swarm join --token SWMTKN-1-4dklz4o6kibrq5a4xl302yrttl91flc8xzvnkv09v2lh8zxj0e-0sesf1f9etggkfqublpybp7e3 192.168.194.130:2377
    This node joined a swarm as a worker.
    ​

命令说明

  • 初始化集群命令

    • 语法 : docker swarm init

      • --advertise-addr : 指定其他节点连接manager时的地址

      • --listen-addr : 监控swarm集群manager的IP和端口

      如果主机同时有多张网卡同时配置了网络, 则需要同时配置这两个选项, 如果主机只有一张网卡配置了IP , 则只需要配置--listen-addr即可

  • 查看节点

    • 语法 : docker node list/docker node ls

      [root@node01 ~]# docker node list
      ID                            HOSTNAME   STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
      zm37bg35xt6ux4o0ugwdioh60 *   node01     Ready     Active         Leader           25.0.4
      ila50dkratcna82vvjftez6ly     node02     Ready     Active                          25.0.4
      4l06sj6biuvciudz6selu5dw4     node03     Ready     Active                          25.0.4
      ​
      #leader 表示该节点为manager节点
      # AVAILABILITY 为Active 表示该节点可以运行task服务
  • 新加一个Work节点

    通过上面初始化manager返回的命令 , 给集群加入新的节点 , 只需要在对应的主机上执行该命令即可

    [root@node03 ~]# docker swarm join --token SWMTKN-1-4dklz4o6kibrq5a4xl302yrttl91flc8xzvnkv09v2lh8zxj0e-0sesf1f9etggkfqublpybp7e3 192.168.194.130:2377
    This node joined a swarm as a worker.

    这个命令本质上就是manager初始化的时候返回了一个token , 其他主机通过这个token加入集群 , 并且token只有24小时。如果失效 , 则需要重新获取

    重新获取token命令如下 : 需要在manager节点运行

    #获取一个worker加入集群的token
    docker swarm join-token worker

    实际返回如下

    [root@node01 ~]# docker swarm join-token worker
    To add a worker to this swarm, run the following command:
    
        docker swarm join --token SWMTKN-1-4dklz4o6kibrq5a4xl302yrttl91flc8xzvnkv09v2lh8zxj0e-0sesf1f9etggkfqublpybp7e3 192.168.194.130:2377
  • 新加一个manager节点

    一个集群要有多个manager节点 , 上面加入了work节点 , 接下来在集群中加入一个manager节点 , 加入方式一样的 , 先获取manager的token , 获取token命令如下

     docker swarm join-token manager

    实际运行节点如下

    [root@node01 ~]# docker swarm join-token manager
    To add a manager to this swarm, run the following command:
    
        docker swarm join --token SWMTKN-1-4dklz4o6kibrq5a4xl302yrttl91flc8xzvnkv09v2lh8zxj0e-3a2eml0ryo0iuu0tjzvpma5ca 192.168.194.130:2377

    这里直接将node02以manager角色添加到集群中

4.3 Swarm节点说明

manager与work的权限

swarm集群中 , 只有manager节点可以执行swarm命令(比如docker node ls) , work节点会报错 , 因为只有manager节点才可以管理集群 , 执行集群相关的命令

注 : work节点只是不能执行swarm的集群命令 , 但是docker本身的命令是可以执行的 , 比如docker ps等

  • 节点管理

    可以分别在manager和node中查看节点的swarm信息 , 对比差异

    docker info
    image-20240309181849247
  • 节点可用性与状态说明

    在使用docker node ls命令查看集群的节点信息的时候 , 有两列需要注意一下 : AVAILABILITY , MANAGER STATUS

    image-20240309182036486
    • MANAGER STATUS

      表示manger节点的状态 , work节点为空 , 它也有三个状态值

      • Leader : 该节点是集群管理和编排决策的主要管理器节点。

      • Reachable : 该节点是管理者节点正在参与Raft选举。如果Leader节点不可用 , 则该节点有资格被选为新领导者。

      • Unavailable : 该节点属于不能与其他manager通信的manager。如果manager节点不可用 , 可以将它加入群集 , 或者将工作器节点升级为管理器。

    • AVAILABILITY

      决定当前节点可用性 , 是否用于运容器 , 它有三个值:

      • Active : 调度程序可以将任务分配给当前节点。

      • Pause : 调度程序不会将新任务分配给当前节点 , 但现有任务仍在运行。

      • Drain : 调度程序不会向当前节点分配新任务。调度程序关闭所有现有任务并在可用节点上重新调度这些任务。

      改变节点的可用性(availability)」

      docker node update --availability drain 节点Id/名称

4.4 集群节点管理

  • 节点权限提升/降低

    节点manager和work两种 , 他们的权限不一样 , 我们可以手动的对节点权限提升/降低 , 也是将manager降级为work , 将work升级为manager节点。升级降级的命令都要在manager节点执行。

    • 将work升级为manager节点

      #将worker节点提升为manager节点 , 在manager节点执行如下命令 : 
      docker node promote 节点名称|节点ID

      比如我将node03升级为manager节点

      image-20240309183154770

      可以看到node03的MANAGER STATUS由原本的空变为Reachable

    • 将manager降级为work

      将manager节点降低为worker节点 , 在manager节点执行如下命令 : 
      docker node demote 节点名称|节点ID

      将刚刚升级的node03节点重新降级为worker节点

      image-20240309183703549
  • work脱离集群

    前面演示了怎么给集群中加入节点 , 现在来看看将节点脱离集群

    #在要脱离集群的节点上使用一下命令,主动离开集群,让节点处于`down`状态,才能删除
    docker swarm leave
    #指向完后 , 等一会在manager节点使用命令 : docker node ls  就会发现该节点已经脱离集群管理

    这里我将node03节点脱离集群 ,node03节点中运行命令之后node03的节点状态STATUS由原本的Ready转换为Down

    image-20240309184258237
    image-20240309184340703

    • 删除脱离集群的节点

      上述节点脱离集群后 , 才能删除节点 , 删除节点使用如下命令

      docker node rm 节点名称|节点ID
      image-20240309184646654
    • manager脱离集群

      manager节点不能脱离集群 , 使用docker swarm leave会报错。

      image-20240309184845086

      manager节点不能脱离集群 , 只能强制退出 , 如果实验中两个manager均运行命令退出后意味着整个swarm 不复存在。

      #manager节点强制退出
      docker swarm leave --force

4.5 Docker-swarm命令汇总

  • swarm命令汇总

    命令

    描述

    docker swarm init

    初始化一个 swarm群集

    docker swarm join

    加入群集作为节点或管理器

    docker swarm join-token

    管理用于加入群集的令牌

    docker swarm leave

    离开 swarm 群集

    docker swarm unlock

    解锁 swarm 群集

    docker swarm unlock-key

    管理解锁钥匙

    docker swarm update

    更新 swarm 群集

  • node命令汇总

    命令

    描述

    docker node demote

    从 swarm 群集管理器中降级一个或多个节点

    docker node promote

    将一个或多个节点推入到群集管理器中(也就是升级节点)

    docker node inspect

    显示一个或多个节点的详细信息

    docker node ls

    列出 swarm 群集中的节点

    docker node ps

    列出在一个或多个节点上运行的任务 , 默认为当前节点

    docker node rm

    从 swarm 群集删除一个或多个节点

    docker node update

    更新一个节点

4.6 图形界面

上述安装过程是通过命令行的方式安装docker-swarm , docker-swarm也提供了一个图形界面来操作 , 接下来就来安装一下docker-swarm的图形界面。

docker-swarm的图形界面需要安装在manager节点上 , 不然无法操作节点

#docker官网地址
https://hub.docker.com/r/dockersamples/visualizer
  • 拉取镜像

    [root@node01 ~]# docker pull dockersamples/visualizer:latest
    latest: Pulling from dockersamples/visualizer
    ddad3d7c1e96: Pull complete 
    3a8370f05d5d: Pull complete 
    71a8563b7fea: Pull complete 
    119c7e14957d: Pull complete 
    28bdf67d9c0d: Pull complete 
    12571b9c0c9e: Pull complete 
    e1bd03793962: Pull complete 
    3ab99c5ebb8e: Pull complete 
    94993ebc295c: Pull complete 
    021a328e5f7b: Pull complete 
    Digest: sha256:530c863672e7830d7560483df66beb4cbbcd375a9f3ec174ff5376616686a619
    Status: Downloaded newer image for dockersamples/visualizer:latest
    docker.io/dockersamples/visualizer:latest
  • 运行镜像

    [root@node01 ~]# docker run -itd --name visualizer -p 8099:8080 -e HOST=192.168.194.130 -e PORT=8080 -v /var/run/docker.sock:/var/run/docker.sock dockersamples/visualizer:latest
    c89b86725043752110add7ae663ddfc746cea48fb4e8a108d21cc95b38c6ddfd
  • 访问图形界面

    http://192.168.194.130:8099/
    image-20240309190425524

5. Docker Service

docker-service是指一组任务的集合 , 服务定义了任务的属性 , 比如任务的个数、服务策略、镜像的版本号等 , 服务有两种模式 :

  • replicated services : 按照一定规则在各个工作节点上运行指定个数的任务

  • global services : 每个工作节点上运行一个任务

docker-swarm-8

5.1 部署nginx

接下来以前面做的Nginx镜像为例 , 分别在几个节点上部署Nginx任务

  • 创建nginx网络

    在manager节点中创建overlay网络

    docker network create -d overlay nginx-net
    image-20240309191235642

  • 部署nginx服务

    在集群中创建5个Nginx服务 , 在manager节点中执行 , 使用docker service create命令

    # --network nginx-net 使用刚刚创建的网络
    # replicas 7 代表 7个副本服务
    # --name nginxsvc 表示创建的service名称
    docker service create --name nginxsvc --network nginx-net -p 8888:80 --replicas 7 192.168.194.130/library/centos-nginx:v1
    
    #[root@node01 ~]# docker service create --name nginxsvc  -p 8888-8890:80/tcp --replicas 7 192.168.194.130/library/centos-nginx:v1
    p3ou73kgugo9jnxau8ip2slri
    overall progress: 7 out of 7 tasks 
    1/7: running   [==================================================>] 
    2/7: running   [==================================================>] 
    3/7: running   [==================================================>] 
    4/7: running   [==================================================>] 
    5/7: running   [==================================================>] 
    6/7: running   [==================================================>] 
    7/7: running   [==================================================>] 
    verify: Service converged 
    如果直接使用-p 实际整体可以直接使用宿主机范围端口映射到容器中
    • 界面查看

      image-20240309194700050
    • manager节点也可以查看

      [root@node01 ~]# docker service ls
      ID             NAME       MODE         REPLICAS   IMAGE                                     PORTS
      c5a67c4cb9lp   nginxsvc   replicated   7/7        192.168.194.130/library/centos-nginx:v1   *:8888->80/tcp
    • 访问nginx

      [root@node01 ~]# curl 192.168.194.130:8888 
      nginx is running!!!! v1 
      [root@node01 ~]# curl 192.168.194.145:8888 
      nginx is running!!!! v1 
      [root@node01 ~]# curl 192.168.194.146:8888 
      nginx is running!!!! v1 
  • 剔除manager中非服务

    前面说manager节点只用于管理集群 , 一般不部署服务 , 而在上面图形界面中显示 , manager中有三个服务 , 如果要剔除 , 可以执行以下命令

    docker node update --availability drain 节点Id|名称

    实际使用如下

    [root@node01 ~]# docker node update --availability drain node01
    node01
    [root@node01 ~]# docker node ls
    ID                            HOSTNAME   STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
    qifjd0vdje4l85wsjr64wq8w0 *   node01     Ready     Drain          Leader           25.0.4
    cmug0o7mqdu339vhwaow3556b     node02     Ready     Active                          25.0.4
    54s2su2q27kfx6w8ypuhcnua2     node03     Ready     Active                          25.0.4
    image-20240309195615524
  • 服务的缩容与扩容

    目前是在两个work中部署了7个nginx,如果要扩容与缩容,只需要修改service的数量就可以无感扩容与缩容,执行一下命令

    #将nginx服务从七个减到5
    [root@node01 ~]# docker service scale nginxsvc=5
    nginxsvc scaled to 5
    overall progress: 5 out of 5 tasks 
    1/5: running   [==================================================>] 
    2/5: running   [==================================================>] 
    3/5: running   [==================================================>] 
    4/5: running   [==================================================>] 
    5/5: running   [==================================================>] 
    verify: Service converged 
    [root@node01 ~]# docker service ls
    ID             NAME       MODE         REPLICAS   IMAGE                                     PORTS
    c5a67c4cb9lp   nginxsvc   replicated   5/5        192.168.194.130/library/centos-nginx:v1   *:8888->80/tcp
    image-20240309200037476

5.2 升级nginx

在我们日常开发中,版本迭代是非常常见的,可能一周、一个月就迭代一个版本,那么版本迭代升级应该怎么做呢,接下来我们将nginx从v1升级到v2。镜像已经在前面步骤准备好了

  • 升级Nginx

    升级过程中主要使用命令:docker service update

    • --public-add : 将服务中的容器,添加新的映射网口

    • --public-rm: 删除指定的映射端口

    • --image : 指定升级之后的镜像

    • --update-delay duration : 设置两次升级之间的时间间隔(ns|us|ms|s|m|h)

    • --update-parallelism uint : 设置同时升级过程中的最大task数量

    [root@node01 ~]# docker service update --publish-add 8889:80 --image 192.168.194.130/library/centos-nginx:v2 nginxsvc
    nginxsvc
    overall progress: 5 out of 5 tasks 
    1/5: running   [==================================================>] 
    2/5: running   [==================================================>] 
    3/5: running   [==================================================>] 
    4/5: running   [==================================================>] 
    5/5: running   [==================================================>] 
    verify: Service converged 
    [root@node01 ~]# curl 192.168.194.130:8889 
    nginx is running!!!! v2
    [root@node01 ~]# curl 192.168.194.130:8888
    nginx is running!!!! v2
    [root@node01 ~]# curl 192.168.194.145:8888
    nginx is running!!!! v2
    [root@node01 ~]# curl 192.168.194.145:8889
    nginx is running!!!! v2
    [root@node01 ~]# curl 192.168.194.146:8889
    nginx is running!!!! v2
    [root@node01 ~]# curl 192.168.194.146:8888
    nginx is running!!!! v2
    [root@node01 ~]# docker service ls
    ID             NAME       MODE         REPLICAS   IMAGE                                     PORTS
    c5a67c4cb9lp   nginxsvc   replicated   5/5        192.168.194.130/library/centos-nginx:v2   *:8888-8889->80/tcp
  • 添加一个新的对外端口

    [root@node01 ~]# docker service update --publish-add 8890:80 nginxsvc
    nginxsvc
    overall progress: 5 out of 5 tasks 
    1/5: running   [==================================================>] 
    2/5: running   [==================================================>] 
    3/5: running   [==================================================>] 
    4/5: running   [==================================================>] 
    5/5: running   [==================================================>] 
    verify: Service converged 

    测试8890是否可以访问

    [root@node01 ~]# curl 192.168.194.130:8890
    nginx is running!!!! v2

    这里发现node01是manager节点,没有部署nginx也可以访问,这个是因为之前创建的network帮助我们转发的

5.3 删除nginx服务

  • 删除nginx服务:docker service rm

    [root@node01 ~]# docker service ls
    ID             NAME       MODE         REPLICAS   IMAGE                                     PORTS
    p3ou73kgugo9   nginxsvc   replicated   7/7        192.168.194.130/library/centos-nginx:v1   *:8888-8890->80/tcp
    [root@node01 ~]# docker service rm nginxsvc
    nginxsvc
    [root@node01 ~]# docker service ls
    ID        NAME      MODE      REPLICAS   IMAGE     PORTS
  • 删除之前创建的nginx-net

    docker network rm nginx-net

5.4 Docker service 命令汇总

命令

描述

docker service create

创建服务

docker service inspect

显示一个或多个服务的详细信息

docker service logs

获取服务的日志

docker service ls

列出服务

docker service rm

删除一个或多个服务

docker service scale

设置服务的实例数量

docker service update

更新服务

docker service rollback

恢复服务至update之前的配置

docker service ps

查看指定服务中的task

6. Docker-stack

6.1 Docker-stack的使用

Stack是一组Service,和docker-compose类似,它也可以通过yml的将一组service放在一起操作,docker stack命令可以方便地操作一个Stack,而不用一个个地操作Service

默认情况下,一个Stack共用一个Network,相互可访问,与其它Stack网络隔绝

下面还是以上面的nginx集群为例,通过docker stack来构建集群

  • 编写docker-stack.yml文件

    docker stack文件的语法基本与docker-compose 类似,

    #版本写高一点,不支持 1 2
    version:'3'
    services:
      edwin-nginx:
        image: 192.168.194.130/library/centos-nginx:v1
        container_name: edwin-nginx
        # 指定一个网络
        networks:
          - edwin-net
        restart: always
        ports:
          - 8888-8890:80
        deploy:
          replicas: 7
    # 创建nginx网络 networks中也可以不指定driver:overlay,因为docker swarm默认网络类型是overlay。
    networks:
      edwin-net:
        driver: overlay

    可以使用命令docker stack config -f docker-stack.yml 配置文件是否书写正常

  • 启动镜像

    在manager节点中创建docker-stack.yml文件。执行如下命令 :

    #nginx-stack 是stack的名字
    docker stack deploy nginx-stack --compose-file=docker-stack.yml 
    #或者是
    docker stack deploy nginx-stack -c docker-stack.yml
    
    [root@node01 ~]# docker stack deploy nginx-stack --compose-file=docker-stack.yml 
    Ignoring unsupported options: restart
    
    Ignoring deprecated options:
    
    container_name: Setting the container name is not supported.
    
    Creating network nginx-stack_edwin-net
    Creating service nginx-stack_edwin-nginx

    image-20240309210634458
  • 查看stack服务

    [root@node01 ~]# docker stack services nginx-stack
    ID             NAME                      MODE         REPLICAS   IMAGE                                     PORTS
    m27utgiz4tx1   nginx-stack_edwin-nginx   replicated   7/7        192.168.194.130/library/centos-nginx:v1   *:8888-8890->80/tcp
  • 查看运行的节点

    查看7个nginx-stack容器分别运行在哪个节点中,可以通过以下命令

    [root@node01 ~]# docker service ls
    ID             NAME                      MODE         REPLICAS   IMAGE                                     PORTS
    m27utgiz4tx1   nginx-stack_edwin-nginx   replicated   7/7        192.168.194.130/library/centos-nginx:v1   *:8888-8890->80/tcp
    [root@node01 ~]# docker service ps nginx-stack_edwin-nginx
    ID             NAME                        IMAGE                                     NODE      DESIRED STATE   CURRENT STATE           ERROR     PORTS
    1d2wwzgj8t08   nginx-stack_edwin-nginx.1   192.168.194.130/library/centos-nginx:v1   node01    Running         Running 3 minutes ago             
    o0ussxgua7hf   nginx-stack_edwin-nginx.2   192.168.194.130/library/centos-nginx:v1   node03    Running         Running 3 minutes ago             
    idekj9an8hcj   nginx-stack_edwin-nginx.3   192.168.194.130/library/centos-nginx:v1   node02    Running         Running 3 minutes ago             
    vel00u4gd8zm   nginx-stack_edwin-nginx.4   192.168.194.130/library/centos-nginx:v1   node02    Running         Running 3 minutes ago             
    olpzg5yqu978   nginx-stack_edwin-nginx.5   192.168.194.130/library/centos-nginx:v1   node01    Running         Running 3 minutes ago             
    buj0pxbb3stf   nginx-stack_edwin-nginx.6   192.168.194.130/library/centos-nginx:v1   node03    Running         Running 3 minutes ago             
    fouzljdfxz87   nginx-stack_edwin-nginx.7   192.168.194.130/library/centos-nginx:v1   node02    Running         Running 3 minutes ago             
    
    [root@node01 ~]# docker stack ps nginx-stack
    ID             NAME                        IMAGE                                     NODE      DESIRED STATE   CURRENT STATE           ERROR     PORTS
    1d2wwzgj8t08   nginx-stack_edwin-nginx.1   192.168.194.130/library/centos-nginx:v1   node01    Running         Running 5 minutes ago             
    o0ussxgua7hf   nginx-stack_edwin-nginx.2   192.168.194.130/library/centos-nginx:v1   node03    Running         Running 5 minutes ago             
    idekj9an8hcj   nginx-stack_edwin-nginx.3   192.168.194.130/library/centos-nginx:v1   node02    Running         Running 5 minutes ago             
    vel00u4gd8zm   nginx-stack_edwin-nginx.4   192.168.194.130/library/centos-nginx:v1   node02    Running         Running 5 minutes ago             
    olpzg5yqu978   nginx-stack_edwin-nginx.5   192.168.194.130/library/centos-nginx:v1   node01    Running         Running 5 minutes ago             
    buj0pxbb3stf   nginx-stack_edwin-nginx.6   192.168.194.130/library/centos-nginx:v1   node03    Running         Running 5 minutes ago             
    fouzljdfxz87   nginx-stack_edwin-nginx.7   192.168.194.130/library/centos-nginx:v1   node02    Running         Running 5 minutes ago       
  • 删除stack服务

    docker stack rm nginx-stack

6.2 docker-stack命令汇总

命令

描述

docker stack deploy

部署新的stack或更新现有stack

docker stack ls

列出现有stack

docker stack ps

列出stack中的任务

docker stack rm

删除一个或多个stack

docker stack services

列出stack中的服务

6.3 Docker Stack和Docker Compose区别

  • Docker stack没有构建指令,无法使用stack命令构建新镜像,需要镜像是预先准备镜像。 docker-compose可以直接构建镜像,所以docker-compose更适合于开发场景;

  • Docker Compose是Python写的,需要安装,Docker Stack是swarm mode的一部分,包含在Docker引擎中

  • Docker stack不支持version版本为3以下的yml

  • Docker stack的功能基本上包含了docker compose。

6.4 其他可用docker stack yml展示

version: "3"

services:
  nginx:
    image: nginx:alpine
    ports:
      - 80:80
    deploy:
      mode: replicated
      replicas: 4
      
  visualizer: 
    image: dockersamples/visualizer
    ports:
      - "9001:8080"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
    deploy:
      replicas: 1
      placement:
        constraints: [node.role == manager]
        
  portainer:
    image: portainer/portainer
    ports:
      - "9000:9000"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
    deploy:
      replicas: 1
      placement:
        constraints: [node.role == manager]

7. Docker-Task

Task是Swarm集群中的最小的调度单位,任务包含一个Docker容器和在容器内运行的命令,如果某一个任务奔溃,那么协调器将创建一个新的副本任务,该任务将生成一个新的容器。

docker-swarm-9

Task调度主要分为Manager节点的任务分配和Worker节点的任务执行两部分

  • Manager节点的任务分配

    • 通过Docker Engine Client在manage节点使用命令docker service create提交Service定义

    • Manager节点根据定义创建相应的Task,并分配IP地址

    • 将Task分发到对应的节点上

    • 节点进行相应的初始化使得它可以执行Task

  • Worker节点的任务执行

    • 连接Manager节点的分配器检查该Task相关定义的信息

    • 验证通过以后在 Worker 节点上执行Task

Task的执行是一种单向机制,它会按顺序的依次经历 assigned, prepared 和 running 等执行状态,如果Task执行失败了,Manager的编排器会直接将该 Task 以及它的 Container 给删除掉,然后在其它节点上另外创建并执行该 Task

8. Docker Swarm使用nfs镜像

8.1 准备NFS环境

  • 安装nfs环境 ,沿用第4节环境,在node02节点中安装nfs服务。所有节点均需要安装nfs-utils软件包,以便客户端可以正常访问nfs

    [root@node01 ~]# yum install nfs-utils
    [root@node02 ~]# yum install nfs-utils
    [root@node03 ~]# yum install nfs-utils
  • 修改node02节点nfs配置文件

    [root@node02 ~]# mkdir /data
    [root@node02 ~]# cat /etc/exports
    /data  *(rw,sync,no_root_squash)
  • 启动nfs服务

    [root@node02 ~]# systemctl start nfs

8.2 手动创建docker service方式

  • 手动创建docker volume ,可以参考docker volume create | Docker Docs 。手动发布服务时需要在集群中每台主机添加volume

    
    [root@node01 ~]#  docker volume create --driver local --opt type=nfs --opt o=addr=192.168.194.145,rw --opt device=:/data smartgovolume1
    smartgovolume1
    
    [root@node01 ~]# docker volume inspect smartgovolume1
    [
        {
            "CreatedAt": "2024-03-10T21:43:43+08:00",
            "Driver": "local",
            "Labels": null,
            "Mountpoint": "/var/lib/docker/volumes/smartgovolume1/_data",
            "Name": "smartgovolume1",
            "Options": {
                "device": ":/data",
                "o": "addr=192.168.194.145,rw",
                "type": "nfs"
            },
            "Scope": "local"
        }
    ]
    
    
    [root@node02 ~]# docker volume create --driver local --opt type=nfs --opt o=addr=192.168.194.145,rw --opt device=:/data smartgovolume1
    smartgovolume1
    
    
    [root@node03 ~]# docker volume create --driver local --opt type=nfs --opt o=addr=192.168.194.145,rw --opt device=:/data smartgovolume1
    smartgovolume1
    
    
  • 使用docker service发布服务时使用volume

    [root@node01 ~]# docker service create --replicas 3 --publish 8888:80 --mount "type=volume,source=smartgovolume1,target=/usr/share/nginx/html/" --name cnginxsvc-volume-test 192.168.194.130/library/centos-nginx:v1wu5tuv6j114ndpb260pnel5aj
    overall progress: 3 out of 3 tasks 
    1/3: running   [==================================================>] 
    2/3: running   [==================================================>] 
    3/3: running   [==================================================>] 
    verify: Service converged 
  • 测试页面是否可以访问

    [root@node02 ~]# echo "node02 nfs volume test" > /data/index.html
    
    [root@node01 ~]# curl 192.168.194.130:8888
    node02 nfs volume test
    [root@node01 ~]# curl 192.168.194.145:8888
    node02 nfs volume test
    [root@node01 ~]# curl 192.168.194.146:8888
    [root@node01 ~]# curl 192.168.194.146:8888
    node02 nfs volume test
    
    
    [root@node02 ~]# echo "AAAA" > /data/index.html
    
    [root@node01 ~]# curl 192.168.194.146:8888
    AAAA
    [root@node01 ~]# curl 192.168.194.130:8888
    AAAA
    [root@node01 ~]# curl 192.168.194.145:8888
    AAAA
    
    [root@node01 ~]# docker service ls
    ID             NAME                    MODE         REPLICAS   IMAGE                                     PORTS
    ln6ocori3etr   cnginxsvc-volume-test   replicated   3/3        192.168.194.130/library/centos-nginx:v1   *:8888->80/tcp
    [root@node01 ~]# docker service ps ln
    ID             NAME                      IMAGE                                     NODE      DESIRED STATE   CURRENT STATE           ERROR     PORTS
    wwz363d5f46q   cnginxsvc-volume-test.1   192.168.194.130/library/centos-nginx:v1   node03    Running         Running 4 minutes ago             
    hjeyib21rtex   cnginxsvc-volume-test.2   192.168.194.130/library/centos-nginx:v1   node02    Running         Running 4 minutes ago             
    7cle9j9hisl3   cnginxsvc-volume-test.3   192.168.194.130/library/centos-nginx:v1   node01    Running         Running 4 minutes ago           

8.3 使用编排方式发布

  • 准备编排文件

    [root@node01 ~]# cat docker-stack-2.yml 
    version: '3.12'
    
    services:
      cnginxsvc:
        image: 192.168.194.130/library/centos-nginx:v1
        deploy:
          mode: replicated
          replicas: 3
          restart_policy:
            condition: on-failure
        ports:
          - "8888:80"
        volumes:
          - "smartgovolume1:/usr/share/nginx/html/"
    
    
    volumes:
      smartgovolume1:
        driver: local
        driver_opts:
          type: "nfs"
          "o": "addr=192.168.194.145,rw"
          device: ":/data/"
  • 发布服务

    [root@node01 ~]# docker stack deploy -c docker-stack-2.yml  nginx-stack
    Creating network nginx-stack_default
    Creating service nginx-stack_cnginxsvc
    [root@node01 ~]# docker stack ps  nginx-stack
    ID             NAME                      IMAGE                                     NODE      DESIRED STATE   CURRENT STATE           ERROR     PORTS
    pcg5vxnuscmi   nginx-stack_cnginxsvc.1   192.168.194.130/library/centos-nginx:v1   node01    Running         Running 4 seconds ago             
    njgg47rscs7n   nginx-stack_cnginxsvc.2   192.168.194.130/library/centos-nginx:v1   node03    Running         Running 4 seconds ago             
    qdtv9cbuadmo   nginx-stack_cnginxsvc.3   192.168.194.130/library/centos-nginx:v1   node02    Running         Running 4 seconds ago             
    
    [root@node01 ~]# docker stack services  nginx-stack
    ID             NAME                    MODE         REPLICAS   IMAGE                                     PORTS
    p987vxtwjn6b   nginx-stack_cnginxsvc   replicated   3/3        192.168.194.130/library/centos-nginx:v1   *:8888->80/tcp
    
    #每个节点会生成一个volume ,在stack如果删除之后,该volume不会删除, 重新部署stack时,需要手动删除该volume
    [root@node01 ~]# docker volume ls
    DRIVER    VOLUME NAME
    local     nginx-stack_smartgovolume1
    
    [root@node02 ~]# docker volume ls 
    DRIVER    VOLUME NAME
    local     nginx-stack_smartgovolume1
    
    [root@node03 ~]# docker volume ls 
    DRIVER    VOLUME NAME
    local     nginx-stack_smartgovolume1
    

    之后直接测试访问即可


参考链接

Docker学习系列 —— 13. Docker swarm集群详解 ( 一 ) (qq.com)

Docker-Swarm集群管理 (qq.com)

Docker三剑客之Swarm (qq.com)

docker-swarm 教程 : 服务管理篇 (qq.com)

Docker Swarm 使用NFS数据共享 - 简书 (jianshu.com)