分享

Docker Swarm入门(二)配置选项与基本运行环境要求

pig2 发表于 2015-3-4 23:51:56 [显示全部楼层] 只看大图 回帖奖励 阅读模式 关闭右栏 4 29926
问题导读

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守护进程使用节点发现的启动命令会是这样:
  1. swarm manage \
  2. --discovery dockerhost01:2375,dockerhost02:2375,dockerhost03:2375 \
  3. -H=0.0.0.0:2375
复制代码


文件发现文件发现利用放置在文件系统中 (例如:/etc/swarm/cluster_config)的配置文件,使用<IP>:<Port>的格式来列出集群中的Docker主机。虽然该列表是静态的,但是通过健康检查服务仍然可以确定健康和不健康的节点,并且可以过滤对不健康的节点请求。基于文件的发现的启动命令和配置文件的例子如下:
  1. sswarm manage \
  2. --discovery file:///etc/swarm/cluster_config \
  3. -H=0.0.0.0:2375
复制代码


  1. #/etc/swarm/cluster_config
  2. dockerhost01:2375
  3. dockerhost02:2375
  4. dockerhost03:2375
复制代码


Consul发现Docker Swarm也支持Consul发现。它的工作原理是利用Consul的键值存储,来维护构成集群的服务器的<IP>:<Port>列表。在这种配置模式下,每个Docker主机会以join模式运行一个Swarm守护进程,并且指向Consul集群的HTTP接口(进行服务注册)。这样的操作使Docker主机的配置、运行以及安全维护产生了一定的开销,但开销并不大。Swarm客户端将会进行这样的操做:
  1. swarm join --discovery consul://consulhost01/swarm \
  2. # This can be an internal IP as long as the other
  3. # Docker hosts can reach it.
  4. --addr=10.100.199.200:2375
复制代码


之后Swarm master会从Consul服务中读取主机列表,它可以这样的方式运行:
  1. 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客户端:
  1. swarm join \
  2. --discovery etcd://etcdhost01/swarm \
  3. --addr=10.100.199.200:2375
复制代码


通过以下命令,Docker Swarm master 服务会连接EtcD,搜寻所提供的路径信息并且成节点列表:
  1. swarm manage \
  2. --discovery etcd://etcdhost01/swarm \
  3. -H=0.0.0.0:2375
复制代码



Zookeeper发现Zookeeper发现模式与其他基于键/值对存储的配置模式类似。一个ZK集合被创建之后用于保存主机信息列表同时还有一个与Docker一起运行的客户端,这个客户端可以向键/值存储服务发送心跳检测信息,几乎可以实时地维护列表。Swarm master也会连接到ZK集合并使用/swarm路径下的的信息来维护主机列表(之后会进行健康检测)。

Swarm客户端(与Docker一起):
  1. swarm join \
  2. # All hosts in the ensemble should be listed
  3. --discovery zk://zkhost01,zkhost02,zkhost03/swarm \
  4. --addr=10.100.199.200
复制代码


Swarm Master:
  1. swarm manage \
  2. --discovery zk://zkhost01,zkhost02,zkhost03/swarm \
  3. -H 0.0.0.0:2375
复制代码


Hosted Token Based Discovery (默认)我还没有使用过这个功能,在这点上没多少能总结的。
调度调度的机制主要的功能是选择在哪个服务器上创建并启动一个容器。它是由一个装箱算法(packing algorithm)和过滤器(或标签)组合而成。每个Docker守护进程启动的时候都带着一组标签,像以下这样:
  1. docker -d \
  2. --label storage=ssd \
  3. --label zone=external \
  4. --label tier=data \
  5. -H tcp://0.0.0.0:2375
复制代码


然后,当开启一个Docker容器时,Swarm将基于过滤器选择一组服务器,然后根据调度机制来分配每次运行的命令。过滤器会告诉Swarm哪写服务器上的容器是可用的或是不可用的,之后调度器会把命令分发到可用的服务器上。以下是几个过滤机制:
  • 约束(Constraint) 这是利用了一个Docker守护程序开始的标签。目前,它只支持'=',(译注:官方doc里是'==',请读者遵循最新的官方doc)但在将来它可能支持'!='。节点必须符合所有的由容器提供的约束以便能进行匹配调度。比如按照下面的例子来开启有一些约束的容器:

  1. docker run -d -P \
  2. -e constraint:storage=ssd \
  3. -e constraint:zone=external \
  4. -t nginx
复制代码


  • 类同(Affinity )
    类同可以以两种方式工作:容器类同或镜像类同。为了在同一台主机上启动两个容器可以运行以下命令:
    1. docker run -d -P \
    2. --name nginx \
    3. -t nginx
    4. docker run -d -P \
    5. --name mysql \
    6. -e affinity:container=nginx \
    7. -t mysql
    复制代码


    由于Swarm并没有对镜像进行管理,设置类同镜像也是可行的。这意味着一个容器仅能在已包含镜像的节点上启动。这就避免了在开启一个容器之前需要在后台等待拉取镜像的过程。举个例子:
    1. docker run -d -P \
    2. --name nginx \
    3. -e affinity:image=nginx \
    4. -t nginx
    复制代码

  • 端口(Port) 端口过滤可以防止在同一主机上任意两个具有相同的静态端口映射的容器启动。这样做的意义很大,你不能重复在Docker主机上端口映射。例如,两个节点以-p 80:80开启不会被允许在同一Docker主机上运行。
  • 健康状况(Healthy) 它阻止了对不健康节点进行调度。

一旦Swarm将主机列表限制在一组符合上述条件的节点上,它就会让对容器进行调度,从以上结点中选出一个,在上面创建并启动容器。目前以下调度是器内置的:
  • 随机分配(Random) 将容器随机分布在可用的结点上。
  • 装箱(Binpacking) 用容器将节点填满(每个容器得到资源固定),然后在移动到下一个节点。如果在运行时需要动态地给容器分配资源,采用这个策略可能会使过程变得更复杂。这意味着即使为每个容器的内存和CPU设置上限,也并不能保证运行期间一切正常。我个人比较喜欢让容器彼此之间竞争,看哪个容器能得到资源。

还有一些其他的调度机制正在开发中,比如平衡策略以及添加Apache Mesos的特性。

TLS(传输层安全协议Transport Layer Security令人高兴的是,Swarm可以在TLS启用下运行。这使得客户端、Swarm守护进程以及Docker守护程序之间的交互变更安全。这是一件好事,因为我的研究安全方面的伙伴看来,在网络中并没有边界。
2a9a1d863a6fbe1e43e687924f23df80.jpg

为了实现以上目标,需要一个包含CA的完整PKI,但我有个解决办法,在另一篇已发布的文章里会提到,它是如何为Docker与Swarm产生所需的TLS证书

按照上面博客中的内容,一旦证书生成并安装,Docker与Swarm守护进程就可以进行如下操作:
Docker:
  1. docker -d \
  2. --tlsverify \
  3. --tlscacert=/etc/pki/tls/certs/ca.pem \
  4. --tlscert=/etc/pki/tls/certs/dockerhost01-cert.pem \
  5. --tlskey=/etc/pki/tls/private/dockerhost01-key.pem \
  6. -H tcp://0.0.0.0:2376
复制代码


Swarm master:
  1. swarm manage \
  2. --tlsverify \
  3. --tlscacert=/etc/pki/tls/certs/ca.pem \
  4. --tlscert=/etc/pki/tls/certs/swarm-cert.pem \
  5. --tlskey=/etc/pki/tls/private/swarm-key.pem  \
  6. --discovery file:///etc/swarm_config \
  7. -H tcp://0.0.0.0:2376
复制代码


然后客户端必须知道TLS连接。以下是环境变量设置:
  1. export DOCKER_HOST=tcp://dockerswarm01:2376
  2. export DOCKER_CERT_PATH="`pwd`"
  3. export DOCKER_TLS_VERIFY=1
复制代码


这样你就设置好了TLS。

还有更多精彩内容!当涉及到复杂的集群软件的配置时,还有很多内容可以讨论,但我觉得对于一个概述性的介绍来说,以上内容已经足够,这可以让你设置、运行并思考如何配置你的Swarm集群。下一篇博客中我会介绍关与Swarm集群架构的一些例子。敬请关注,并欢迎在下面发表评论!

所有这些在博文背后的研究能成为可能归功于我工作的公司: Rally Software in Boulder, CO.。每季度我们至少有一个骇客周,它使我们能够研究很棒的东西,像Docker Swarm。如果您想切入正题,直接开始Vagrant 例子,这里有一个repo,它是我在2014年Q1骇客周研究的成果:





已有(4)人评论

跳转到指定楼层
18177114672 发表于 2016-10-29 21:34:02
环境变量是加到那个文件啊?
export DOCKER_HOST=tcp://Server:2375
export DOCKER_CERT_PATH="`pwd`"
export DOCKER_TLS_VERIFY=1
".bashrc" 102L, 3202C written                                            
root@Docker:~# source .bashrc
root@Docker:~# docker info
The server probably has client authentication (--tlsverify) enabled. Please check your TLS client certification settings: Get https://Server:2375/v1.24/info: remote error: bad certificate

怎么会报错呢?
回复

使用道具 举报

18177114672 发表于 2016-10-29 21:38:31
pwd是什么意思呢?是swarm的路径还是本机的呢?
回复

使用道具 举报

NEOGX 发表于 2016-10-30 09:23:57
18177114672 发表于 2016-10-29 21:34
环境变量是加到那个文件啊?
export DOCKER_HOST=tcp://Server:2375
export DOCKER_CERT_PATH="`pwd`"

虽然设置了,但是没有提供客户端certificate英文不错的话,可以参考这个


https://integratedcode.us/2015/07/29/using-tls-with-the-docker-engine/


https://github.com/docker/toolbox/issues/255
回复

使用道具 举报

18177114672 发表于 2016-10-30 17:46:25
NEOGX 发表于 2016-10-30 09:23
虽然设置了,但是没有提供客户端certificate英文不错的话,可以参考这个

# docker info
The server probably has client authentication (--tlsverify) enabled. Please check your TLS client certification settings: Get https://Server:2376/v1.24/info: remote error: bad certificate
这样的输出是什么情况啊?

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条