一个Swarm是一组Docker引擎或节点的集群,并在这个集群之上部署服务和应用。我们可以使用Docker命令行工具或者API管理集群中的节点,并且还可以通过Swarm部署和编排相应的服务。当我们没有使用Swarm模式的时候,我们只是简单地对容器进行操作;而在Swarm模式下,我们就可以对服务进行编排。值得注意的是,在同一个Docker实例上既可以运行Swarm的服务,也可以运行独立的容器。

本文目录:

节点的工作原理

Docker1.12及其以后版本中引入的Swarm模式,即允许创建一个Docker集群。一个Swarm集群包含一个或多个节点,既可以是物理节点,也可以是虚拟节点。但是,需要保证的是节点上要安装Docker1.12或高于1.12的Docker引擎。

Swarm模式下节点分为两种:管理节点工作节点

节点的工作原理

管理节点

管理节点负责集群的管理任务:

  • 维护集群状态信息
  • 服务调度
  • 处理Swarm模式下的API请求

通过Raft原理,管理节点负责维护整个Swarm集群的内部一致状态以及其上运行的所有服务。为了测试其功能,我们可以运行单个管理节点的Swarm集群。为了保证服务的正常运行,如果单个管理节点的Swarm集群失败,则需要创建一个新的Swarm集群来接管原来的服务。

为了很好的利用Swarm集群的容错功能,Docker建议部署奇数个节点以保证整个Swarm集群的高可用性。与此同时,当采用多个管理节点时,Swarm系统可以保证管理节点的故障恢复,而不会导致服务停机。

  • 一个具有三个管理节点的Swarm集群,最多可允许一个管理节点出现故障。
  • 一个具有五个管理节点的Swarm集群,最多可允许两个管理节点出现故障。
  • 一个具有N个管理节点的Swarm集群,最多可允许(N-1)/2个管理节点出现故障。

在一个Swarm集群中,Docker推荐最多部署七个管理节点。因为,更多的管理节点并不一定意味着高可用性和高伸缩性,有时恰恰相反。

工作节点

工作节点也是Docker引擎的实例,主要负责运行容器实例。工作节点不参与Raft分布式状态维护,调度决策的制定以及服务Swarm模式下的API请求。我们可以创建单个管理节点的Swarm集群,但却不能创建具有单个工作节点的Swarm集群。模式情况下,所有的管理节点也是工作节点。当然,也可以通过配置,让管理节点仅负责“管理功能”。

为了防止服务调度器在具有多个节点的Swarm集群中,将任务布置到管理节点上,可以将管理节点的可用性设置为Drain。这样,服务调度器就不会将任务部署到Drain状态的节点上,而只将任务分派到Active状态的节点。

角色转换

Docker Swarm模式中,允许我们将工作节点提升为管理节点以保证整个Swarm集群的正常运行,尤其是在管理节点出现故障时。相关命令可以参考docker node promote

同样的道理,我们也可以将管理节点变为工作节点。相关命令可以参考docker node demote

服务的工作原理

在Swarm模式下,Docker允许我们通过创建服务的方式来部署应用镜像。通常情况下,服务是某些更大应用程序的上下文中为服务器的镜像。比如,服务包括HTTP服务器,数据库,或者希望在分布式环境中运行的任何类型的可执行程序。

当创建一个服务的时候,我们需要制定服务需要的镜像(即运行环境)和即将在容器中运行的命令(即应用程序)。当然,也包括其他选项:

  • 端口:在Swarm集群外提供服务的端口
  • 网络方式:用于连接到Swarm集群中其他服务的网络环境
  • 系统限制:CPU和内存限制及预留
  • 更新操作:更新时延策略
  • 副本数量:Swarm中镜像的副本数量

服务,任务与容器

当我们向Swarm集群中部署服务时,管理节点将服务定义为服务所需的状态。然后,将服务以任务副本的方式分派到Swarm集群中的各个节点上。这些任务在Swarm集群中的节点上独立运行。

一个容器就是一个独立的进程。Swarm集群中,每个任务调用一个容器。一个任务类似调度器放置在容器里面的一个”插槽“。一旦容器处于运行状态,调度器能够识别任务处于运行状态。如果容器出现问题或终止,则任务终止。

服务的工作原理

任务与调度

任务是 Swarm集群中调度的基本单元,具有 原子性,即一个任务在容器中要么运行成功,要么失败。当我们创建或更新一个服务所需要的服务状态时,调度器通过调度任务来满足服务所需的状态。比如,我们创建一个包括三个HTTP监听的服务,调度器则通过创建三个任务来做出响应。每个任务都是调度器通过创建一个容器并填充一个”插槽“来实现。简单来讲就是,容器是任务的实例化。如果其中一个HTTP监听服务失败或崩溃,调度器将创建一个新容器并执行新的任务副本。

任务采用的是 单向机制。它通过一系列状态单独运行:分配,准备,运行等。如果任务失败,调度器将删除该任务及其容器,然后根据服务所需的状态创建一个新任务来替代原来的任务。

Swarm集群的基础逻辑包括 通用调度器编排器。服务和任务均具有抽象性,而将其类型是不可知。假设我们要实现其他类型的任务,比如虚拟机任务或非容器化任务。调度器和编排器对于任务的类型是不可知的。但是,目前Docker只支持容器任务。

Swarm模式下如何接受服务并创建任务,以及将任务分派到其他节点,如下图所示。

调度器与编排器

复制及全局服务

Swarm模式下有两种服务的部署方式,复制服务全局服务

复制服务模式下,我们需要制定将要运行的任务副本的数量。比如,部署一个具有三个任务副本的HTTP监控服务,每个任务都具有相同的内容。

全局服务模式下,每个节点均运行一个服务的任务副本,不需要指定任务副本的数量。当新的节点加入Swarm集群后,编排器则创建新的任务并将其分派到该节点。监控服务,反病毒扫描程序或者其他类型的容器都是比较好的全局服务的对象。

PKI工作原理

Docker引擎中内置的公钥基础设施(Public Key Infrastructure)系统使得容器的部署和编排变得更加简单和安全。Swarm集群中的节点使用传输层安全(TLS)来认证,授权和加密它们与集群中其他节点的通信。

当我们使用命令docker swarm init创建一个Swarm集群时,Docker引擎则将当前节点视为一个管理节点。默认情况下,管理节点自身生成一个新的跟证书颁发机构(CA)以及密钥对,以保护与加入集群的其他节点的通信。当然,也可以通过配置–external-ca参数来指定外部的根证书颁发机构。

与此同时,管理节点还生成两个token值(用于向Swarm集群中加入节点),一个是工作节点token值,另一个是管理节点token值。每一个token值都包含根CA证书的摘要和随机生成的密钥。当节点加入集群时,它使用摘要来验证远程管理节点的根CA证书,使用密钥来确保该节点是经过批准的节点。

# 创建一个swarm
$ docker swarm init
# 查看管理节点和工作节点的加入命令
# 向Swarm中加入管理节点 docker swarm join-token manager
# 向Swarm中加入工作节点 docker swarm join-token worker
$ docker swarm join-token manager
To add a manager to this swarm, run the following command:

    docker swarm join \
    --token SWMTKN-1-35n1uqy8q7si9lvkapojdkxjcntl5uixtdg1xo0ib3b2sg9t8g-86w02153sf0kbncz42aoa41p9 \
    10.0.2.15:2377
$ docker swarm join-token worker
To add a worker to this swarm, run the following command:

    docker swarm join \
    --token SWMTKN-1-35n1uqy8q7si9lvkapojdkxjcntl5uixtdg1xo0ib3b2sg9t8g-6t4a6w0shlr78nc55hh9si3ll \
    10.0.2.15:2377
# 通过对比可以发现,管理节点和工作节点使用的是不同的token值
# 两个token值的前半部分是一样的,即根证书的摘要是一样的;后半部分是不一样的,即随机生成的密钥

每次当新的节点加入Swarm集群时,管理节点向包含随机生成的节点ID颁发证书,用来标识证书通用名(CN)下的节点和组织名(UN)下的角色。节点ID用来标识Swarm集群中节点寿命的密码安全。

PKI工作原理