Docker--Docker Swarm集群

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时,

    1. 编排器会先创建3个task,每个task有一个taskID,通过分配器为每个task分配一个虚拟IP。
    2. 再讲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节点。

  1. 准备5个主机,主机名分别是docker1、docker2、docker3、docker4、docker5

  2. 查看swarm激活状态

    通过docker info命令查看swarm的激活状态。

上图表示swarm未激活。

  1. swarm初始化

    在"docker1"主机上运行docker swarm init 命令。创建并初始化一个swarm

  2. 添加worker节点

    复制上面执行命令的结果中添加worker节点命令在docker4和docker5中运行,将这两个节点添加未docker节点

  3. 添加manager节点

    执行docker swarm join-token manager命令

    复制上面的响应结果,在docker2和docker3中运行,将这两个节点添加为manager节点

  4. 查看swarm节点

    在manager 节点docker1、docker2、docker3 上执行docker node ls 查看当前节点数据,但是在worker节点不能运行docker node ls 命令

swarm集群维护

退出swarm集群

  1. worker 退群:直接运行docker swarm leave 即可

  2. worker 重新加入:先在manager运行docker swarm join-token worker

    然后复制生成的命令,在新worker节点上运行,就添加到swarm集群了。

  3. 查看节点情况,发现原来的docker5是down,新的docker5节点是Ready

  4. 删除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引擎,模拟宕机情况

    sh 复制代码
    systemctl stop docker
  • 加入manager ,启用docker3 的docker引擎

    sh 复制代码
    systemctl 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 选项指定。

    sh 复制代码
    docker 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标签。

    sh 复制代码
    docker 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数字证书轮换

  1. 轮换周期:Swarm的CA数字证书有可能被攻击,所以需要轮换,默认90天轮换一次。

  2. 指定证书:轮换的数字证书来自哪里呢?通过docker swarm ca命令可以指定外部ca数字证书,或生成新的CA数字证书。

  3. 轮换过程:当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进行扩容/缩容,有两种实现方式:

  1. docker service update 方式

    sh 复制代码
    # 变更task数量
    docker service update --replicas 4 toms
  2. docker service scale 方式

    sh 复制代码
    # 变更服务数量
    docker service scale toms=7
  3. 暂停节点的task分配

    生产环境下,由于某主机性能低下,扩容时,不想为此主机分配更多的task,可以pause 该主机节点。

    sh 复制代码
    # 不为docker2 增加task数量
    docker node update --availability pause docker2
    # 然后就可以扩容了
    docker service scale toms=10
  4. 清空task

    当不想让manager节点接收task或者某个节点出现问题,需要停止服务进行维修,此时就需要将该节点上的task清空,以不影响service的整体性能。

    sh 复制代码
    # 清空docker2 节点上的task,此时就将docker2节点上task分配到其他节点了。
    docker node update --availability drain docker2

    task容错

    当task所在主机或容器发生故障,manager编排器会自动创建新的task,然后分配到可用节点上。

    service 删除

    sh 复制代码
    docker service rm [service name|service ID]

    删除后,service消失,对应的task也全部删除。task相关的节点容器也全部消失。

滚动更新

当一个service的task较多时,为了不影响对外提供服务,对service进行更新时可采用滚动更新。

比如:将镜像tomcat:8.5.49 的service 的镜像滚动更新为tomcat:8.5.39

  1. 创建service

    sh 复制代码
    docker 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  
  2. 更新service:将镜像tomcat:8.5.49 的service 的镜像滚动更新为tomcat:8.5.39

    sh 复制代码
    docker service update --image tomcat:8.5.39 toms

更新回滚

当更新失败,会回滚到更新前的状态,用户也可通过命令方式手动回滚。

sh 复制代码
docker service update --rollback toms

service全局部署模式

常见的service部署模式有两种:replicated模式和global模式。

前面创建的service 是replicated模式。下来创建global模式的service。

  1. 创建service,通过--mode 指定部署模式,默认采用replicated模式。

    sh 复制代码
    docker 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,依然能响应请求的现象!

相关推荐
两年半的个人练习生^_^1 小时前
JMM 进阶:彻底理解 CAS 实现原理
java·开发语言
wuminyu1 小时前
Java锁机制之park和unpark源码剖析
java·linux·c语言·jvm·c++
W_LuYi1852 小时前
手撸极简zkEVM验证器:RISC-V电路实践
java·risc-v
AI人工智能+电脑小能手2 小时前
【大白话说Java面试题 第102题】【并发篇】第2题:volatile 能否保证线程安全?
java·安全·面试
KobeSacre2 小时前
JUC 概述
java·开发语言
小bo波3 小时前
形式化方法 × UML
java·软件工程·uml·面向对象·形式化方法·tla+
就叫_这个吧3 小时前
IDEA中Javaweb项目创建+servlet,实现简单的信息录入获取
java·servlet·intellij-idea·web
程序员Jelena3 小时前
接口调用的代码实现:从入门到实战
java
代码钢琴师3 小时前
Throttle4j 快速上手教程
java