docker swarm的相关知识扫盲
一、什么是docker swarm
要了解什么是docker swarm首先需要了解什么是docker,docker是一种容器方案,它基于Linux内核提供的namespace资源隔离和Cgroup资源限制实现了进程级别的自包含的容器技术,实现了真正的一次编译到处运行和快速启动。
那么docker swarm是什么呢?docker swarm是一种容器编排技术,容器编排旨在自动执行容器的配置、部署、网络、扩展、可用性以及生命周期管理,也就是说你声明你的这个应用是使用什么网络、有多少个可用度、重启策略是什么;容器编排程序会自动的保证保证应用尽可能接近你定义的状态(声明式架构)。由于太过简陋docker swarm目前已经不是一种主流的技术,但是没有绝对不好的技术只有不适合的场景,对于我们的程序来说,k8s的众多组件往往还是偏重的,并且由于docker swarm是docker程序内置的,所以docker swarm在公司内部的产品中还是广泛应用。
二、核心概念和对应的玩法
2.1 节点
docker swarm的节点也是分成两类,一类是manager(管理节点),一类是worker(工作节点)。manager节点提供了对外的api(http或者cli)供用户操作集群中的资源。请注意:
docker swarm中manager节点默认也是工作节点的一部分(也就是说你的业务负载会平等的出现在管理节点和工作节点),只是它没有集群管理、资源调度和提供对外API的能力。
列出节点(只有管理节点可以执行):
docker node ls
多个manager具有平等的操作集群的能力,他们维护了一个kv数据库(类似k8s的etcd)并且依赖RAFT算法(这是一种分布式算法)用来保证状态的一致,多节点时如果超过[(N-1)/2]+1个管理节点不可用,那么集群就会异常。
第一个初始化的节点默认为manager节点,其他的节点后面只能使用docker swarm join加入集群:
docker swarm init [这后面当然可以跟参数,不跟的话程序会使用默认的]
manager节点和worker节点可以用过promote和demote命令来相互转化。
# worker升级成为manager
docker node promote [nodeID]
# manager降级成为worker
docker node demote [nodeID]
当然也可以在加入集群时就选定角色:
# 管理节点加入token获取
$ docker swarm join-token manager
docker swarm join --token SWMTKN-1-1s5x6ot5pd9mzv5vynr4l1ry08tikyar50xbk87r0z1fr6y54f-669kpcoku8zklqkgj243ezetu 192.168.1.1:2377
# 工作节点加入token获取
$ docker swarm join-token worker
docker swarm join --token SWMTKN-1-1s5x6ot5pd9mzv5vynr4l1ry08tikyar50xbk87r0z1fr6y54f-4dd2j9x6kh0mvjk499gmm9hc5 192.168.1.1:2377
2.2 Service
Service是docker swarm中的一个抽象,默认情况下(即不启用内部dnsrr+外部lb)service至少承担了以下两个功能,保证容器副本数量和提供对外访问的ingress端口以及LB的能力。
这里面有三个概念:service、task、container,service是docker swarm应用层的最上层抽象,它负责保证目前可用的task的数量,以及根据内部的dns解析和自带的lb提供对外访问的能力。task是容器的一个抽象,类似于k8s中只有一个容器的pod,事实上它是service直接管理的对象;而container就是docker cri的具体实现了,它负责根据task的规模维护容器的生命周期(创建销毁等)。
创建service:
创建service与创建一个容器某种程度上参数是一致的,只是操作的资源对象时service。
docker service create [options]
# docker service create --name nginx-test -p 80 -d nginx
列出service:
$ docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
bb3gt6tuxljq boring_johnson replicated 0/1 nginx:latest *:30000->80/tcp
ca75ldzkdv20 gracious_wilson replicated 1/1 nginx:latest
xm6rgzb6mijr tender_tharp replicated 1/1 nginx:latest
如上表示我有三个service,其中第一个service对外映射了80端口(我选择了程序自动分配外部端口,所以程序分配了30000),这三个service的副本数都是1,但是第一个service是0/1代表目前未达到目标副本数,swarm的scheduler将会根据task的状态(new/pending/running/failed)来决定是等待还是重新投递。
伸缩副本,如下我把这个service直接扩张到了8个副本:
docker service update --replicas=8 bb3gt6tuxljq
bb3gt6tuxljq
overall progress: 8 out of 8 tasks
1/8: running [==================================================>]
2/8: running [==================================================>]
3/8: running [==================================================>]
4/8: running [==================================================>]
5/8: running [==================================================>]
6/8: running [==================================================>]
7/8: running [==================================================>]
8/8: running [==================================================>]
verify: Service converged
[root@host-172-15-110-80 ~]# docker service ps bb3gt6tuxljq
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
obrwo0tu2x6z boring_johnson.1 nginx:latest host-172-15-110-83 Running Running 7 minutes ago
itwqt8ybdn62 boring_johnson.2 nginx:latest host-172-15-110-80 Running Running 38 seconds ago
4mlvhxnnv83y boring_johnson.3 nginx:latest host-172-15-110-81 Running Running 38 seconds ago
oo6dzg8pwamo boring_johnson.4 nginx:latest host-172-15-110-81 Running Running 7 seconds ago
s03yl3cbvksz boring_johnson.5 nginx:latest host-172-15-110-80 Running Running 7 seconds ago
m24npvfijukx boring_johnson.6 nginx:latest host-172-15-110-83 Running Running 7 seconds ago
rphye3c2rft9 boring_johnson.7 nginx:latest host-172-15-110-81 Running Running 7 seconds ago
1ccpdw7dcdxl boring_johnson.8 nginx:latest host-172-15-110-83 Running Running 7 seconds ago
pending service:
由于配置的原因,某些service在当前swarm中没有节点可以执行它的task。在这种情况下,service会一直保持pending状态,比如:
-
如果所有的节点都暂停了或者都处于
DRAIN状态,创建service时就会一直处于pending状态,直到有节点变为可用状态。 -
资源不满足:比如给service划定一定的内存。如果没有一个节点具有所需要的内存空间量,service会一直保持
pending状态,直到一个节点变的可用。 - 其他约束条件
task中有readness probe和lineness probe,也就是存活探针和可读性探针来确定容器的状态,存活探针检测失败的话会触发service的再次调度。所以你不能直接停止或者重启service管理的容器,因为一旦容器退出,swarm存活探针检测失败就会拉起新的容器。
手动强制再次调度可以执行:
docker service update [serviceName] --force
删除service:
docker service rm [serviceName]
2.3 网络
docker swarm支持多种网络模式,但是这个部分我不准备展开,网络的主要我们主要讲一下ingress和docker_gwbridge。这是使用中经常出问题的部分。
其中docker_gwbridge是一个虚拟的二层网桥,docker_gwbridge作为一个虚拟的二层网桥,它负责将来自Docker容器的网络流量转发到主机上的其他容器或外部网络,并根据需要对流量进行NAT处理。
而ingress网络本质上是一个overlay网络,基于vxlan技术实现了跨节点的组网、负载均衡和服务发现等功能。一个service中的容器要与外界通信,必须通过这两个网络。我们可以查看网络:
docker network ls
NETWORK ID NAME DRIVER SCOPE
ce817db13d02 bridge bridge local
f1031e535fcb docker_gwbridge bridge local
e5a1994a0c7b host host local
tpwh1eeq4cbc ingress overlay swarm
7e5e5f600dc2 none null local
在实际使用中我们一定要避免docker_gwbridge和ingress网络与主机所在的网络冲突,这个我们在实际使用中经常碰到,这是导致swarm中容器无法通信的常见原因之一。
我们在service超过124个以后你可能会发现service报错找不到可用的VIP了,这个与ingress的CIDR宽度有关,默认/24的宽度只有256个ip包含内部互相通信等占用,一般只能创建124个左右,这个时候可以把ingress改大。
自定义overlay:
默认的ingress网络虽然能够实现跨节点网络,但是效率往往较低,可以自行创建overlay网络(创建网络时指定驱动为overlay然后自定义自己占用的网段),并在创建service的时候指定这个网络。
浙公网安备 33010602011771号