一、Docker Swarm介绍
Docker Swarm是Docker的集群管理工具,它提供了标准的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 则可以在多个服务器或主机上创建容器集群服务,其主要作用是把若干台Docker主机抽象为一个整体,并且通过一个入口(docker stack)统一管理这些Docker主机上的各种Docker资源。
-
-
docker stack
- docker stack 是构成特定环境中的 service 集合, 它是自动部署多个相互关联的服务的简便方法,而无需单独定 义每个服务。
- stack file 是一种 yaml 格式的文件,类似于 docker-compose.yml 文件,它定义了一个或多个服务,并 定义了服务的环境变量、部署标签、容器数量以及相关的环境特定配置等。
Docker Swarm就是用来管理Docker集群的,但是现在基本上使用的很少,一般都是用的K8S,学习K8S之前可以先学习一个Docker Swarm,将其作为一个容器编排的一个学习基础,了解一下即可
二、Docker Swarm运行原理
Swarm集群由多个运行在swarm mode的docker主机组成,docker主机分为管理节点(manager)和工作节点(work node)两种类型
-
管理节点(manager):负责整个集群的管理工作包括集群配置、服务管理,服务的创建和调度等
-
工作节点(work node):负责运行相应的服务来执行任务(运行容器服务)
manager节点也可以运行的容器服务,但是一般不这么做,只是让它管理work node
Swarm集群的优点:
- 在线修改Service的配置,包括networks和volumes,不需要重启docker服务
- 可以将其它standalone模式的docker主机加入到Swarm集群
Standalone模式简单点说就是 manager 和 work 的一种管理关系模式
在Docker Swarm中有几个基本概念:nodes、Service、tasks、load balancing。需要简单了解一下
2.1 nodes
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:
- 维护cluster state
- scheduling服务
- service swarm mode集群服务
-
工作节点(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指做管理)
docker node promote 复制代码
通过以上命令可以修改节点模式,将worker节点变为manager节点,也可以将manager节点转换为worker节点。
2.1 Service与tasks
Service是manage和work节点上执行的task的定义,创建service的时候可以指定使用哪个container image以及执行的命令。
当Service部署到Swarm集群的时候,swarm管理节点会将service为标准(container image以及执行的命令),然后将service调度到集群的节点上,以一个或多个tasks执行,这些nodes上运行的tasks之间是相互独立的。
- 在replicated service模式下,swarm管理节点会根据desired state中设置的scale分发replica tasks
- 在globalservice模式,swarm集群会向每个可用的节点运行tasks
如上service中有三个replicas tasks,每个实例是Swarm集群中的一个task。
Task是Swarm集群中调度的最小单元,当创建或更新service时候给定了desired state,集群会调度tasks来实现这种理想状态。
- Task是一种单向机制,它整个周期过程中会完成一系列的状态(assigned、prepared和running等),tasks运行失败集群会remove这个tasks并创建新的tasks来替代。
2.1 load balancing
负载均衡:Swarm集群使用ingress loading balancing提供集群服务,Swarm集群会自动为service分配PublishedPort,默认使用30000-32767范围。
三、Docker-swarm安装部署
3.1 准备工作
-
官方地址
https://docs.docker.com/engine/swarm/ 复制代码
-
添加私服仓库地址
由于官方镜像下载比较慢,由于网络原因可能拉取不下来,而集群的每个节点都需要安装镜像,所以使用私有仓库会快很多,当然也可以不使用私有仓库,直接自己下载上传。
#编辑配置文件 vi /etc/docker/daemon.json #增加仓库配置信息 # 在daemon.json中添加以下 key,保存退出。此步用于让 docker 信任私有仓库地址 {"insecure-registries":["192.168.242.130:5000"]} #重新加载docker配置 systemctl daemon-reload #重启docker systemctl restart docker 复制代码
3.2 docker-swarm安装
这里模拟安装集群,以三个节点搭建集群在加上一个Harbor节点,节点信息如下
节点 | Ip | 说明 |
---|---|---|
manager-01 | 192.168.242.131 | swarm-manager 节点 |
work-01 | 192.168.242.132 | swarm-work节点 |
work-02 | 192.168.242.133 | swarm-work节点 |
harbor | 192.168.242.130 | harbor 私服 |
安装上述配置,克隆出相应的虚拟机,其中harbor之前已经存在,这里用之前的,所以一共克隆出三个服务器
-
查看网络情况
docker network ls 复制代码
-
初始化manager管理节点
-
语法
docker swarm init 复制代码
-
参数说明
这个命令需要指定两个参数--advertise-addr 与--listen-addr
- --advertise-addr:指定其他节点连接manager时的地址
- --listen-addr:监控swarm集群manager的IP和端口
初始化manager管理节点完整命令如下
#这里使用192.168.242.131这台主机作为manager 所以以下命令在192.168.242.131上执行 端口默认是2377 docker swarm init --advertise-addr 192.168.242.131:2377 --listen-addr 192.168.242.131:2377 复制代码
执行上面命令后,就会初始化swarm集群,并且会告诉我们如何增加wrok 节点和manager节点
-
再次查看网络情况
#集群初始化后会新增集群网络 docker network ls 复制代码
-
-
查看节点
docker node ls 复制代码
-
新加一个work节点
通过上面初始化manager返回的命令,给集群加入新的节点,只需要在对应的主机上执行该命令即可
docker swarm join --token SWMTKN-1-55wujoaco7zp7kdvot57wu15drul4m3svoifnitz69r6jv2xyj-5o009d6f4oxlnahfwfzke5ukj 192.168.242.131:2377 复制代码
我在192.168.242.132这台主机上执行上述命令,将其加入到集群中
这个命令本质上就是manager初始化的时候返回了一个token,其他主机通过这个token加入集群,并且token只有24小时。如果失效,则需要重新获取
-
重新获取token
#获取一个worker加入集群的token docker swarm join-token worker 复制代码
-
-
查看节点
docker node ls 复制代码
-
新加一个manager节点
一个集群要有多个manager节点,上面加入了work节点,接下来在集群中加入一个manager节点,加入方式一样的,先获取manager的token
-
获取manager节点的token
#获取一个manager加入集群的token ,这个命令要在之前的那个manager 192.168.242.131 上执行 docker swarm join-token manager 复制代码
-
加入集群
这里就用 192.168.242.133 这个主机作为一个manager加入集群
-
3.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
-
AVAILABILITY
决定当前节点可用性,是否用于运容器,它有三个值:
- Active:调度程序可以将任务分配给当前节点。
- Pause:调度程序不会将新任务分配给当前节点,但现有任务仍在运行。
- Drain:调度程序不会向当前节点分配新任务。调度程序关闭所有现有任务并在可用节点上重新调度这些任务。
改变节点的可用性(availability)
docker node update --availability drain 节点Id/名称 复制代码
-
MANAGER STATUS
表示manger节点的状态,work节点为空,它也有三个状态值
- Leader:该节点是集群管理和编排决策的主要管理器节点。
- Reachable:该节点是管理者节点正在参与Raft选举。如果Leader节点不可用,则该节点有资格被选为新领导者。
- Unavailable:该节点属于不能与其他manager通信的manager。如果manager节点不可用,可以将它加入群集,或者将工作器节点升级为管理器。
-
3.4 集群节点管理
-
节点权限提升/降低
节点manager和work两种,他们的权限不一样,我们可以手动的对节点权限提升/降低,也是将manager降级为work,将work升级为manager节点。升级降级的命令都要在manager节点执行。
-
将work升级为manager节点
#将worker节点提升为manager节点,在manager节点执行如下命令: docker node promote 节点名称|节点ID 复制代码
比如我将132 节点升级为manager节点
-
将manager降级为work
将manager节点降低为worker节点,在manager节点执行如下命令: docker node demote 节点名称|节点ID docker node ls 复制代码
将刚刚升级的132 节点重新降级为worker节点
-
-
work脱离集群
前面演示了怎么给集群中加入节点,现在来看看将节点脱离集群
#在要脱离集群的节点上使用一下命令, 主动离开集群,让节点处于down状态,才能删除 docker swarm leave #指向完后,等一会在manager节点使用命令:docker node ls 就会发现该节点已经脱离集群管理 复制代码
这里我将132节点脱离集群
-
删除脱离集群的节点
上述节点脱离集群后,才能删除节点,删除节点使用如下命令
docker node rm 节点名称|节点ID 复制代码
-
manager脱离集群
manager节点不能脱离集群,使用docker swarm leave会报错。
manager节点不能脱离集群,只能强制退出,manager退出后意味着整个swarm 不复存在。
#manager节点强制退出 docker swarm leave --force 复制代码
3.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 更新一个节点
四、图形界面
上述安装过程是通过命令行的方式安装docker-swarm,docker-swarm也提供了一个图形界面来操作,接下来就来安装一下docker-swarm的图形界面。
docker-swarm的图形界面需要安装在manager节点上,不然无法操作节点
#docker官网地址
https://hub.docker.com/r/dockersamples/visualizer
复制代码
-
拉取镜像
docker pull dockersamples/visualizer:latest 复制代码
-
备份镜像
备份镜像有两种方式:私服和tar包。
-
tar包
镜像拉取下来之后,可以把它打成一个tar,保存起来,后面使用的时候直接还原即可,就不用下载了
#打成一个tar 包 docker save dockersamples/visualizer:latest -o dockersamples.visualizer.tar #需要用的时候还原成镜像 docker load -i dockersamples.visualizer.tar 复制代码
-
私服
除了打成tar 存在本地之外,还可以将镜像上传私服,以后在私服拉取
# 1、标记镜像打一个tag docker tag dockersamples/visualizer:latest 192.168.242.130:5000/edwinedu/dockersamples/visualizer:latest # 2、上传标记的镜像 上传之前要先登录 docker login -u admin -p Harbor12345 192.168.242.130:5000 docker push 192.168.242.130:5000/edwinedu/dockersamples/visualizer:latest 复制代码
-
-
运行镜像
# /var/run/docker.sock 是必须要的挂载目录 HOST是指定Ip,需要是manager节点的Ip docker run -itd --name visualizer -p 8099:8080 -e HOST=192.168.198.131 -e PORT=8080 -v /var/run/docker.sock:/var/run/docker.sock 192.168.242.130:5000/edwinedu/dockersamples/visualizer:latest 复制代码
-
访问图形界面
http://192.168.242.131:8099/ 复制代码
五、Docker-service
docker-service 是指一组任务的集合,服务定义了任务的属性,比如任务的个数、服务策略、镜像的版本号等,服务有两种模式:
- replicated services:按照一定规则在各个工作节点上运行指定个数的任务
- global services:每个工作节点上运行一个任务
接下来以Nginx为例,分别在几个节点上部署Nginx任务
5.1 Nginx基础镜像准备
-
拉取Nginx镜像
docker pull nginx:1.18.0-alpine 复制代码
-
备份镜像
由于要在每个节点都安装Nginx,所以需要在每个节点都下载镜像,当然可以使用私服下载,但是这里我不使用私服,练习一个scp命令
#打成一个tar 包 mkdir -p /data/nginx docker save nginx:1.18.0-alpine -o /data/nginx/nginx:1.18.0.tar 复制代码
-
传输镜像
将nginx镜像使用scp 命令传输到192.168.242.132,192.168.242.132两个节点中
#执行下面命令之前,要确保132 133 两个节点有指定的目录 /data/nginx #注意nginx\:1.18.0.tar 中间有一个反斜杠 scp /data/nginx/nginx\:1.18.0.tar root@192.168.242.132:/data/nginx scp /data/nginx/nginx\:1.18.0.tar root@192.168.242.133:/data/nginx 复制代码
-
解压nginx
分别在所有节点中解压nginx (192.168.242.132,192.168.242.132两个节点)
cd /data/nginx docker load -i nginx:1.18.0.tar 复制代码
5.2 部署Nginx
-
创建nginx网络
在manager节点中创建overlay网络
docker network create -d overlay nginx-net 复制代码
-
部署Nginx
在集群中创建7个Nginx服务,在manager节点中执行,使用【docker service create】命令
# --network nginx-net 使用刚刚创建的网络 # replicas 7 代表 7个副本服务 docker service create --name nginx --network nginx-net -p 80:80 --replicas 7 nginx:1.18.0-alpine 复制代码
-
界面查看
-
manager节点也可以查看
docker service ls 复制代码
-
-
访问Nginx
#三台主机都可以访问 http://192.168.242.131/80 http://192.168.242.132/80 http://192.168.242.133/80 复制代码
-
剔除manager中非服务
前面说manager节点只用于管理集群,一般不部署服务,而在上面图形界面中显示,manager中有三个服务,如果要剔除,可以执行以下命令
docker node update --availability drain 节点Id|名称 复制代码
-
服务的缩容与扩容
目前是在两个work中部署了7个nginx,如果要扩容与缩容,只需要修改service的数量就可以无感扩容与缩容,执行一下命令
#将nginx服务从七个减到5 docker service scale nginx=5 复制代码
5.3 升级Nginx
在我们日常开发中,版本迭代是非常常见的,可能一周、一个月就迭代一个版本,那么版本迭代升级应该怎么做呢,接下来我们将nginx从1.18升级到1.19。
-
查看nginx版本
查看nginx版本可以通过容器查看,也可以通过界面查看
#通过容器查看版本,先进入容器中 docker exec -it 503fe639bb89 sh nginx -v #退出容器 exit 复制代码
-
准备nginx:1.19的镜像
跟上面1.18的镜像一样,先在manager节点上拉取镜像,然后scp到132 133两台主机上,生产环境我们可以使用私服拉取镜像,不需要打包,这里只是练习scp命令
#拉取nginx:1.19.3-alpine镜像 docker pull nginx:1.19.3-alpine #打成一个tar 包 mkdir -p /data/nginx docker save nginx:1.19.3-alpine -o /data/nginx/nginx:1.19.3.tar #执行下面命令之前,要确保132 133 两个节点有指定的目录 /data/nginx #注意nginx\:1.18.0.tar 中间有一个反斜杠 scp /data/nginx/nginx\:1.19.3.tar root@192.168.242.132:/data/nginx scp /data/nginx/nginx\:1.19.3.tar root@192.168.242.133:/data/nginx #分别在132 133 主机上执行解压1.19.3.tar cd /data/nginx docker load -i nginx:1.19.3.tar 复制代码
-
升级Nginx
在manager节点执行以下命令,将nginx从1.18.0-alpine升级到1.19.3-alpine
docker service update --image nginx:1.19.3-alpine nginx 复制代码
-
添加一个对外端口
#将8090 也映射到容器的80端口 docker service update --publish-add 8090:80 nginx 复制代码
5.4 删除Nginx服务
-
删除service
docker service rm nginx 复制代码
-
删除之前创建的nginx-net
docker network rm nginx-net 复制代码
5.5 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-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: nginx:1.19.3-alpine container_name: edwin-nginx # 指定一个网络 networks: - edwin-net restart: always ports: - 80:80 deploy: replicas: 7 # 创建nginx网络 networks中也可以不指定driver:overlay,因为docker swarm默认网络类型是overlay。 networks: edwin-net: driver: overlay 复制代码
-
上传docker-stack.yml
将docker-stack.yml上传到manager节点的/data/nginx目录下 复制代码
-
启动镜像
在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 复制代码
-
查看stack服务
docker stack services nginx-stack 复制代码
-
查看运行的节点
查看7个nginx-stack容器分别运行在哪个节点中,可以通过以下命令
# 查看service的服务名为:nginx-stack_edwin-nginx docker service ls #查看7个nginx-stack容器分别运行在哪个节点中 docker service ps nginx-stack_edwin-nginx 复制代码
-
查看的前提是我们要修改各个主机的名字,不然都会显示localhost.localdomain
-
修改主机名字
# 第一步 在各个主机执行 docker-swarm-work-02 为当前主机要设置的主机名 hostnamectl set-hostname docker-swarm-manager-01 #第二步 vi /etc/hosts # 将其中的 localhost.localdomain 替换成 docker-swarm-work-02 127.0.0.1 localhost docker-swarm-work-02 localhost4 localhost4.localdomain4 ::1 localhost docker-swarm-work-02 localhost6 localhost6.localdomain6 #第三步 重启服务器 reboot #第四步 查看hostname hostname 复制代码
-
分别按照上述步骤修改主机名字后,再次查看查看7个nginx-stack容器分别运行在哪个节点中,结果如下
-
-
删除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.2 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。
七、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