从零开始轻松部署Docker Swarm集群

Posted Friends of the wind

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从零开始轻松部署Docker Swarm集群相关的知识,希望对你有一定的参考价值。


理论

Docker Swarm是跨主机的容器集群编排工具,类似于k8s,但是它更小巧,是 Docker 官方容器编排项目,集成在docker不用手动安装。

Swarm Cluster模式特性

1)批量创建服务
建立容器之前先创建一个overlay的网络,用来保证在不同主机上的容器网络互通的网络模式

2)强大的集群的容错性
当容器副本中的其中某个节点宕机后,cluster会根据服务注册发现机制,以及之前设定的值–replicas n,在集群中剩余的空闲节点上,重新拉取容器副本。整个副本迁移的过程无需人工干预,迁移后原本的集群的load balance依旧好使!

不难看出,docker service其实不仅仅是批量启动服务这么简单,而是在集群中定义了一种状态。Cluster会持续检测服务的健康状态并维护集群的高可用性。

3)服务节点的可扩展性
Swarm Cluster不光提供了优秀的高可用性,同时也提供了节点弹性扩展或缩减的功能。当容器组想动态扩展时,只需通过scale参数即可。

仔细观察的话,可以发现所有扩展出来的容器副本都run在原先的节点下面,如果有需求想在每台节点上都run一个相同的副本,方法其实很简单,只需要在命令中将"–replicas n"更换成"–mode=global"即可!

复制服务(–replicas n)
将一系列复制任务分发至各节点当中,具体取决于您所需要的设置状态,例如“–replicas 3”。

全局服务(–mode=global)
适用于集群内全部可用节点上的服务任务,例如“–mode global”。如果大家在 Swarm 集群中设有 7 台 Docker 节点,则全部节点之上都将存在对应容器。

4)调度机制
所谓的调度其主要功能是cluster的server端去选择在哪个节点创建并启动一个容器实例的动作。它是由一个装箱算法和过滤器组合而成。每次通过过滤器(constraint)启动容器的时候,swarm cluster 都会调用调度机制筛选出匹配约束条件的服务器,并在这上面运行容器。


Swarm是典型的master-slave结构,通过发现服务来选举manager。manager是中心管理节点,各个node上运行agent接受manager的统一管理,集群会自动通过Raft协议分布式选举出manager节点,无需额外的发现服务支持,避免了单点的瓶颈问题,同时也内置了DNS的负载均衡和对外部负载均衡机制的集成支持。

Swarm的关键概念

1.Swarm
集群的管理和编排是使用嵌入docker引擎的SwarmKit,可以在docker初始化时启动swarm模式或者加入已存在的swarm

2.Node
一个节点是docker引擎集群的一个实例,可以将其视为Docker节点。
要将应用程序部署到swarm,请将服务定义提交给管理器节点。
管理器节点将称为任务的工作单元分派给工作节点。

Manager节点还执行维护所需群集状态所需的编排和集群管理功能。Manager节点选择单个领导者来执行编排任务。
worker工作节点接收并执行从管理器节点分派的任务。

默认情况下,管理器节点还将服务作为工作节点运行,但您可以将它们配置为仅运行管理器任务并且是仅管理器节点。代理程序在每个工作程序节点上运行,并报告分配给它的任务。工作节点向管理器节点通知其分配的任务的当前状态,以便管理器可以维持每个工作者的期望状态。

3.Service
一个服务是任务的定义,在管理机或工作节点上执行。它是群集系统的中心结构,是用户与群集交互的主要根源。创建服务时,你需要指定要使用的容器镜像。

4.Task
任务是在docekr容器中执行的命令,Manager节点根据指定数量的任务副本分配任务给worker节点

Swarm的调度策略

Swarm在调度(scheduler)节点(leader节点)运行容器的时候,会根据指定的策略来计算最适合运行容器的节点,目前支持的策略有:spread, binpack, random.
1)Random
顾名思义,就是随机选择一个Node来运行容器,一般用作调试用,spread和binpack策略会根据各个节点的可用的CPU, RAM以及正在运行的容器的数量来计算应该运行容器的节点。(类似于摇筛子)

2)Spread
在同等条件下,Spread策略会选择运行容器最少的那台节点来运行新的容器,binpack策略会选择运行容器最集中的那台机器来运行新的节点。使用Spread策略会使得容器会均衡的分布在集群中的各个节点上运行,一旦一个节点挂掉了只会损失少部分的容器。(哪个人的工作任务少,有新任务就分配给他)

3)Binpack
Binpack策略最大化的避免容器碎片化,就是说binpack策略尽可能的把还未使用的节点留给需要更大空间的容器运行,尽可能的把容器运行在一个节点上面。(集中给一个服务器节点分派任务,将空闲留给更需要的服务)


一、Dcoker Swarm 集群环境部署

角色主机名IP
swarm managerdocker01172.16.0.161
swarm workerdocker02172.16.0.162
swarm workerdocker03172.16.0.163

修改主机名
关防火墙和selinux;注意:实验环境,必须保证所有虚拟机是同一种状态的快照,否则,会报错。

二、部署流程

1.创建Swarm集群

docker01操作
[root@docker01 ~]# docker swarm init --advertise-addr 172.16.0.161
正确会有如下提示:

提示:保存初始化后token,因为在节点加入时要使用token作为通讯的密钥

2. 查看集群信息

查看集群详细信息:
[root@docker01 ~]# docker info

查看节点信息:
[root@docker01 ~]# docker node ls

更改节点的availablity状态
swarm集群中node的availability状态可以为 active或者drain,其中:
active:node可以接受来自manager节点的任务分派;
drain:node节点会结束task,且不再接受来自manager节点的任务分派(也就是下线节点)

当node1的状态改为drain后,该节点就不会接受task任务分发,就算之前已经接受的任务也会转移到别的节点上。
再次修改为active状态(及将下线的节点再次上线)

3. 将节点添加到Swarm集群

docker02操作:
docker swarm join --token SWMTKN-1-3l0a35w02f271gw3fhr0rz9jpvbf6sv2122o0bknesolozon02-7swvpjyzwvjim0yd4yyqd0s8g 172.16.0.161:2377

docker03操作:
docker swarm join --token SWMTKN-1-3l0a35w02f271gw3fhr0rz9jpvbf6sv2122o0bknesolozon02-7swvpjyzwvjim0yd4yyqd0s8g 172.16.0.161:2377

4.在Swarm中部署服务(nginx为例)

Docker 1.12版本提供服务的Scaling、health check、滚动升级等功能,并提供了内置的dns、vip机制,实现service的服务发现和负载均衡能力

1)创建网络并部署服务
[root@docker01 ~]# docker network create -d overlay nginx_net

部署服务
创建一个具有一个副本(–replicas 1 )的nginx服务,使用镜像nginx
[root@docker01 ~]# docker service create --replicas 1 --network nginx_net --name my_nginx -p 80:80 nginx

2)查看命令
正在运行服务的列表
[root@docker01 ~]# docker service ls

查询Swarm中服务的信息
docker service inspect --pretty my_nginx

查询哪个节点正在运行该服务
docker service ps my_nginx

登陆该节点,可以查看到nginx容器在运行中
[root@docker01 ~]# docker ps

3)在Swarm中动态扩展服务(scale)
扩展加原有总共4个
[root@docker01 ~]# docker service scale my_nginx=4

4)模拟宕机node节点
如果一个节点宕机了(即该节点就会从swarm集群中被踢出),则Docker应该会将在该节点运行的容器,调度到其他节点,以满足指定数量的副本保持运行状态。

[root@docker03 ~]# systemctl stop docker

再次在docker02和docker01节点上将从docker03上转移过来的两个task关闭

命令:docker stop my_nginx.3.rhbj4bcr4t2c3y2f8vyfmbi21(任务名,不是容器名)

再次查询服务的状态列表,发现这两个task又转移到docker03上了
[root@docker01 ~]# docker service ps my_nginx

5)Swarm 动态缩容服务(scale)
同理,swarm还可以缩容,同样是使用scale命令
如下,将my_nginx容器变为1个

[root@docker01 ~]# docker service scale my_nginx=1
my_nginx scaled to 1

[root@docker01 ~]# docker service ls

ID NAME MODE REPLICAS IMAGE PORTS
zs7fw4ereo5w my_nginx replicated 1/1 nginx:latest *:80->80/tcp

[root@docker01 ~]# docker service ps my_nginx

5.Swarm中使用Volume

1)查看volume的帮助信息
[root@docker01 ~]# docker volume --help

2)创建volume
[root@docker01 ~]# docker volume create --name testvolume

查看创建的volume
[root@docker01 ~]# docker volume ls

查看volume详情
[root@docker01 ~]# docker volume inspect testvolume

3)创建新的服务并挂载testvolume(nginx为例)
提示:
参数src写成source也可以;dst表示容器内的路径,也可以写成target

[root@docker01 ~]# docker service create --replicas 3 --mount type=volume,src=testvolume,dst=/zjz --name test_nginx nginx

验证:有没有挂载成功(登录各个节点的容器看看有没有指定的目录并创建文件测试)

容器中操作
[root@docker01 ~]# docker exec -it 63451219cb4e /bin/bash
root@63451219cb4e:/# cd /zjz/
root@63451219cb4e:/zjz# ls
root@63451219cb4e:/zjz# echo “gen wo xue docker” > docker.txt
root@63451219cb4e:/zjz# ls
docker.txt

本地目录查看
执行docker volume inspect testvolume 可以看到本地的路径(上面已经执行过了)
本地路径:/var/lib/docker/volumes/testvolume/_data
[root@docker01 ~]# cd /var/lib/docker/volumes/testvolume/_data
[root@docker01 _data]# ls
docker.txt
[root@docker01 _data]# cat docker.txt
gen wo xue docker

还可以将node节点机上的volume数据目录做成软链接
[root@docker01 _data]# ln -s /var/lib/docker/volumes/testvolume/_data /zjz
[root@docker01 _data]# cd /zjz/
[root@docker01 zjz]# ls
docker.txt
[root@docker01 zjz]# echo “123” > 1.txt

创建并挂载且使用网络
先创建本地目录
mkdir /opt/web
[root@docker01 ~]# docker service create --replicas 1 --mount type=bind,target=/usr/share/nginx/html/,source=/opt/web/ --network nginx_net --name zjz_nginx -p 8880:80 nginx


报错解决

注意:Docker Swarm很注重,一致性,所以必须保证环境及条件一致性,否则报错!!!

1、实验环境:如果三台虚拟机的快照状态不一样,会报错,英文提示群集模式不匹配;
解决:克隆完全一样的三台虚拟机,尝试

2、如果之前有创建的Nginx服务,再启动一组,会出现不报错,一直创建但是不成功。删除之前的才能创建下一组。

3、执行创建Swarm集群命令可能会报错:

Error response from daemon: This node is already part of a swarm. Use “docker swarm leave” to leave this swarm and join another one.

解决:
[root@docker01 ~]# docker swarm leave -f
leave就是在集群中删除节点,-f参数强制删除,执行完在重新执行OK

以上是关于从零开始轻松部署Docker Swarm集群的主要内容,如果未能解决你的问题,请参考以下文章

从零开始搭建Docker Swarm集群

docker从零开始网络(一) overly网络

从零开始搭建服务器之更加优雅地部署项目

从零开始搭建kubernetes集群环境(虚拟机/kubeadm方式)

Kubernetes部署_02_从零开始搭建k8s集群v1.21.0(亲测可用)

Kubernetes部署_02_从零开始搭建k8s集群v1.21.0(亲测可用)