首页 理论教育 无注册中心DockerSwarm的运行状况

无注册中心DockerSwarm的运行状况

时间:2023-11-05 理论教育 版权反馈
【摘要】:假设有一个三节点的集群,其中两个节点运行Swarm manager,另一个节点运行Swarm worker。manager接受请求,决定要做什么,并将任务发送给Swarm worker。图4-3Swarm节点将任务转换为Docker Engine命令Docker Engine收到Swarm worker的命令并开始执行,如图4-4所示。我们将向node-1上的Swarm manager发送请求,它将查询其在内部存储的集群状态,并做出决定,例如,在node-2上运行新实例。接下来worker会将任务转换为Docker命令,并将其发送给本地引擎。那我们将没有manager可用,或者被迫使用node-2上的manager。

无注册中心DockerSwarm的运行状况

假设有一个三节点的集群,其中两个节点运行Swarm manager,另一个节点运行Swarm worker。manager接受请求,决定要做什么,并将任务发送给Swarm worker。然后worker将这些任务转换为发送给本地Docker Engine的命令,manager同时也是worker。

如果我们描述之前为go-demo服务所做的流程,并且假设没有与Swarm相关的服务发现功能,它会像下面这样。

用户向其中一个manager发送请求,这个请求不是声明性指令,而是对期望状态的一个表述。例如,我想在集群内部运行两个go-demo服务实例和一个DB实例,如图4-1所示。

图4-1 用户发送请求给其中一个manager

一旦Swarm manager收到我们对期望状态的请求,它就会将其与集群的当前状态进行比较,生成任务,然后将它们发送给Swarm worker。任务可能是在node-1和node-2上运行go-demo服务的实例,以及在node-3上运行go-demo-db服务的实例,如图4-2所示。

图4-2 Swarm manager将期望状态与集群的当前状态进行比较,生成任务,然后将它们发送给Swarm worker

Swarm worker从管理器接收任务,再将它们转换为Docker Engine命令,并将它们发送给本地Docker Engine实例,如图4-3所示。

图4-3 Swarm节点将任务转换为Docker Engine命令

Docker Engine收到Swarm worker的命令并开始执行,如图4-4所示。

图4-4 Docker Engine管理本地容器

接下来,假设我们向manager发送新的期望状态。例如,我们可能期望将go-demo实例的数量扩展到3个。我们将向node-1上的Swarm manager发送请求,它将查询其在内部存储的集群状态,并做出决定,例如,在node-2上运行新实例。做出决定后,manager将创建一个新任务并将其发送到node-2上的Swarm worker。接下来worker会将任务转换为Docker命令,并将其发送给本地引擎。执行命令后,我们将在node-2上运行go-demo服务的第三个实例,如图4-5所示。

如果这个流程真像上面描述的话,则会遇到很多问题,这些问题会使这个方案几乎不能使用。

我们试着列举一些将要面对的问题。

图4-5 一个缩放请求发送给了Swarm manager

Swarm manager使用我们发送给它的信息,如果我们一直使用同一个manager,并且集群状态不会因为manager无法控制的因素发生变化,那么这并不会有什么问题。我们需要理解的很重要的一点是,集群的信息并不是只存在一个地方,每个地方的信息也是不完整的。每个manager只知道它自己做过的事情,这样会有什么问题呢?

我们来试一下别的(但并不少见的)情况。(www.xing528.com)

如果我们将扩展到三个实例的请求发送到node-2上的manager会发生什么?node-2上的manager会忽略node-1上的manager中创建的任务,它会尝试运行三个新go-demo服务实例,导致总共有五个实例,node-1上的manager创建了两个实例,node-2上的manager创建了三个实例。

我们会尝试一直只用同一个manager,但在这种情况下会出现单点故障。如果整个node-1挂掉怎么办?那我们将没有manager可用,或者被迫使用node-2上的manager。

许多其他因素都可能会产生这样的偏差。也许其中一个容器意外停止,在这种情况下,当我们决定扩展到三个实例时,node-1上的manager依然会认为此刻有两个实例正在运行,并且会创建任务来运行一个新的实例。最终集群内还是只有两个实例在运行而不是三个。

可能出错的状况清单是列不完的,这里不再举例说明。

需要注意任何一个manager处于隔离状态都是不可接受的。所有的manager都应该拥有相同的信息。另一方面,每个节点都需要监控由Docker Engine生成的事件,并确保把自己服务器的任何更改传播给所有的manager。最后,我们需要监控每台服务器的状态以防止其出现故障。换句话说,每个manager都需要掌握整个集群的最新情况,只有这样,它才能将我们对期望状态的请求准确地转换为分派给Swarm节点的任务。

怎样才能使所有的manager在无论谁改变了集群的情况下都能得到关于整个集群状况的完整视图呢?

这个问题的答案取决于我们设定的需求。我们需要一个工具来存储所有的信息,它得是分布式的,这样一台服务器的故障不会影响功能的正常运行。分布式提供了容错功能,但这本身并不意味着数据要在整个集群中同步。该工具需要在所有的实例中维护数据副本。数据复制并不是什么新东西,只是在这种情况下复制的速度需要很快,以便向它请求的服务可以(近乎)实时地接收数据。此外,我们需要一个系统来监控集群内的每台服务器,并在有任何更改时更新数据。

总之,我们需要一个分布式服务注册中心和一个监控系统。前者最好通过服务注册中心或者键值存储来完成。旧版Swarm(Docker 1.12之前的独立版)支持Consul(https://www.consul.io/)、etcd(https://github.com/coreos/etcd)和Zookeeper(https://zookeeper.apache.org/)。我个人偏向Consul,但三者中的任何一个都没有问题。

有关服务发现和主流服务注册中心比较更详细的讨论,请参阅《微服务运维实战(第一卷)》的相关章节。

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈