十docker swarm

【十docker swarm】但使书种多,会有岁稔时。这篇文章主要讲述十docker swarm相关的知识,希望能为你提供帮助。
一、概述Swarm是docker的一种集群模式,由多个docker节点组成,一般最小规模为3节点。在这些节点中将划分两种角色:manager、workers;做为manager角色的节点将采用Raft算法进行选举,其中将会有一个成为leader,集群任务由该节点进行调度。当一个leader节点发生故障时,其他manager将会重新选举推出新的leader掌管集群。而worker节点负责运行维护服务副本,也就是具体的容器。
1、功能特点

与 Docker Engine 集成的集群管理:使用 Docker Engine CLI 创建一组 Docker Engine,您可以在其中部署应用程序服务。您不需要额外的编排软件来创建或管理集群。
去中心化: Docker 引擎不是在部署时处理节点角色之间的差异,而是在运行时处理任何专业化。您可以使用 Docker 引擎部署两种类型的节点、管理器和工作器。这意味着您可以从单个磁盘映像构建整个集群。
声明式服务模型: Docker Engine 使用声明式方法让您定义应用程序堆栈中各种服务的所需状态。例如,您可能会描述一个应用程序,该应用程序由具有消息队列服务和数据库后端的 Web 前端服务组成。
缩放:对于每个服务,您可以声明要运行的任务数量。当您扩大或缩小规模时,群管理器会通过添加或删除任务来自动适应以保持所需的状态。
期望状态协调: swarm 管理器节点不断监控集群状态,并协调实际状态和您表达的期望状态之间的任何差异。例如,如果您设置一个服务来运行容器的 10 个副本,并且托管其中两个副本的工作机器崩溃,则管理器会创建两个新副本来替换崩溃的副本。swarm manager 将新的副本分配给正在运行且可用的 worker。
多主机网络:您可以为您的服务指定一个覆盖网络。群管理器在初始化或更新应用程序时自动为覆盖网络上的容器分配地址。
服务发现: Swarm 管理器节点为 Swarm 中的每个服务分配一个唯一的 DNS 名称并平衡运行容器的负载。您可以通过嵌入在 swarm 中的 DNS 服务器查询在 swarm 中运行的每个容器。
负载均衡:您可以将服务的端口暴露给外部负载均衡器。在内部,swarm 允许您指定如何在节点之间分发服务容器。
默认安全: swarm 中的每个节点都强制执行 TLS 相互身份验证和加密,以保护自身与所有其他节点之间的通信。您可以选择使用自签名根证书或来自自定义根 CA 的证书。
滚动更新:在推出时,您可以增量地将服务更新应用到节点。swarm 管理器允许您控制服务部署到不同节点集之间的延迟。如果出现任何问题,您可以回滚到该服务的先前版本

2、节点
运行 Docker 的主机可以主动初始化一个 Swarm 集群或者加入一个已存在的 Swarm 集群,这样这个运行 Docker 的主机就成为一个 Swarm 集群的节点 (node) 。
节点分为管理 (manager) 节点和工作 (worker) 节点。
管理节点用于 Swarm 集群的管理,docker swarm 命令基本只能在管理节点执行(节点退出集群命令 docker swarm leave 可以在工作节点执行)。一个 Swarm 集群可以有多个管理节点,但只有一个管理节点可以成为 leader,leader 通过 raft 协议实现。通常,第一个启用docker swarm的节点将成为leader,后来加入的都是follower。当前的leader如果挂掉,剩余的节点将重新选举出一个新的leader。每一个manager都有一个完整的当前集群状态的副本,可以保证manager的高可用。
工作节点是任务执行节点,管理节点将服务 (service) 下发至工作节点执行。管理节点默认也作为工作节点。你也可以通过配置让服务只运行在管理节点。worker节点之间,通过control plane进行通信,这种通信使用gossip协议,并且是异步的。
来自 Docker 官网的这张图片形象的展示了集群中管理节点与工作节点的关系。

3、服务和任务
任务 (Task)是 Swarm 中的最小的调度单位,目前来说就是一个单一的容器。
服务 (Services) 是指一组任务的集合,服务定义了任务的属性。服务有两种模式:
replicated services 按照一定规则在各个工作节点上运行指定个数的任务。
global services 每个工作节点上运行一个任务
两种模式通过 docker service create 的 --mode 参数指定。
来自 Docker 官网的这张图片形象的展示了容器、任务、服务的关系

4、网络模式
在Swarm集群中,由于在容器上层又增加了一个service概念,因此对容器的访问更改成了对service的访问,然后再由一个service对应多个容器。那么一个service可能会包含多个容器副本,而这些容器副本多数情况下是运行在不同的主机中,为了实现service到具体容器副本的转发,在网络模式上与之前的单机的容器网络也将有
所不同。

services
swarm service是一个抽象的概念,它只是一个对运行在swarm集群上的应用服务,所期望状态的描述。它就像一个描述了下面物品的清单列表一样:
服务名称
使用哪个镜像来创建容器
要运行多少个副本
服务的容器要连接到哪个网络上
应该映射哪些端口
task
在Docker Swarm中,task是一个部署的最小单元,task与容器是一对一的关系。
stack
stack是描述一系列相关services的集合。我们通过在一个YAML文件中来定义一个stack。

由于一个service会包含多个容器副本,多个副本可以看成一个service整体,它们通常只干一类相同的事情。而稍复杂一点的情况是,一个service可能还需要依赖其他service的能力才能完成任务,那么这就涉及从一个service到另一个service的调用。那么因此在swarm中最常见的2种网络访问是:
外部至swarm内部的service的调用
swarm内部,service至service的调用

Service到Service的调用,在swarm中将使用overlay网络解决该问题,overlay是一种覆盖多个主机的虚拟网络,它是利用路由转发策略将对虚拟网络中ip的请求转发至具体容器IP上来
完成通信。而在swarm中不紧如此,还将使用Docker内部的DNS为服务名进行DNS解析,这意味着你可以在swarm集群内部使用服务名称来访问对应的service。如下图所示,在swarm集群中
一个service可被其他容器应用调用,该调用可以基于服务名的DNS记录,如果一个service分配的vip,那么使用服务名调用DNS将解析为vip,vip在对应具体的容器副本IP,而如果使用
dnsrr模式(轮询),则使用服务名调用时会直接返回一个具体的容器副本ip。

外部到service的调用,在swarm中仍然采用端口映射方式,使用宿主机端口映射到overlay网络分配的容器副本IP,而这种映射仍然基于一种多副本间的轮询。
即使宿主机中并没有实际运行对应的容器副本,那么该主机仍然会使用本地端口,转发请求至其他主机上的容器副本

在swarm初始化过程中,会创建一个默认的overlay网络名为ingress,当然也支持用户自定义自己的overlay网络。要让service使用自定义的网络,那么在创建service时,指定需要使用的网络名称即可。
在Swarm初始化完成后,默认会创建一个网桥docker_gwbridge,和一个veth设备,而在docker中对应的会出现两个网络,一个名为ingress的overlay网络,一个为docker_gwbridge桥接网络。不仅如此还会创建两个默认network namespace,这两个网络空间的名称为ingress_sbox和另一个ingress,数据包需要进入这两个网络空间中进行一些处理,然后才到达容器的网络空间中。
在Swarm集群中配置使用overlay网络的服务,首先overlay网络会拥有独立的网段,如10.0.0.0/24。那么默认情况下会从该网段中为服务分配的一个IP,该IP是一个虚拟IP,docker使用IPVS对该虚拟IP进行负载,负载至具体的容器IP上,该IP同样来自overlay网络段。
而容器也会拥有2个veth对,一个用于连接容器至docker_gwbridge,另一个用于连接容器至ingress网络空间;因此在容器的网络空间中会出现2个veth接口,分别拥有不同的IP。
二、swarm搭建安装三台docker,128、129、130
[root@docker dockerfile]# docker swarm init
Error response from daemon: --live-restore daemon configuration is incompatible with swarm mode

docker swarm初始化和--live-restore参数不兼容
三台docker机器去掉这个参数并重启

[root@docker dockerfile]# docker swarm init
Swarm initialized: current node (q0o0dtete9jg1o5z1p5x82dr5) is now a manager.

To add a worker to this swarm, run the following command:

docker swarm join --token SWMTKN-1-09ykfse4tnmz15df3d1vq9vk1jxzdhjjrqmc4r5acxq7yx5ax0-devvjbie9goc98m5ekuvg1efx 192.168.10.128:2377

To add a manager to this swarm, run docker swarm join-token manager and follow the instructions.

可以在其他机器直接执行docker swarm join --token SWMTKN-1-09ykfse4tnmz15df3d1vq9vk1jxzdhjjrqmc4r5acxq7yx5ax0-devvjbie9goc98m5ekuvg1efx 192.168.10.128:2377加入这个集群
也可以在当前节点执行docker swarm join-token manager重新生成加入集群的语句

[root@docker dockerfile]# docker swarm join-token manager
To add a manager to this swarm, run the following command:

docker swarm join --token SWMTKN-1-09ykfse4tnmz15df3d1vq9vk1jxzdhjjrqmc4r5acxq7yx5ax0-67zhyf4ffrdlg83qmzl81tcpk 192.168.10.128:2377
另外两台机器分别执行命令加入集群

[root@docker ~]# docker node ls
IDHOSTNAMESTATUSAVAILABILITYMANAGER STATUSENGINE VERSION
q0o0dtete9jg1o5z1p5x82dr5 *dockerReadyActiveLeader20.10.9
7443a0o2nwiyi8d7c7jr5uqobdocker129ReadyActiveUnreachable20.10.11
mzo5jzic62dwbdtcqz11eum5adocker130ReadyActiveReachable20.10.10

[root@docker ~]# docker info
Swarm: active
NodeID: q0o0dtete9jg1o5z1p5x82dr5
Is Manager: true
ClusterID: m9iiedb0wypylkgx1m7ofphey
Managers: 3 ##可以确定如果加入swarm集群,默认情况下Managers也是node节点
Nodes: 3

[root@docker ~]# docker node ls
IDHOSTNAMESTATUSAVAILABILITYMANAGER STATUSENGINE VERSION
q0o0dtete9jg1o5z1p5x82dr5 *dockerReadyActiveLeader20.10.9
7443a0o2nwiyi8d7c7jr5uqobdocker129ReadyActiveReachable20.10.11
mzo5jzic62dwbdtcqz11eum5adocker130ReadyActive20.10.10

默认情况下manager同时也是worker,如果不想让manager同时承担worker的任务的话,执行如下指令,“drain”的意思是manager节点不再接受新的task,如果节点上已经有task在运行,则停止掉并调度到其它worker节点上去:
docker node update --availability drain manager
docker node update docker130 --role worker ##将docker130只设置为worker节点
最好只设置一个为管理节点,如果有两个以上管理节点,会因为开机的先后顺序,搞得leader来回跳,服务命令又只能在管理节点运行
也可以使用命令生成加入集群特定权限的语句
docker swarm join-token manager
docker swarm join-token worker
docker service 适合启动单个服务,对于多服务部署和管理有些无能为力
1、constraint参数
标明使用指定docker服务器创建服务
--constraint node.role == manager
--constraint node.hostname==docker129

三、案例1、命令启动
[root@docker dockerfile]# docker service create --replicas 3 -p 80:80 --name nginx nginx:1.13-alpine
tk1lrh6zhdgfytnivna36vlp5
overall progress: 3 out of 3 tasks
1/3: running[==================================================> ]
2/3: running[==================================================> ]
3/3: running[==================================================> ]
verify: Service converged

[root@docker dockerfile]# docker service ls ###查看当前swarm运行的服务
IDNAMEMODEREPLICASIMAGEPORTS
tk1lrh6zhdgfnginxreplicated3/3nginx:1.13-alpine*:80-> 80/tcp

[root@docker dockerfile]# docker service ps nginx ###查看某个服务的详情
IDNAMEIMAGENODEDESIRED STATECURRENT STATEERRORPORTS
u2y6570eslc2nginx.1nginx:1.13-alpinedocker129RunningRunning less than a second ago
lg0j7m4mppfhnginx.2nginx:1.13-alpinedocker130RunningRunning less than a second ago
suq5u9c7805tnginx.3nginx:1.13-alpinedockerRunningRunning about a minute ago

docker service logs nginx ##查看服务日志
docker service logs -f nginx ##实时观察日志

扩容
[root@docker ~]# docker service scale nginx=5
nginx scaled to 5
overall progress: 5 out of 5 tasks
1/5: running[==================================================> ]
2/5: running[===================

    推荐阅读