2-9-Docker-Swarm
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 ComposeDocker Swarm和Docker Compose都是Docker官方容器编排项目Docker Compose是一个在单个服务器或主机上创建多个容器的工具 , 可以将组成某个应该的多个docker容器编排在一起 , 同时管理。
Docker Swarm则可以在多个服务器或主机上创建容器集群服务 , 其主要作用是把若干台Docker主机抽象为一个整体 , 并且通过一个入口 (docker stack) 统一管理这些Docker主机上的各种Docker资源。
docker stackdocker stack是构成特定环境中的service集合, 它是自动部署多个相互关联的服务的简便方法 , 而无需单独定义每个服务。stack file是一种yaml格式的文件 , 类似于docker-compose.yml文件 , 它定义了一个或多个服务 , 并定义了服务的环境变量、部署标签、容器数量以及相关的环境特定配置等。
Docker Swarm就是用来管理Docker集群的 , 但是现在基本上使用的很少 , 一般都是用的K8S,学习K8S之前可以先学习一个Docker Swarm , 将其作为一个容器编排的一个学习基础 , 了解一下即可。
Swarm的基本架构如下图所示

这个图作为一个整体实际上都处于一个所谓的集群中 , 它可能对应了一到多台的实际服务器。每台服务器上都装有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) 下发至工作节点执行。管理节点默认也作为工作节点。你也可以通过配置让服务只运行在管理节点。下图展示了集群中管理节点与工作节点的关系
服务和任务
任务(
Task) 是Swarm中的最小的调度单位 , 目前来说就是一个单一的容器。 服务 (Services) 是指一组任务的集合 , 服务定义了任务的属性。服务有两种模式 :replicated services: 按照一定规则在各个工作节点上运行指定个数的任务。global services: 每个工作节点上运行一个任务
两种模式通过
docker service create的--mode参数指定。下图展示了容器、任务、服务的关系。
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的状态通知到管理节点以维护节点的状态信息。

管理节点(
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数量在
globalservice模式 ,swarm集群会向每个可用的节点运行tasks。

如上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 环境准备
环境说明
配置私有仓库(
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节点查看网络情况 , 新增了一个用于集群的网络

其他节点以
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
节点可用性与状态说明
在使用
docker node ls命令查看集群的节点信息的时候 , 有两列需要注意一下 :AVAILABILITY,MANAGER STATUS
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节点
可以看到
node03的MANAGER STATUS由原本的空变为Reachable将
manager降级为work将manager节点降低为worker节点 , 在manager节点执行如下命令 : docker node demote 节点名称|节点ID将刚刚升级的
node03节点重新降级为worker节点
work脱离集群前面演示了怎么给集群中加入节点 , 现在来看看将节点脱离集群
#在要脱离集群的节点上使用一下命令,主动离开集群,让节点处于`down`状态,才能删除 docker swarm leave #指向完后 , 等一会在manager节点使用命令 : docker node ls 就会发现该节点已经脱离集群管理这里我将
node03节点脱离集群 ,node03节点中运行命令之后node03的节点状态STATUS由原本的Ready转换为Down

删除脱离集群的节点
上述节点脱离集群后 , 才能删除节点 , 删除节点使用如下命令
docker node rm 节点名称|节点ID
manager脱离集群manager节点不能脱离集群 , 使用docker swarm leave会报错。
manager节点不能脱离集群 , 只能强制退出 , 如果实验中两个manager均运行命令退出后意味着整个swarm不复存在。#manager节点强制退出 docker swarm leave --force
4.5 Docker-swarm命令汇总
swarm命令汇总node命令汇总
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/
5. Docker Service
docker-service是指一组任务的集合 , 服务定义了任务的属性 , 比如任务的个数、服务策略、镜像的版本号等 , 服务有两种模式 :
replicated services: 按照一定规则在各个工作节点上运行指定个数的任务global services: 每个工作节点上运行一个任务

5.1 部署nginx
接下来以前面做的Nginx镜像为例 , 分别在几个节点上部署Nginx任务
创建
nginx网络在
manager节点中创建overlay网络docker network create -d overlay nginx-net
部署
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 实际整体可以直接使用宿主机范围端口映射到容器中界面查看

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
服务的缩容与扩容
目前是在两个
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
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-netdocker network rm nginx-net
5.4 Docker service 命令汇总
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
查看
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命令汇总
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以下的ymlDocker 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容器和在容器内运行的命令,如果某一个任务奔溃,那么协调器将创建一个新的副本任务,该任务将生成一个新的容器。

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 使用NFS数据共享 - 简书 (jianshu.com)