Docker Flow:代理–按需HAProxy服务发现和重新配置

Docker Flow:Proxy项目的目标是提供一种简单的方法,以便在每次部署新服务或扩展服务时重新配置代理。 它不是试图“重新发明轮子”,而是要利用现有的领导者,并通过易于使用的集成将他们结合起来。 它使用HAProxy作为代理,并使用Consul作为服务注册表。 在这两个之上,它添加了允许按需重新配置代理的自定义逻辑。

在进入示例之前,让我们讨论使用动态代理的必要性。

需要动态代理

我将假设您已经在使用Docker来部署您的服务和应用程序,或者至少,您知道它是如何工作的。 在众多好处中,Docker使我们能够部署不可变且易于扩展的容器。 在实现具有伸缩性的容器时,您应该学习的第一件事是,我们应该让Docker决定将要暴露给主机的端口。 例如,如果您的服务侦听端口8080,则应在容器内部内部定义该端口,但不要向主机公开该端口的固定编号。 换句话说,应该使用标志-p 8080而不是-p 8080:8080运行容器。 其背后的原因是扩展。 如果暴露给主机的端口是“硬编码的”,则由于潜在的冲突,我们无法扩展该容器。 毕竟,两个进程无法侦听同一端口。 即使您决定永不扩展在同一台服务器上,对端口进行硬编码也将意味着您需要严格控制每个服务专用的端口。 如果您采用微服务方法,则服务数量将增加,从而使端口管理成为一场噩梦。 不使用预定义端口的第二个原因是代理。 它应该负责请求或重定向和负载平衡( HAProxynginx通常是最常见的选择)。 每当部署新容器时,也需要重新配置代理。

当您进一步采用Docker时,您将开始使用一种集群编排工具。
例如, Docker Swarm将确保将容器部署在集群中的某个位置。 它将选择最适合需求的服务器。 这极大地简化了群集管理,但带来了问题。 如果我们事先不知道将在哪个服务器上部署容器,那么我们的用户将如何访问服务? 不仅端口是未知的,IP也是未知的。 解决方案是在每次部署或销毁新容器时都重新配置代理。

动态代理重新配置的成功管理取决于几个概念和工具。 我们需要一个地方来存储所有正在运行的容器的信息。 该信息应该是可靠的,容错的并且是分布式的。 满足这些目标的一些工具是ConsuletcdZookeeper 。 为了进行比较,请阅读“ 服务发现:Zookeeper与etcd与Consul”一文。 一旦选择了用于注册服务的工具,就需要一种在创建新的Docker事件( runstoprm )时更新该数据的方法。 这可以通过Registrator轻松完成。 它将在每个Docker事件上更新服务注册表。 最后,有了服务注册表,我们可以在其中存储信息以及监视Docker事件和更新注册表数据的方式,剩下的唯一事情就是更新代理。 我们该怎么做?

每次部署新服务时,我们都可以手动更新代理配置。 我猜没有必要解释为什么应该放弃此选项,所以让我们继续。

每次部署新容器时,我们可以自动更新代理。 该解决方案可以监视Consul(或任何其他服务注册表)并应用一些模板解决方案来更新代理配置。 但是,这是解决该问题的非常危险的方式,因为不应立即更新代理。 在部署和代理重新配置之间,我们应该运行测试(我们称它们为部署后测试)。 他们应确认部署已正确执行,并且没有集成问题。 仅当所有部署后测试均成功时,我们才应重新配置代理,并让我们的用户受益于新功能。 最好的方法是通过蓝绿色部署过程。 请参阅《 Docker Flow:蓝绿色部署和相对扩展》以了解更多信息。

如果手动和自动“ 我们不等待任何人”代理重新配置都被丢弃,那么剩下的唯一解决方案就是按需重新配置。 我们应该能够与旧版本并行地将新容器部署到生产环境中,运行部署后测试,最后告诉代理重新配置自身。 我们应该能够使一切自动化,但可以自行决定何时触发更改。

这就是Docker Flow:Proxy发挥作用的地方。 它使用HAProxyConsul ,并添加了一个我们希望更改配置时可以调用的API。

让我们来看看它的作用。

搭建环境

如果您更喜欢使用Docker Machine而不是Vagrant,请查阅Docker Flow:Proxy项目中的示例。 如果您对项目有任何问题,建议或意见,请给我发送电子邮件(我的信息在“ 关于”部分中)或创建“ 新问题” )。

我们将要研究的示例的前提条件是VagrantGit client

我正在尽力确保我所有带有实际示例的文章都可以在各种OS和硬件组合上使用。 但是,制作始终有效的演示非常困难,并且您可能会遇到一些问题。 在这种情况下,请与我联系(我的信息在“ 关于”部分中),我将尽力帮助您,因此,使示例更可靠。

让我们从签出项目代码开始。

git clone https://github.com/vfarcic/docker-flow-proxy.git

cd docker-flow-proxy

为了演示Docker Flow:Proxy的好处,我们将设置Swarm集群并部署服务。 我们将创建四个虚拟机。 一个( 代理 )将运行Docker Flow:ProxyConsul 。 其他三台机器将组成具有一个主节点和两个节点的Swarm集群。

由于我想集中精力研究Docker Flow:Proxy的工作方式,因此我将跳过详细说明如何设置环境,仅提及我们将使用Ansible来配置VM。

在启动计算机之前,您可能需要安装vagrant-cachier插件。 它将缓存依赖项,以便以后的软件包安装更快。

vagrant plugin install vagrant-cachier

让我们创建虚拟机。

vagrant up swarm-master swarm-node-1 swarm-node-2 proxy

创建和配置四个服务器需要一些时间,因此请喝杯咖啡,几分钟后再回来。 当vagrant命令完成时,我们将继续。

现在,我们已启动并运行了四个服务器。 第一个( 代理 )正在运行Consuldocker-flow-proxy容器。 领事将包含我们可能需要进行代理配置的所有信息。 同时,它是设置Swarm集群的首选服务发现工具。 在生产中,您可能应该在集群中的所有服务器上运行它,但是,对于此演示,应该有一个实例。

其他三个VM构成集群。 除了Swarm本身之外,集群中的每台计算机都在运行Registrator ,该Registrator监视Docker事件,并在运行新容器时将数据放入Consul中。 它也以其他方式起作用。 如果停止或卸下了容器,则Registrator将从Consul中删除数据。 换句话说,多亏了Registrator,Consul将始终拥有有关群集上运行的所有容器的最新信息。

让我们进入代理虚拟机并快速查看集群状态。

vagrant ssh proxy

export DOCKER_HOST=tcp://10.100.192.200:2375

docker info

docker info的输出如下。

Containers: 4
 Running: 4
 Paused: 0
 Stopped: 0
Images: 4
Server Version: swarm/1.1.3
Role: primary
Strategy: spread
Filters: health, port, dependency, affinity, constraint
Nodes: 2
 swarm-node-1: 10.100.192.201:2375
  └ Status: Healthy
  └ Containers: 2
  └ Reserved CPUs: 0 / 1
  └ Reserved Memory: 0 B / 1.536 GiB
  └ Labels: executiondriver=native-0.2, kernelversion=3.13.0-79-generic, operatingsystem=Ubuntu 14.04.4 LTS, storagedriver=devicemapper
  └ Error: (none)
  └ UpdatedAt: 2016-03-21T14:24:54Z
 swarm-node-2: 10.100.192.202:2375
  └ Status: Healthy
  └ Containers: 2
  └ Reserved CPUs: 0 / 1
  └ Reserved Memory: 0 B / 1.536 GiB
  └ Labels: executiondriver=native-0.2, kernelversion=3.13.0-79-generic, operatingsystem=Ubuntu 14.04.4 LTS, storagedriver=devicemapper
  └ Error: (none)
  └ UpdatedAt: 2016-03-21T14:24:51Z
Plugins: 
 Volume: 
 Network: 
Kernel Version: 3.13.0-79-generic
Operating System: linux
Architecture: amd64
CPUs: 2
Total Memory: 3.072 GiB
Name: 9fdd284ff391

如您所见,Swarm集群包含两个节点( swarm-node-1swarm-node-2 ),每个节点具有一个CPU和1.5 GB RAM,状态为Healthy

总而言之,我们设置了四个服务器。 代理节点托管Docker Flow:ProxyConsulDocker Flow:代理将是我们进入系统的唯一入口,而Consul将充当服务注册表。 对我们服务的所有请求都将转到代理节点中的单个端口80,并且HAProxy将确保将其重定向到最终目的地。

其他三个节点构成了我们的Docker Swarm集群。 swarm-master负责编排,并将服务部署到其节点之一(目前仅swarm-node-1swarm-node-2 )。 这些节点中的每个节点都在运行Registrator ,该注册器监视Docker事件并更新有关已部署(或已停止)容器的Consul信息。

现在已经完成了所有设置,让我们运行一些服务。

运行服务的单个实例

我们将运行在docker-compose-demo.yml文件中定义的服务。

cd /vagrant

export DOCKER_HOST=tcp://swarm-master:2375

docker-compose \
    -p books-ms \
    -f docker-compose-demo.yml \
    up -d

我们只是运行公开HTTP API的服务。 该服务的详细信息对于本文而言并不重要。 重要的是它正在Docker Engine公开的随机端口上运行。 由于我们正在使用Swarm,因此它可能在其任何节点上运行。 换句话说,服务的IP和端口都由Swarm决定,而不是由我们控制。 这是一件好事,因为Swarm消除了在(可能巨大)集群中管理服务的繁琐任务。 但是,事先不知道IP和端口会带来一些问题,最重要的一个问题是,如果我们不知道服务的位置,该如何访问该服务。

这是注册器开始起作用的时刻。 它检测到一个新容器正在运行,并将其数据存储到Consul中。 我们可以通过运行以下请求来确认。

curl proxy:8500/v1/catalog/service/books-ms \
    | jq '.'

curl命令的输出如下。

[
  {
    "ServicePort": 32768,
    "ServiceAddress": "10.100.192.201",
    "ServiceTags": null,
    "ServiceName": "books-ms",
    "ServiceID": "swarm-node-1:booksms_app_1:8080",
    "Address": "10.100.198.200",
    "Node": "proxy"
  }
]

我们可以看到,在这种情况下,该服务在端口32768上的10.100.192.201swarm-node-1 )中运行。 服务的名称( books-ms )与我们部署的容器的名称相同。 我们现在要做的就是重新加载代理。

curl \
    "proxy:8080/v1/docker-flow-proxy/reconfigure?serviceName=books-ms&servicePath=/api/v1/books" \
     | jq '.'

而已。 我们要做的就是发送HTTP请求以reconfigure代理。 serviceName查询包含我们要与代理集成的服务的名称。 它需要匹配Consul中存储的ServiceName值。 servicePath是标识服务的唯一URL。 HAProxy将重定向所有以该值开头的URL请求。

curl命令的输出如下。

{
  "ServicePath": "/api/v1/books",
  "ServiceName": "books-ms",
  "Message": "",
  "Status": "OK"
}

Docker Flow:代理回答说成功重新配置了在/ api / v1 / books路径上运行的服务books-ms

让我们看看该服务是否确实可以通过代理访问。

curl -I proxy/api/v1/books

curl命令的输出如下。

HTTP/1.1 200 OK
Server: spray-can/1.3.1
Date: Mon, 14 Mar 2016 22:08:11 GMT
Access-Control-Allow-Origin: *
Content-Type: application/json; charset=UTF-8
Content-Length: 2

响应为200 OK ,这意味着我们的服务确实可以通过代理访问。 我们要做的就是告诉docker-flow-proxy服务的名称及其基本URL。

扩展服务

Docker Flow:代理不限于单个实例。 它将重新配置代理以在所有当前部署的服务实例之间执行负载平衡。

例如,让我们将服务扩展到三个实例。

docker-compose \
    -p books-ms \
    -f docker-compose-demo.yml \
    scale app=3

让我们看看结果。

docker-compose \
    -p books-ms \
    -f docker-compose-demo.yml \
    ps

docker-compose ps命令的结果如下。

Name               Command          State               Ports
------------------------------------------------------------------------------
books-ms-db     /entrypoint.sh mongod   Up      27017/tcp
booksms_app_1   /run.sh                 Up      10.100.192.202:32768->8080/tcp
booksms_app_2   /run.sh                 Up      10.100.192.201:32768->8080/tcp
booksms_app_3   /run.sh                 Up      10.100.192.202:32769->8080/tcp

我们还可以确认Registrator收到了事件并将信息存储到Consul。

curl proxy:8500/v1/catalog/service/books-ms \
    | jq '.'

这次,领事返回了不同的结果。

[
  {
    "ServicePort": 32768,
    "ServiceAddress": "10.100.192.201",
    "ServiceTags": null,
    "ServiceName": "books-ms",
    "ServiceID": "swarm-node-1:booksms_app_1:8080",
    "Address": "10.100.198.200",
    "Node": "proxy"
  },
  {
    "ServicePort": 32769,
    "ServiceAddress": "10.100.192.201",
    "ServiceTags": null,
    "ServiceName": "books-ms",
    "ServiceID": "swarm-node-1:booksms_app_2:8080",
    "Address": "10.100.198.200",
    "Node": "proxy"
  },
  {
    "ServicePort": 32768,
    "ServiceAddress": "10.100.192.202",
    "ServiceTags": null,
    "ServiceName": "books-ms",
    "ServiceID": "swarm-node-2:booksms_app_3:8080",
    "Address": "10.100.198.200",
    "Node": "proxy"
  }
]

如您所见,该服务被扩展为三个实例(不计算数据库)。 其中一个在swarm-node-110.100.192.201 )上运行,而其他两个部署在swarm-node-210.100.192.202 )上。 即使三个实例正在运行,代理也会继续将所有请求重定向到第一个实例。 我们可以通过重新运行reconfigure命令来更改它。

curl "proxy:8080/v1/docker-flow-proxy/reconfigure?serviceName=books-ms&servicePath=/api/v1/books" \
     | jq '.'

从此刻起, HAProxy已配置为在所有三个实例之间执行负载平衡。 我们可以继续扩展(和取消扩展)服务,并且只要我们发送reconfigure请求,代理就会在所有实例之间平衡请求的负载。 它们可以分布在任意数量的服务器之间,甚至可以分布在不同的数据中心(只要它们可以从代理服务器访问)。

请尝试使用Docker Flow:Proxy 。 部署多个服务,扩展它们,销毁它们,等等。 在项目README中可以找到更多信息。 如果您对项目有任何问题,建议或意见,请与我联系(我的信息位于“ 关于”部分)。 随时创建一个新问题或发送请求请求。

在进行下一个任务之前,请不要忘记停止(或销毁)我们创建的VM并释放您的资源。

exit

vagrant destroy -f

翻译自: https://www.javacodegeeks.com/2016/03/docker-flow-proxy-demand-haproxy-service-discovery-reconfiguration.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值