Docker Swarm入门(三)Swarm SOA举例


【编者的话】本文作者Matt Bajor热衷Docker及相关产品的研究,本文是他写的Docker Swarm入门系列的第三篇,文中描述了Docker Swarm的SOA架构及其基本的属性,大致介绍了SOA架构的相关的层次,包括程序层、集群层、服务分发层、以及路由层。

Docker Swarm带来的最令人兴奋的功能之一是用非常小的经费就能构建一个现代化的、有弹性的以及灵活的架构。用户能够与由Docker主机构建的多样化的集群进行交互,就好像在与一台集成了现有工具链的主机进行交互一样。用户可以构建他们所需要的全部服务层,之后用一个精美而简单的方式来创建SOA(Service-oriented architecture 面向服务的架构)。

本文将要试图围绕着Docker Swarm描述一个完整的SOA架构,其具有以下属性:
  • 管理程序层由独立的Docker主机组成(Docker/Registrator)
  • 集群层将Docker主机绑在一起(Docker Swarm)
  • 服务发现层(Consul)
  • 路由层在基于Consul有关服务下管理流量(HAProxy/Nginx)


管理程序层

管理程序层由一组离散Docker主机构成。每个主机上都有运行服务,允许其参与集群中的工作:

  • Docker daemon:Docker守护程序被配置之后,用来监听网络端口以及本地Linux socket,这样Swarm守护程序就可以与它进行通信。此外,每一个Dockerhost都配有一系列的标签,之后与Swarm调度器一起工作,来决定容器被置于哪里。它们有助于对Docker主机进行描述,而且不论在哪,任何标识信息都可以与Docker主机相关联。这是一个Docker主机被启动时一组标签的例子:
    • 范围:应用程序/数据库
    • 硬盘:ssd/hdd
    • 环境:开发/生产
  • Swarm daemon:Swarm客户端与Docker守护进程一起运行,以保持该节点在Swarm集群中运行。该Swarm守护进程在合作模式下(join mode)运行并且对Consul发送基本的心跳信号,以保持其记录在/swarm位置的更新。这个记录是Swarm master用来创建集群的。如果此守护进程终止,Consul中的列表应该会被自动升级,并且自动地删除该节点。Swarm客户端在Consul中会使用类似于/swarm一样的路径,它包含了Docker主机的列表:


swarm_section.png

  • Registrator daemon:当创建或者销毁容器时,要使用Registrator来更新Consul。它监听Docker socket,接下来每当有新的事件发生时,Consul的键/值对就会被更新。例如,一个名叫deepthought的应用需要3个在分离的主机并运行在80端口上,于是Consul会创建如下的结构:


services_section.png


模式:
/services/<service>-<port>/<dhost>:<cname>:<cport> 的值是: <ipaddress>:<cport>
  • service:容器的镜像名字
  • port:容器公开的端口
  • dhost:容器运行的Docker主机
  • cport:容器公开的端口
  • ipaddress:容器运行的Docker主机的ip地址


docker ps 会输出以下类似信息:
$ docker ps
CONTAINER ID        IMAGE                       COMMAND                CREATED             STATUS              PORTS                                   NAMES
097e142c1263        mbajor/deepthought:latest   "nginx -g 'daemon of   17 seconds ago      Up 13 seconds       10.100.199.203:49166->80/tcp   dockerhost03/grave_goldstine
1f7f3bb944cc        mbajor/deepthought:latest   "nginx -g 'daemon of   18 seconds ago      Up 14 seconds       10.100.199.201:49164->80/tcp   dockerhost01/determined_hypatia
127641ff7d37        mbajor/deepthought:latest   "nginx -g 'daemon of   20 seconds ago      Up 16 seconds       10.100.199.202:49158->80/tcp   dockerhost02/thirsty_babbage

这是记录服务及位置的最基本的方法。 Registrator还支持和容器一起传递元数据,这里传递的元数据通常会包含服务的关键信息

另一个要提的是,Registrator的开发者似乎想要将其作为一个守护进程运行在Docker容器内。由于Docker Swarm集群被当做是一台Docker主机,我宁愿Registrator应用作为守护程序运行在Docker主机上。这样,即使没有容器在集群上运行,群集仍然可以正常运作。这一点似乎可以用来对平台和应用两个概念进行区分。

集群层

Docker master服务正是运行在这一层上。对其进行配置后,就可以读取在/swarm前缀下Consul的键/值对,之后它根据这些键/值信息可以产生节点信息列表。同时它也在监听客户端与Docker(创建,删除,等..)的链接并且可以把这些请求发送给那些合适的后台Docker主机,这意味着,它要具有以下需求:
  • 能够监听网络
  • 能够与Consul通信
  • 能够与所有的Docker守护进程进行通信


目前我还没有看到如何让Swarm守护程序本身保持高可用性的相关内容,但使用了一段时间之后,我发现这确实是一个值得研究的问题。我希望可以把支持TCP的负载均衡代理(比如HAProxy)放在几个Swarm守护进程的前端,以合理分发流量。相黏会话机制(Sticky sessions)必须启用,如果不同的Swarm守护进程之间涉及到同步的问题,采用积极或者消极的机制(active/passive)都是可以的,至少现在看起来以上方案似乎是可行的。在实际情况中,即使是在Swarm出现故障的情况下,容器仍然可以继续运行并且是可以访问的,我们宁可接受一个不具备高可用性的Swarm结点,也不愿意增加其复杂性和由于负载均衡导致的多余开销。

服务发现层

服务发现层运行在一个由Consul结点构建的集群上,具体来说它主要负责键/值存储。为了维持法定个数(n/2 + 1个节点)即使在出现故障的情况下节点数也应该是个奇数。Consul服务有许多特征,这里仅举几例,比如包括自动服务发现、健康检查与键/值存储。我们只使用了键/值存储,但我希望将Consul集成到你自己的架构之后,其相关的特性能带给你诸多好处。对于此配置示例,以下是处理键/值存储的步骤:
  • 在Docker主机的Swarm客户端会在/swarm中注册
  • Swarm master会读取/swarm以构建其Docker主机列表
  • 该Registrator守护进程会在/services前缀的目录中加入或者删除结点
  • Consul-template会读取键/值存储为路由层生成配置


这是用于存储所有群集的元数据的中央数据。Consul中的每个条目主要是用来对Docker主机上的容器和路由终端入口进行绑定。

Consul也有一个可安装的GUI(图形化用户界面)而且我强烈建议安装它用来开发工作。它可以使你搞清楚什么已经被注册以及哪里更容易做。一旦集群启动并运行,你可能就不再需要它了。

路由层

这是一个边缘层,而且所有外部应用流量都将贯穿其中。这些节点都在Swarm集群的边缘,他们都有静态IP并且具有可以定位到群集上的任何服务的DNS条目。这些节点监听端口80/443等,并且运行着以下服务:

  • Consul-template:此服务用于拉取consul的键/值存储对(在/services下)当它检测变化时,会写入新的HAProxy/Nginx配置并优雅地重新加载该服务。这些模板是用Go编写的以及输出的应该是标准的HAProxy或Nginx形式。

  • HAProxy或Nginx:这些服务器都是在实际应用中被充分验证过的,它们已经帮你准备好任何你运行服务所需要的东西,虽然是处在集群边缘。该服务被Consul-template动态地配置并且在需要时重新被加载。一种经常会发生的变化是对于一个特定的虚拟主机列表的修改。由于列表中所维护的内容全是当前在运行的服务,在Consul中,对于列表的修改和容器的变化一样频繁。


以上内容是基于SOA的一个对Docker Swarm集群的简要概述。在接下来的文章中,我将演示一个上述在Vagrant环境下的工作基础设施。这篇文章将会在Docker Denver Meetup 后发布,敬请关注!

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


原文链接:Intro to Docker Swarm: Part 3 - Example Swarm SOA (翻译:田浩浩 校对:王哲)

===========================
译者介绍
田浩浩,悉尼大学USYD硕士研究生,目前在珠海从事Android应用开发工作。业余时间专注Docker的学习与研究,希望通过DockerOne把最新最优秀的译文贡献给大家,与读者一起畅游Docker的海洋。

------------------------------------------
Docker Swarm入门(一)概观
Docker Swarm入门(二)配置选项与需求
Docker Swarm入门(三)Swarm SOA举例

7 个评论

你好,问下有swarm+Consul+Consul UI的配置文档么?谢谢
作者你好,咨询下:“cport:容器公开的端口” 以及 “port:容器公开的端口”有何区别?
port: service的暴露的端口 cport是 容器内暴露的端口
田老师,您好:
最近我在学习swarm集群,并准备运用到我们的开发和测试环境上。看到您的文章后,对我学习swarm的帮助很大。但是也有一些疑问:
1.运行在swarm上的服务,能不能不和宿主机做端口映射,如果和宿主机做端口映射的话,我要是运行另外其他的docker容器,是不是需要考虑宿主机端口冲突的问题?是不是不做端口映射就没法在swarm集群之外 访问这些服务了?
2.关于您文章的路由层,这块的问题。您说 nginx和 haproxy 位于swarm集群的边缘,是不是可以理解为脱离swarm运行的?例如,nginx和haproxy 是直接 安装到宿主机上的,如果是直接安装到宿主机上的话,nginx 配置里的upstream 怎么配置和连接 swarm 集群里运行的后端服务?

如果不是脱离swarm集群上运行的,那么在swarm集群外怎么访问 nginx 和 haproxy,和宿主机做端口映射?

麻烦 田老师 解答一下我的疑问。 期待您的回复。 谢谢
1 不和宿主机做端口映射: 不指定-p就可以, 不做端口映射 外部是访问不到的 但是在同一个 docker network下service之间可以互相访问的
2 如果 脱离swarm, nginx 配置docker container的 ip
如果使用swarm service 运行代理容器, 可以开放映射80端口, 然后代理容器内配置各种容器服务
2 如果还不是很明白的话, 请尝试结合https://traefik.io/来理解

要回复文章请先登录注册