问题导读
1.Docker Swarm支持Consul发现,原理是什么?
2.类同可以以哪两种方式工作?
上一篇:
Docker Swarm入门(一)概观
【编者的话】本文作者Matt Bajor 热衷Docker及相关产品的研究,本文是他写的Docker Swarm入门系列的第二篇,主要介绍了Docker Swarm的最基本的配置选项和运行要求。作者通过实际例子介绍了Swarm的几个基本的发现服务及其对于容器调度策略,最后还介绍了如何在Swarm集群通信中使用安全传输协议。
Docker Swarm集群运行环境的最低要求 创建基本的Docker Swarm集群对运行环境要求并不是很高。事实上,我们可以将Swarm守护进程运行在现有的Docker主机上,使其在不添加任何其他的硬件或虚拟资源的情况下就能够直接运行,这种方式绝对是可行的(也许不是最好的做法)。此外,在运行最基本的Docker Swarm集群的过程中,在基于发现机制 识别文件或节点的时候,并不需要添加其他的基础设施(当然除了Docker本身)。
我个人认为在另一台服务器上运行Swarm master服务本身是一个不错的想法。该服务器并不需要大量的资源,但它却需要用很多的文件描述符来处理所有的TCP流量的输入和输出。在下面例子中,我会使用dockerswarm01来作为专用的Swarm master服务。
配置选项 在默认情况下Swarm有各种各样的配置,当涉及到运行守护进程及其配套的基础设置时,配置过程的灵活性就变得很强。下面列出了不同类别的配置选项以及它们是如何进行配置的。
发现服务 Swarm使用的发现服务是一种维护集群状态的机制。它可以与各种后端服务协同工作,基本的工作流程都是一致的,都涉到及以下的概念:
后端服务维护着Docker结点的列表,这些服务应该是集群的一部分。 通过节点的列表,Swarm 会检查每一个结点的健康状况并且跟踪进出集群的节点。
节点发现 节点发现仅需要通过命令行来完成。这是最基本的发现机制类型,它并不需要对配置文件或者其他相关内容进行维护。Swarm守护进程使用节点发现的启动命令会是这样:
swarm manage \
--discovery dockerhost01:2375,dockerhost02:2375,dockerhost03:2375 \
-H=0.0.0.0:2375 复制代码
文件发现 文件发现利用放置在文件系统中 (例如:/etc/swarm/cluster_config)的配置文件,使用<IP>:<Port>的格式来列出集群中的Docker主机。虽然该列表是静态的,但是通过健康检查服务仍然可以确定健康和不健康的节点,并且可以过滤对不健康的节点请求。基于文件的发现的启动命令和配置文件的例子如下:
sswarm manage \
--discovery file:///etc/swarm/cluster_config \
-H=0.0.0.0:2375 复制代码
#/etc/swarm/cluster_config
dockerhost01:2375
dockerhost02:2375
dockerhost03:2375 复制代码
Consul发现 Docker Swarm也支持Consul 发现。它的工作原理是利用Consul的键值存储,来维护构成集群的服务器的<IP>:<Port>列表。在这种配置模式下,每个Docker主机会以join模式运行一个Swarm守护进程,并且指向Consul集群的HTTP接口(进行服务注册)。这样的操作使Docker主机的配置、运行以及安全维护产生了一定的开销,但开销并不大。Swarm客户端将会进行这样的操做:
swarm join --discovery consul://consulhost01/swarm \
# This can be an internal IP as long as the other
# Docker hosts can reach it.
--addr=10.100.199.200:2375 复制代码
之后Swarm master会从Consul服务中读取主机列表,它可以这样的方式运行:
swarm manage --discovery consul://consulhost01/swarm -H=0.0.0.0:2375 复制代码
这些基于键/值的基本配置模式会引发一个问题:Swarm集群的健康状况检查服务如何与Swarm客户端(在 join模式下)协同工作?由于通过键/值存储的列表本身就是动态的,它是否需要运内部Swarm健康检查服务呢?我对相关的功能并不熟悉,所以不妄加评论,但这个问题应该引起注意。
EtcD发现 EtcD 发现的工作方式与Consul发现大致相同。集群中的每个Docker主机会以join模式运行一个Swarm守护进程,并指向一个EtcD的终端(endpoint)。这样EtcD可以通过心跳检测来维护一个记录集群中活跃服务器(active servers)的列表。一个运行有标准Docker守护进程的Docker主机会同时运行一个具有类似配置Swarm客户端:
swarm join \
--discovery etcd://etcdhost01/swarm \
--addr=10.100.199.200:2375 复制代码
通过以下命令,Docker Swarm master 服务会连接EtcD,搜寻所提供的路径信息并且成节点列表:
swarm manage \
--discovery etcd://etcdhost01/swarm \
-H=0.0.0.0:2375 复制代码
Zookeeper发现 Zookeeper 发现模式与其他基于键/值对存储的配置模式类似。一个ZK集合被创建之后用于保存主机信息列表同时还有一个与Docker一起运行的客户端,这个客户端可以向键/值存储服务发送心跳检测信息,几乎可以实时地维护列表。Swarm master也会连接到ZK集合并使用/swarm路径下的的信息来维护主机列表(之后会进行健康检测)。
Swarm客户端(与Docker一起):
swarm join \
# All hosts in the ensemble should be listed
--discovery zk://zkhost01,zkhost02,zkhost03/swarm \
--addr=10.100.199.200 复制代码
Swarm Master:
swarm manage \
--discovery zk://zkhost01,zkhost02,zkhost03/swarm \
-H 0.0.0.0:2375 复制代码
Hosted Token Based Discovery (默认) 我还没有使用过这个功能,在这点上没多少能总结的。
调度 调度的机制主要的功能是选择在哪个服务器上创建并启动一个容器。它是由一个装箱算法(packing algorithm)和过滤器(或标签)组合而成。每个Docker守护进程启动的时候都带着一组标签,像以下这样:
docker -d \
--label storage=ssd \
--label zone=external \
--label tier=data \
-H tcp://0.0.0.0:2375 复制代码
然后,当开启一个Docker容器时,Swarm将基于过滤器选择一组服务器,然后根据调度机制来分配每次运行的命令。过滤器会告诉Swarm哪写服务器上的容器是可用的或是不可用的,之后调度器会把命令分发到可用的服务器上。以下是几个过滤机制:
约束(Constraint) 这是利用了一个Docker守护程序开始的标签。目前,它只支持'=',(译注:官方doc 里是'==',请读者遵循最新的官方doc)但在将来它可能支持'!='。节点必须符合所有的由容器提供的约束以便能进行匹配调度。比如按照下面的例子来开启有一些约束的容器:
docker run -d -P \
-e constraint:storage=ssd \
-e constraint:zone=external \
-t nginx 复制代码
一旦Swarm将主机列表限制在一组符合上述条件的节点上,它就会让对容器进行调度,从以上结点中选出一个,在上面创建并启动容器。目前以下调度是器内置的:
随机分配(Random) 将容器随机分布在可用的结点上。 装箱(Binpacking) 用容器将节点填满(每个容器得到资源固定),然后在移动到下一个节点。如果在运行时需要动态地给容器分配资源,采用这个策略可能会使过程变得更复杂。这意味着即使为每个容器的内存和CPU设置上限,也并不能保证运行期间一切正常。我个人比较喜欢让容器彼此之间竞争,看哪个容器能得到资源。
还有一些其他的调度机制正在开发中,比如平衡策略 以及添加Apache Mesos 的特性。
TLS(传输层安全协议Transport Layer Security ) 令人高兴的是,Swarm可以在TLS启用下运行。这使得客户端、Swarm守护进程以及Docker守护程序之间的交互变更安全。这是一件好事,因为我的研究安全方面的伙伴看来,在网络中并没有边界。
为了实现以上目标,需要一个包含CA的完整PKI,但我有个解决办法,在另一篇已发布的文章里会提到,它是如何为Docker与Swarm产生所需的TLS证书 。
按照上面博客中的内容,一旦证书生成并安装,Docker与Swarm守护进程就可以进行如下操作:
Docker:
docker -d \
--tlsverify \
--tlscacert=/etc/pki/tls/certs/ca.pem \
--tlscert=/etc/pki/tls/certs/dockerhost01-cert.pem \
--tlskey=/etc/pki/tls/private/dockerhost01-key.pem \
-H tcp://0.0.0.0:2376 复制代码
Swarm master:
swarm manage \
--tlsverify \
--tlscacert=/etc/pki/tls/certs/ca.pem \
--tlscert=/etc/pki/tls/certs/swarm-cert.pem \
--tlskey=/etc/pki/tls/private/swarm-key.pem \
--discovery file:///etc/swarm_config \
-H tcp://0.0.0.0:2376 复制代码
然后客户端必须知道TLS连接。以下是环境变量设置:
export DOCKER_HOST=tcp://dockerswarm01:2376
export DOCKER_CERT_PATH="`pwd`"
export DOCKER_TLS_VERIFY=1 复制代码
这样你就设置好了TLS。
还有更多精彩内容! 当涉及到复杂的集群软件的配置时,还有很多内容可以讨论,但我觉得对于一个概述性的介绍来说,以上内容已经足够,这可以让你设置、运行并思考如何配置你的Swarm集群。下一篇博客中我会介绍关与Swarm集群架构的一些例子。敬请关注,并欢迎在下面发表评论!
所有这些在博文背后的研究能成为可能归功于我工作的公司: Rally Software in Boulder, CO. 。每季度我们至少有一个骇客周,它使我们能够研究很棒的东西,像Docker Swarm。如果您想切入正题,直接开始Vagrant 例子,这里有一个repo,它是我在2014年Q1骇客周研究的成果: