Docker Swarm
Docker Swarm 是docker原生集群管理系统,它将一个Docker主机池变成了一个虚拟主机,只需要使用简单的API就可以实现与Docker集群的通信。
从Docker 1.12.0开始,Docker Swarm就内置于Docker引擎中了,不需要单独安装配置。
节点架构
-
swarm node
从物理上讲,一个swarm 就是若干个安装了Docker的物理机或虚拟机,这些主机上的Docker 都采用Swarm 模式运行。
从逻辑上讲,一个Swarm 由若干个节点node组成,每个node会落实在一个物理Docker主机上,但是一个物理Docker主机不一定就是一个node ,也可能一个主机上有多个node节点,即swarm node与Docker主机不是一对一关系。
swarm node 有两种类型:manager和worker。
-
Manager
Manager节点用于维护swarm集群状态、调试service、处理swarm集群管理任务。为了防止单点故障,一个swarm集群一般包含多个manager,这些Manager通过Raft算法为维护着一致性。
-
Worker
Worker节点用于在其Container 中运行task任务,即对外提供service服务。默认manager 同时也充当worker角色,可以运行task任务。
-
角色转换
manager 和Worker 的角色不是一成不变的,他们之间可以相互转换。
manager--》worker 称为节点降级
worker--》manager 称为节点升级
服务架构
-
-
service
搭建docker swarm的目的是为了在swarm集群中运行应用,提供更强抗压能力的服务。
service服务是一个逻辑概念,表示对外提供的服务。
-
task
一个service是通过task的形式出现在swarm 的各个节点中,每个节点的task是通过容器对外提供服务。
-
编排器
在swarm manager中有一个编排器,用来管理task的创建与停止。比如:
searm manager 中定义一个有3个task的service时,
- 编排器会先创建3个task,每个task有一个taskID,通过分配器为每个task分配一个虚拟IP。
- 再讲task注册到内置的DNS中。当某个task不可用时,编排器会在DNS中注销该task。
-
分发器
swarm manager中有一个分发器,用于对task的监听、调度等操作。
在前面的例子中,当编排器创建3个task后,会调用分发器为每个task分配节点,
分发器会现在swarm集群的所有节点中找到3个 available node,每个node分配一个task。每个task像是一个"插槽",分发器会在每个"插槽"中放入一个容器,一个容器就是一个task实例。
一旦容器运行,分发器就能监测其运行状态,即task的运行状态。
如果容器不可用或被终止,task也会被终止。此时编排器会立即在DNS中注销该task,然后编排器再生成一个新的task,并在DNS中注册,然后分发器分配一个新的available node ,然后在此节点上运行容器。
分发器除了为task分配节点外,还实现对访问请求的负载均衡。当请求到来时,会被manager处理:根据内置的DNS,实现访问的负载均衡。
服务部署模式
常见的service部署模式有两种:replicated模式与global模式
-
replicated模式 :副本模式,service的默认部署模式,需要指定task数量。当task数量不等于swarm 的节点数量时,需要使用replicated模式。
manager 中的分发器会找到task个数的available node,为每个节点分配一个或若干个task。
-
global模式:全局模式,分发器为每个节点都分配一个task。不能指定task数量。swarm集群每增加一个节点,编排器就会创建一个task,通过分发器分配到新的节点上。
swarm集群搭建
现在搭建一个swarm集群,包括5个swarm节点。
-
准备5个主机,主机名分别是docker1、docker2、docker3、docker4、docker5
-
查看swarm激活状态
通过docker info命令查看swarm的激活状态。
上图表示swarm未激活。
-
swarm初始化
在"docker1"主机上运行docker swarm init 命令。创建并初始化一个swarm
-
添加worker节点
复制上面执行命令的结果中添加worker节点命令在docker4和docker5中运行,将这两个节点添加未docker节点
-
添加manager节点
执行
docker swarm join-token manager命令复制上面的响应结果,在docker2和docker3中运行,将这两个节点添加为manager节点
-
查看swarm节点
在manager 节点docker1、docker2、docker3 上执行docker node ls 查看当前节点数据,但是在worker节点不能运行docker node ls 命令
swarm集群维护
退出swarm集群
-
worker 退群:直接运行docker swarm leave 即可
-
worker 重新加入:先在manager运行
docker swarm join-token worker然后复制生成的命令,在新worker节点上运行,就添加到swarm集群了。
-
查看节点情况,发现原来的docker5是down,新的docker5节点是Ready
-
删除down节点:在manager节点上运行docker node rm
manager 退群
对于manager节点,原则上不推荐直接退群,这样会导致swarm集群的一致性受到损坏。
可在docker swarm leave 命令后添加-f 或--force选项进行强制退群。
swarm自动锁定
-
swarm集群自动锁定原理
在manager集群中,swarm童话该国Raft日志方式维护manager集群中数据的一致性。
即每个节点通过manager间通信方式维护自己的Raft日志。
但在通信过程中有一种风险:攻击者通过Raft日志数据的传递来访问、篡改manager节点中的数据。为了防止被攻击,swarm开启了一种集群自动锁定功能,为通信启用TLS加密。加密解密的公钥与私钥全部维护在各个节点的Docker内存中。一旦节点的Docker 重启,则密钥丢失。
swarm通过autolock 标志来设置集群的自动锁定功能:true表示开启,false表示关闭。
-
设置自动锁定
在manager节点通过
docker swarm update -autolock=true开启此时查看manager的docker info,可以看到autolock设为true。
-
查看解锁密钥
在manager中运行
docker swarm unlock-key查看 -
关闭一个manager
直接关闭docker3 的docker引擎,模拟宕机情况
shsystemctl stop docker -
加入manager ,启用docker3 的docker引擎
shsystemctl start docker此时查看节点
docker info,可以看到Swarm值为locked,若要加入,必须先解锁。在docker3中执行
docker swarm unlock命令解锁输入密钥就完成解锁了。
swarm节点维护
角色转换
-
worker升级为manager
通过
docker node promote命令可以将worker升级为manager。下面的命令是将docker4和docker5升级为manager
-
manager降级为worker
通过
docker node demote命令将manager降级为worker -
docker node update 变更角色
通过
docker node update --role [manager|worker] [node]也可以变更角色sh# 将docker2和docker3变为manager docker node update --role manager docker2 docker node update --role manager docker3 # 将docker4和docker5变为worker docker node update --role worker docker4 docker node update --role worker docker5
节点标签
swarm可以为节点添加描述性标签,以便于更加了解节点。
-
添加/修改节点标签
通过
docker node update --label-add命令为指定node添加key=value的标签。如果key已经存在,则修改value。如果要添加或修改多个标签,需要多个--label-add 选项指定。shdocker node update --label-add auth=zs --label-add email=zs@163.com docker2通过
docker node inspect查看该节点的标签 -
删除节点标签
通过
docker node update --label-rm为指定的node删除指定key标签。若要删除多个标签,通过多个
--label-rm指定要删除的key标签。shdocker node update --label-rm auth --label-rm email docker2
节点删除
manage节点通过docker node rm 命令可以删除一个Down 状态的、指定的worker节点。注意:该命令只能删除worker节点,不能删除manager节点!
-
有问题的删除:无法直接删除Ready状态的worker节点;
无法删除manager节点。
-
正确的删除:首先关闭节点的Docker,是节点变为Down状态,然后再删除。
-
强制删除:添加 -f选项实现强制删除!
注意:对于manager节点,强制删除也不能删除!
docker node rm -f使一个节点强制退群,而docker swarm leave是使当前docker主机关闭swarm模式。
swarm安全(PKI)
Docker内置了PKI(public key infrastructure,公钥基础设置),保障系统安全!
TLS安全保障
Swarm 节点之间采用TLS来鉴权,授权和加密通信。
当运行docker swarm init命令时,Docker 指定当前节点为一个manager节点。
manager节点生成一个新的swarm CA根证书及一对密钥。同时还会生成2个token(一个用于添加worker节点,一个用于添加manager节点)。每个token都包含CA根证书的digest个一个随机密钥。
当有节点加入Swarm时,复制manager中对应的docker swarm join 加入命令。并在该节点中运行。这个过程是通过随机密钥这种对称验证方式保障通信安全的。
一旦节点加入Swarm 集群,他们之间的通信都是通过TLS加密方式进行的。
先通过CA证书对通信对方的身份进行验证,在验证通过后再进行数据通信。通信数据是通过随机密钥加密过的。
CA数字证书轮换
-
轮换周期:Swarm的CA数字证书有可能被攻击,所以需要轮换,默认90天轮换一次。
-
指定证书:轮换的数字证书来自哪里呢?通过
docker swarm ca命令可以指定外部ca数字证书,或生成新的CA数字证书。 -
轮换过程:当manager运行
docker swarm ca --rotate会按顺序执行以下内容:- Docker生成一个交叉签名(cross-signed)根证书,即新根证书由旧的根证书生成的,这份交叉签名根证书是一个过渡性的根帧数。是为了确保节点仍信任旧的根帧数,也信任新的根证书。
- Docker 通知所有节点立即更新根证书,这回花费几分钟时间。
- 所有节点更新了根证书后,manager 会通知所有节点仅信任新的根证书,不再信任旧的根证书和交叉签名根证书。
- 所有节点使用新的根证书签发自己的数字证书。
如果使用外部的CA根证书,那就不存在交叉签名根证书生成,直接通知所有节点更新新证书,后续过程旧与前面相同了。
manager集群容灾
热备容灾
Swarm的manager集群采用热备方式提升容灾能力。
即再manager集群中只有一个处于leader状态,其余manager处于热备状态,当manager宕机,其余manager会自动发起leader选举,重新选举一个新的manager leader。
选举算法采用Raft算法。其简单思路是,所有manager都有选举与被选举权,最后获得过半选票的manager 当选新的leader。
service创建
注意:service只能依附于docker swarm集群!所以service创建前提是swarm集群搭建完毕!
创建service
在manager中运行 docker service create 命令
比如创建一个tomcat镜像,服务名为toms,包含3个task,端口9000
sh
docker service create --name toms --replicas 3 -p 9000:8080 tomcat:8.5.49
sh
# 查看服务列表
docker service ls # 用来查看正在运行的service。一个swarm可运行多个swarm。
# 查看指定服务详情
docker service inspect [service name|service ID]
此时用户就可以通过swarm集群中的任意主机来访问服务了,
比如:docker3:9000或docker2:9000
sh
# 查看task节点,查看指定服务的各个task所分配的节点信息
docker service ps [service name|service ID]
# 查看节点task
docker node ps [node]
# 查看节点docker5的task
docker node ps docker5
# 查看service日志
docker service logs [service name|service ID]
# 查看task日志
docker service logs [taskID]
# taskID 可通过查看task详情获取
docker node ps [service name|service ID]
负载均衡
当一个service 包含多个task时,用户访问service 会通过负载均衡的方式转发给各个task处理。负载均衡策略为轮询策略,且无法通过修改service的属性方式进行变更。
但可以通过第三方实现负载均衡策略的变更,例如:Nginx、HAProxy。
service操作
task伸缩
当需要在不停止服务的前提下对服务的task进行扩容/缩容,有两种实现方式:
-
docker service update 方式
sh# 变更task数量 docker service update --replicas 4 toms -
docker service scale 方式
sh# 变更服务数量 docker service scale toms=7 -
暂停节点的task分配
生产环境下,由于某主机性能低下,扩容时,不想为此主机分配更多的task,可以pause 该主机节点。
sh# 不为docker2 增加task数量 docker node update --availability pause docker2 # 然后就可以扩容了 docker service scale toms=10 -
清空task
当不想让manager节点接收task或者某个节点出现问题,需要停止服务进行维修,此时就需要将该节点上的task清空,以不影响service的整体性能。
sh# 清空docker2 节点上的task,此时就将docker2节点上task分配到其他节点了。 docker node update --availability drain docker2task容错
当task所在主机或容器发生故障,manager编排器会自动创建新的task,然后分配到可用节点上。
service 删除
shdocker service rm [service name|service ID]删除后,service消失,对应的task也全部删除。task相关的节点容器也全部消失。
滚动更新
当一个service的task较多时,为了不影响对外提供服务,对service进行更新时可采用滚动更新。
比如:将镜像tomcat:8.5.49 的service 的镜像滚动更新为tomcat:8.5.39
-
创建service
shdocker service create --name toms --replicas 10 --update-parallelism 2 --update-delay 3s --update-max-failure-ratio 0.2 --update-failure-action rollback --rollback-parallelism 2 --rollback-delay 3s \ --rollback-max-failure-ratio 0.2 --rollback-failure-action continue -p 9000:8080 tomcat:8.5.49 -
更新service:将镜像tomcat:8.5.49 的service 的镜像滚动更新为tomcat:8.5.39
shdocker service update --image tomcat:8.5.39 toms
更新回滚
当更新失败,会回滚到更新前的状态,用户也可通过命令方式手动回滚。
sh
docker service update --rollback toms
service全局部署模式
常见的service部署模式有两种:replicated模式和global模式。
前面创建的service 是replicated模式。下来创建global模式的service。
-
创建service,通过--mode 指定部署模式,默认采用replicated模式。
shdocker service create --name toms --mode global -p 9000:8080 tomcat:8.5.49该模式会在每个节点上分配一个task
task伸缩
对于global模式来说,要改变task数量,必须先改变该service所依附的swarm集群的节点数量。节点增加,task自动增加;节点减少,task自动减少。
比如在manager节点新增一个节点,那么这个节点会自动增加一个task。
overlay网络
overlay网络,称为重叠网络或覆盖网络,是一种构建于underlay网络之上的逻辑虚拟网络。
在物理网络的基础上,通过节点间单播隧道机制将主机两两相连而形成的虚拟、独立的网络。
Docker Swarm集群中的overlay网络 主要通过iptables、ipvs、vxlan等技术实现。
overlay网络模型
overlay网络模型 在创建时,会创建出两个网络:docker_gwbidge网络和ingress网络。同时还创建出docker_gwbidge网关与br0网关,和ingress-sbox容器。
当请求到达后,先经由docker_gwbidge网关跳转到ingress-sbox容器,选择一个容器IP作为目的地址,然后再跳转到br0网关。
在br0网关中根据目的地址进行判断,如果目的地址是本地容器ip,则直接讲请求发给该容器处理,如果目的地址不是本地容器IP。则讲请求经由vxlan接口,通过vxlan隧道技术将请求发给目的地址容器。
这就解释了,当请求访问的集群中某个docker主机,即使这个主机没有task,依然能响应请求的现象!