七夕你们过得怎么样?今天数人云带你们回归技术和干货。虽然咱们可以在Swarm集群当中部署任意数量的服务,但这并不表明各项服务所有可为用户所访问。而新的Swarm网络使得各项服务之间可以更为轻松地实现彼此通讯。node
下面咱们将共同探讨如何利用其对各服务进行公开。咱们还将尝试将一套代理机制整合至Swarm网络当中,从而更为充分地发挥1.12版本带来的优点。nginx
在开始进行以前,咱们须要设置一套用于演示的集群。docker
要完成本示例,咱们假定你们已经拥有一套版本为v0.8或者更高的Docker Machine,其中包含版本为v1.12或者更高的Docker Engine。最便捷的获取方法就是经过Docker Toolbox下载。数据库
若是您是Windows用户,请利用Git Bas运行所有示例(经过Docker Toolbox安装)。后端
docker-machine create -d virtualbox node-1 docker-machine create -d virtualbox node-2 docker-machine create -d virtualbox node-3 eval $(docker-machine env node-1) docker swarm init \ --advertise-addr $(docker-machine ip node-1) \ --listen-addr $(docker-machine ip node-1):2377 TOKEN=$(docker swarm join-token -q worker) eval $(docker-machine env node-2) docker swarm join \ --token $TOKEN \ $(docker-machine ip node-1):2377 eval $(docker-machine env node-3) docker swarm join \ --token $TOKEN \ $(docker-machine ip node-1):2377`
如今咱们已经拥有了一套Swarm集群,接下来是部署一项服务。服务器
包含三个节点的Docker Swarm集群网络
为了检验新的Docker Swarm网络功能,咱们首先建立如下两套网络。负载均衡
eval $(docker-machine env node-1) docker network create --driver overlay proxy docker network create --driver overlay go-demo
其一(proxy)将用于代理与面向API公开的服务之间的通讯。而其二(go-demo)则面向所有用于构建go-demo服务的容器。该服务包含两套容器,且利用MongoDB用于存储数据,而vfarcic/go-demo则做为配备API的后端。frontend
咱们将从数据库起步。因为其不会公共开放,所以不须要将其添加至代理当中。这里,咱们直接将其附加至go-demo网络。curl
docker service create --name go-demo-db \ --network go-demo \ mongo
数据库上线并开始运行后,咱们接下来部署后端。因为咱们但愿外部用户可以使用该API,所以应当将其归入代理。咱们将其同时附加至两套网络(proxy与go-demo)。
docker service create --name go-demo \ -e DB=go-demo-db \ --network go-demo \ --network proxy \ vfarcic/go-demo
由三台节点、两套网络与多套容器构成的Docker Swarm集群
如今两套容器都运行在集群当中,且可以彼此经过go-demo网络进行通讯。下面将代理引入其中。咱们这里使用HAProxy。
须要注意的是,咱们并无指定端口,这意味着没有任何一套容器可以为go-demo网络以外的请求所访问。
咱们能够经过多种方式创建代理机制。其一利用HAProxy建立一套新镜像,其中包含各配置文件。这种方式比较适合服务数量相对固定的状况。不然,咱们应当建立一套每当有新服务(而非新版本发布)出现时即进行新配置的镜像。
经过第二种方法,其将以分卷形式存在,咱们可以在必要时仅修改配置文件而非整套新镜像。然而,这种做法也存在弊端。在部署至一套集群时,咱们应当尽量避免使用分卷。接下来你们会看到,代理就是不须要分卷的机制之一。另外,--volume可替换为docker service命令中的—mount参数。
第三种选项是使用专门与Docker Swarm协做的代理之一。在这种状况下,咱们将使用vfarcic/docker-flow-proxy容器,其由Docker Flow: Proxy项目建立而成。其基于HAProxy且拥有多项其它功能,容许咱们经过发送HTTP请求对其进行从新配置。
下面一块儿来看:
docker service create --name proxy \ -p 80:80 \ -p 443:443 \ -p 8080:8080 \ --network proxy \ -e MODE=swarm \ vfarcic/docker-flow-proxy`
咱们开启的端口80与443将负责处理互联网流量(HTTP与HTTPS)。第三个端口则为8080,咱们将利用它向代理发送配置请求。另外,咱们强调其应当归属于proxy网络。如此一来,因为go-demo也被附加至同一套网络,意味着代理可以经过SDN对其进行访问。
在这套代理的帮助下,咱们实现了最实用的网络路由功能之一。不管你们在哪台服务器上运行该代理,咱们都可以向任意节点发送请求,而Docker网络会确保其被从新定向至代理之一。
最后一项参数为环境变量MODE,其负责告知该代理,各容器将被部署至Swarm集群当中。请参阅项目的README文件以了解更多细节信息。
配合代理服务的Docker Swarm集群
须要注意的是,该代理即便已经运行在某一节点当中,仍会被放置于其外以表达其在逻辑上的分离特性。
在开始以前,首先确认代理正在运行。
docker service ps proxy
若是其“最新状态(Last state)”为“运行(Running)”,则可继续。若是否则,请等待直到该服务上线并开始运行。
如今代理已经部署完成,咱们应当确保其知晓go-demo服务的存在。
curl "$(docker-machine ip node-1):8080/v1/docker-flow-proxy/reconfigure?serviceName=go-demo&servicePath=/demo&port=8080"
这条请求的做用是从新配置代理以指定服务名称(go-demo)、API的URL路径(/demo)以及该服务的内部端口(8080)。从如今开始,全部指向该代理且使用以/demo开头路径的请求都将被从新定向至go-demo服务。
如今咱们能够测试代理是否按预期运行——发送一条HTTP请求进行验证。
curl -i $(docker-machine ip node-1)/demo/hello
该curl命令的输出结果以下所示。
HTTP/1.1 200 OK Date: Mon, 18 Jul 2016 23:11:31 GMT Content-Length: 14 Content-Type: text/plain; charset=utf-8 hello, world!
代理正常起效!它响应了HTTP status 200并向API返回了hello,world!
须要注意的是,这一过程与咱们执行操做所在的具体节点无关。因为Docker网络(路由体系)负责实现负载均衡,所以咱们可以前往任意服务器。做为示例,下面咱们发送一样的请求,但这一次立足于node-3。
curl -i $(docker-machine ip node-3)/demo/hello
结果仍然彻底相同。
下面让咱们一块儿了解由该代理生成的配置。
若是你们选择自行构建代理解决方案,那么固然须要了解如何配置代理并利用Docker网络中的各项新功能。
下面首先检查Docker Flow: Proxy为咱们建立的配置。咱们能够进入当前运行的容器并经过/cfg/haproxy.cfg文件查看这部分信息。不过问题是,找到由Docker Swarm运行的一套容器须要配合一点技巧。举例来讲,若是咱们利用Docker Compose部署此容器,那么其名称会存在必定规律,即便用__格式。而docker service命令会利用散列后的名称运行容器。在个人笔记本上,docker-flow-proxy的建立名称为proxy.1.e07jvhdb9e6s76mr9ol41u4sn。所以,要进入由Docker Swarm部署并运行的容器,咱们须要对镜像名称进行过滤。
第一步,咱们须要找到代理运行所在的具体节点。
docker service ps proxy
须要注意的是该node列中的值,同时确保在如下命令中使用该正确值。
eval $(docker-machine env node-1) # Change node-1 with the node value previously obtained
此命令将给出如下代理配置输出结果。
docker exec -it \ $(docker ps -q --filter "ancestor=vfarcic/docker-flow-proxy") \ cat /cfg/haproxy.cfg exit
配置信息中最重要的部分以下所示。
frontend services bind *:80 bind *:443 option http-server-close acl url_go-demo path_beg /demo use_backend go-demo-be if url_go-demo backend go-demo-be server go-demo go-demo:8080
对于第一部分(frontend),熟悉HAProxy的朋友应该不会感到陌生。其接收来自端口80(HTTP)以及443(HTTPS)的请求。若是路径以/demo开头,其会被从新定向至后端go-demo处。在这里,各请求会被发送至go-demo在端口8080上的地址。此地址同时亦是咱们所部署的服务名称。因为go-demo同proxy存在于同一网络当中,所以Docker可以确保该请求被从新定向至目标容器。很简单,对吧?咱们无需再另行指定IP以及外部端口。
接下来的问题是,如何实现负载均衡。举例来讲,咱们要如何指定该代理跨越所有实例执行循环?
在开始进行负载均衡解释以前,首先建立几个go-demo服务实例。
eval $(docker-machine env node-1) docker service scale go-demo=5
稍等一下子,就将有5个go-demo服务实例开始运行。
包含规模化go-demo服务与代理实例的Docker Swarm集群
咱们该如何让代理将请求均衡至所有实例当中?答案是不用——咱们并不须要执行特别的操做。
正常来说,若是咱们不使用Docker Swarm功能,则可以使用如下配置方式:
backend go-demo-be server instance_1 <INSTANCE_1_IP>:<INSTANCE_1_PORT> server instance_2 <INSTANCE_2_IP>:<INSTANCE_2_PORT> server instance_3 <INSTANCE_3_IP>:<INSTANCE_3_PORT> server instance_4 <INSTANCE_4_IP>:<INSTANCE_4_PORT> server instance_5 <INSTANCE_5_IP>:<INSTANCE_5_PORT>
然而在新的Docker网络当中,咱们将再也不须要进行上述配置。本来的做法只会在新副本添加或者删除时,给咱们的实例监控与代理更新工做形成麻烦。
如今,Docker会帮助咱们完成所有负载均衡工做。更准确地讲,当该代理将某条请求从新定向至go-demo时,其实际将其发送至Docker网络并由后者执行跨越所有服务副本(实例)的负载均衡。这套方案的意义在于,代理负责将端口80(或者443)从新定向至网络中的正确服务处,其它任务则所有由Docker完成。
你们能够随意向该服务发送更多请求,并检查其中一套副本的日志记录。在这里,你们会发现其接收到的请求约为整体请求数量的五分之一——与咱们的服务实例数量刚好吻合。
Docker网络与Docker 1.12及更高版本提供的Swarm相结合,无疑开启了一道通向更多新机遇的大门。不一样容器与负载均衡之间的内部通讯只是其中的一小部分,咱们亦能够更为轻松地配置公开代理。另外,咱们须要确保面向API进行公开的所有服务皆以代理形式接入同一网络。在此以后,咱们要作的就是进行配置以将全部请求从新定向至目标服务名称。这样全部来自代理的请求都将指向Docker网络,并由后者跨越所有实例执行负载均衡。
但新的问题在于,这套方案的具体效率是否理想。毕竟咱们在体系中引入了新的层。尽管过去咱们也会使用代理以及服务,但如今Docker网络会在两者之间创建负载均衡机制。答案是,由此带来的运行负担很是有限。Docker利用Linux IPVS实现负载均衡,其做为Linux内核的组成部分已经拥有超过15年历史,并且事实证实其是一种极为高效的负载均衡实现方式。事实上,其速度表现远远优于nginx或者HAProxy。
下一个问题是,咱们是否须要代理机制。是的,固然须要。DOcker所使用的IPVS只负责实现负载均衡。咱们还须要一套代理以接收来自端口80与443的请求,并根据其实际路径将其从新定向至各目标服务。在此基础之上,咱们还能够利用它执行多种任务,包括SSL握手以及验证等等。
那么这种做法存在哪些缺点?首先想到的确定是粘性会话。若是咱们但愿同一用户向同一实例发送请求,那么这套方案显然并不适用。另外一个问题是,咱们是否应当在服务以内实现粘性会话,或者应该将其做为独立实体。这个问题咱们在本文中暂时不做讨论,只须要明确这里提到的方案并不适用于粘性会话便可。
那么其具有哪些优点?首先,整个实现过程很是简单。咱们用不着在部署新副本时对代理进行从新配置。如此一来,整个流程将很是便捷。因为咱们不须要包含所有端口IP及端口的列表,所以也就无需使用Registrator以及Consul Template之类的工具。过去,咱们须要利用Registrator以监控Docker事件,并将IP及端口保存在键值存储方案(例如Consul)当中。信息存储完成后,咱们会利用Consul Template从新建立代理配置。虽然很多项目都能简化这一流程,但Docker Swarm与Docker网格的再现从根本上下降了其实施难度。
在本文中,咱们讲述了如何利用Docker Flow: Proxy项目配置HAProxy。其中包含HAProxy及一系列其它API,容许咱们利用简单的HTTP请求对代理进行从新配置。另外,其还消除了对手动配置或者模板的依赖性。
在另外一方面,创建自定义解决方案的流程也变得更为简单。本文只稍稍列举几项重点即解释了整个构建过程,这在nginx或者HAProxy配置工做中是彻底没法想象的。
因此个人建议是先尝试一下Docker Flow: Proxy,然后再作决定。
今天咱们已经总结了Docker v1.12带来的一系列Swarm与网络新功能,特别是在公开代理方面的改进。
那么咱们是否是就可以成功运行Swarm群集了呢?还差得远!本文仅仅只是开始,咱们还有大量问题有待回答。Docker Compose发生了哪些改变?咱们该如何在不形成停机的前提下部署新版本?是否还有其它值得一试的工具?
后续的内容,也敬请你们期待!