通过Docker Swarm,Docker Compose和Consul扩展到无限(第1/4部分)–品尝即将到来的产品...

本系列分为以下文章。

先前的文章主要关注Docker的 持续交付容器 。 在与Jenkins,Docker和Ansible的持续集成,交付或部署中,我解释了如何持续构建,测试和部署打包到容器中的微服务,并在多台服务器上做到这一点,而无需停机并具有回滚功能。 我们使用Ansible,Docker,Jenkins和其他一些工具来实现该目标。

现在该扩展我们在前几篇文章中所做的工作,并在任意数量的服务器上扩展服务。 我们会将所有服务器视为一个服务器场 ,并不要将容器部署到预定义的位置,而是将容器部署到运行最少数量的容器。 与其将每个服务器视为我们部署的单独位置,我们将所有服务器视为一个单元。

我们将继续使用一些以前使用过的相同工具。

  • 带有VirtualBox的 Vagrant将提供一种简便的方法来创建和配置将充当我们服务器的轻量级,可复制和便携式虚拟机。
  • Docker将提供一种简便的方法来构建,运送和运行打包在容器中的分布式应用程序。
  • Ansible将用于设置服务器和部署应用程序。
  • 我们将使用Jenkins来检测对代码存储库的更改,并触发将测试,构建和部署应用程序的作业。
  • 最后, nginx将为我们的微服务将在其上运行的不同服务器和端口提供代理。

在这些之上,我们将看到一些新的如下。

  • Docker Compose是一个方便的工具,可让我们运行容器。
  • Docker Swarm会将服务器池变成单个虚拟主机。
  • 最后,我们将使用Consul进行服务发现和配置。

为了遵循本文,请使用VirtualBox设置Vagrant 。 完成后,请安装vagrant-cachier插件。 尽管不是强制性的,但是它将加快VM的创建和安装。

vagrant plugin install vagrant-cachier

有了先决条件,我们就可以开始构建服务器场了。

服务器设置

我们将创建四个虚拟机。 一个(群主机)将用于编排部署。 它的主要功能是充当Docker Swarm主节点 。 我们不会事先决定在哪里部署某些东西,而是告诉Docker Swarm部署什么,它将部署到运行最少容器的节点上。 我们可以采用其他策略,但作为演示,此默认策略就足够了。 除了Swarm之外,我们还将在同一节点上设置AnsibleJenkinsConsulDocker Compose 。 将创建另外三个虚拟机,并将它们分别命名为swarm-node-01swarm-node-02swarm-node-03 。 与swarm-master不同,这些节点将仅具有Consul和Swarm代理。 他们的目的是托管我们的服务(打包为Docker容器)。 稍后,如果我们需要更多的硬件,我们只需增加一个节点,然后让Swarm负责平衡部署。

我们将从启动Vagrant VM开始。 请记住,将创建四个虚拟机,每个虚拟机需要1GB的RAM。 在8GB 64位计算机上,运行这些VM应该没有问题。 如果没有足够的可用空间,请尝试通过将v.memory = 1024更改为较小的值来编辑Vagrantfile

所有代码都位于vfarcic / docker-swarm GitHub存储库中。

git clone https://github.com/vfarcic/docker-swarm.git
cd docker-swarm
vagrant up
vagrant ssh swarm-master

我们可以通过运行infra.yml Ansible剧本来设置所有服务器。

ansible-playbook /vagrant/ansible/infra.yml -i /vagrant/ansible/hosts/prod

首次对一台服务器运行Ansible时,它将询问您是否要继续连接。 回答

许多东西将被下载(Jenkins容器是最大的)并使用此命令进行安装,因此请等待一段时间。 我不会详细介绍Ansible。 在官方网站以及此博客的其他文章中,您都可以找到很多有关它的文章。 重要的细节是,一旦完成Ansible剧本的执行, swarm-master将安装JenkinsConsulDocker ComposeDocker Swarm 。 其他三个节点收到仅安装ConsulSwarm代理的说明 。 有关更多信息,请查阅与Jenkins,Docker和Ansible持续集成,交付或部署以及持续集成交付和部署中的其他文章。

在本文中,我们永远不会输入任何swarm-node服务器。 一切都将在单个位置完成( swarm-master )。

现在,让我们介绍一下本博客中从未使用过的工具。 领事Docker Swarm

领事

Consul是旨在轻松发现和配置分布式和高可用性数据中心的工具。 它还具有易于设置故障检测和键/值存储的功能。

让我们看一下安装在所有计算机上的Consul

例如,我们可以使用以下命令查看集群的所有成员。

consul members

输出应该类似于以下内容。

Node           Address              Status  Type    Build  Protocol
swarm-master   10.100.199.200:8301  alive   server  0.5.0  2
swarm-node-01  10.100.199.201:8301  alive   client  0.5.0  2
swarm-node-02  10.100.199.202:8301  alive   client  0.5.0  2
swarm-node-03  10.100.199.203:8301  alive   client  0.5.0  2

通过Consul随处可见,我们可以存储有关我们部署的应用程序的信息,并将其传播到所有服务器。 这样,应用程序就可以在本地存储数据,而不必担心中央服务器的位置。 同时,当一个应用程序需要有关其他应用程序的信息时,它也可以在本地请求它。 能够在所有服务器之间传播信息是所有分布式系统的基本要求。

检索相同信息的另一种方法是通过Consul的REST API。 我们可以运行以下命令。

curl localhost:8500/v1/catalog/nodes | jq .

这将产生以下以jq格式化的JSON输出。

[
  {
    "Node": "swarm-master",
    "Address": "10.100.199.200"
  },
  {
    "Node": "swarm-node-01",
    "Address": "10.100.199.201"
  },
  {
    "Node": "swarm-node-02",
    "Address": "10.100.199.202"
  },
  {
    "Node": "swarm-node-03",
    "Address": "10.100.199.203"
  }
]

稍后,当我们部署第一个应用程序时,我们将详细介绍Consul 。 请注意,即使我们将通过运行Shell的命令来使用Consul(至少直到进入运行状况部分),它也具有可以通过打开http://10.100.199.200:8500来访问的UI。

码头工人

Docker Swarm允许我们利用标准Docker API在集群中运行容器。 使用它的最简单方法是设置DOCKER_HOST环境变量。 让我们运行Docker命令info

export DOCKER_HOST=tcp://0.0.0.0:2375
docker info

输出应类似于以下内容。

Containers: 9
Strategy: spread
Filters: affinity, health, constraint, port, dependency
Nodes: 3
 swarm-node-01: 10.100.199.201:2375
  └ Containers: 3
  └ Reserved CPUs: 0 / 1
  └ Reserved Memory: 0 B / 1.019 GiB
 swarm-node-02: 10.100.199.202:2375
  └ Containers: 3
  └ Reserved CPUs: 0 / 1
  └ Reserved Memory: 0 B / 1.019 GiB
 swarm-node-03: 10.100.199.203:2375
  └ Containers: 3
  └ Reserved CPUs: 0 / 1
  └ Reserved Memory: 0 B / 1.019 GiB

我们立即获得有关已部署容器的数量的信息(目前为9),Swarm用于分配它们的策略(已传播;在运行容器数量最少的服务器上运行),节点(服务器)的数量,以及每一个的其他详细信息他们。 目前,每台服务器都部署了一个Swarm代理和两个Consul Registrator(总共九个)。 所有这些部署都是我们之前运行的infra.yml剧本的一部分。

部署方式

让我们部署第一个服务。 我们将使用在books-service.yml中定义的Ansible剧本。

ansible-playbook /vagrant/ansible/books-service.yml -i /vagrant/ansible/hosts/prod

运行此脚本或本文中的任何其他剧本都很慢,因为我们将图像拉到所有节点上,而不仅仅是要部署到的节点。 这背后的原因是,如果节点发生故障,我们希望一切准备就绪,以便尽快重新部署到另一个节点。 好消息是,下次运行它时,它将更快,因为已经下载了映像,并且Docker仅会拉差异。

我们刚运行的剧本遵循与蓝/绿部署文章中已经讨论过的逻辑相同的逻辑。 主要区别在于,这一次在实际运行Playbook之前,我们鲜有未知的事物。 我们不知道节点服务的IP将被部署到其中。 由于此设置背后的想法不仅是在多个节点之间分配应用程序,而且还可以轻松地扩展它们,因此端口也是未知的。 如果我们提前定义它,则可能存在多个服务使用相同端口和冲突的危险。

现在,我们将研究该剧本的功能,然后在下一篇文章的后面,我们将探讨其完成方式。

图书服务由两个容器组成。 一个是应用程序本身,另一个是应用程序所需的MongoDB。 让我们看看他们部署到了哪里。

docker ps | grep booksservice

结果因情况而异,看起来类似于以下内容。 Docker ps命令将输出比以下内容更多的信息。 与本文无关的内容已被删除。

vfarcic/books-service:latest  10.100.199.203:32768->8080/tcp   swarm-node-03/booksservice_blue_1   
mongo:latest                  10.100.199.201:32768->27017/tcp  swarm-node-01/booksservice_db_1

我们可以看到应用程序容器已部署到swarm-node-03并正在侦听端口32768 。 另一方面,数据库进入了单独的节点swarm-node-01并监听端口32768图书服务的目的是从Mongo数据库中存储和检索图书。

让我们检查一下这两个容器是否相互通信。 当我们从应用程序容器( booksservice_blue_1 )请求数据时,它将从数据库( booksservice_db_1 )中检索数据。 为了对其进行测试,我们将请求服务插入几本书,然后要求它检索所有商店记录。

curl -H 'Content-Type: application/json' -X PUT -d '{"_id": 1, "title": "My First Book", "author": "Joh Doe", "description": "Not a very good book"}' http://10.100.199.200/api/v1/books | jq .
curl -H 'Content-Type: application/json' -X PUT -d '{"_id": 2, "title": "My Second Book", "author": "John Doe", "description": "Not a bad as the first book"}' http://10.100.199.200/api/v1/books | jq .
curl -H 'Content-Type: application/json' -X PUT -d '{"_id": 3, "title": "My Third Book", "author": "John Doe", "description": "Failed writers club"}' http://10.100.199.200/api/v1/books | jq .
curl http://10.100.199.200/api/v1/books | jq .

最后一个请求的结果如下。

[
  {
    "_id": 1,
    "title": "My First Book",
    "author": "John Doe"
  },
  {
    "_id": 2,
    "title": "My Second Book",
    "author": "John Doe"
  },
  {
    "_id": 3,
    "title": "My Third Book",
    "author": "John Doe"
  }
]

我们请求服务将其放入数据库的所有三本书都已存储。 您可能已经注意到,我们没有对运行应用程序的IP /端口执行请求。 我们没有对10.100.199.203:32768进行curl (这是服务当前正在运行的位置),我们在标准HTTP端口80上执行了对10.100.199.200的请求。 那就是部署我们的nginx服务器的地方,通过Consul,Registrator和Templating的“魔力”, nginx已更新为指向正确的IP和端口。 如何发生这种情况的详细信息将在下一篇文章中进行解释。 现在,重要的是要知道有关我们应用程序的数据存储在Consul中,并且可能需要它的每个服务都可以自由访问。 在这种情况下,该服务是nginx ,可同时充当反向代理和负载平衡器。

为了证明这一点,让我们运行以下内容。

curl http://localhost:8500/v1/catalog/service/books-service-blue | jq .

由于我们将练习蓝色/绿色部署 ,因此服务的名称在books-service-bluebooks-service-green之间交替显示。 这是我们第一次部署它,因此名称为blue 。 下一个部署将是绿色 ,而不是蓝色 ,依此类推。

[
  {
    "Node": "swarm-node-03",
    "Address": "10.100.199.203",
    "ServiceID": "swarm-node-03:booksservice_blue_1:8080",
    "ServiceName": "books-service-blue",
    "ServiceTags": null,
    "ServiceAddress": "",
    "ServicePort": 32768
  }
]

我们还将信息存储为图书服务 (通用的,没有蓝色或绿色),并带有IP和端口,应该可供公众使用。

curl http://localhost:8500/v1/catalog/service/books-service | jq .

与以前的输出可能因情况而异(IP和端口在部署之间有所变化)不同,此输出应始终相同。

[
  {
    "Node": "swarm-master",
    "Address": "10.100.199.200",
    "ServiceID": "books-service",
    "ServiceName": "books-service",
    "ServiceTags": [
      "service"
    ],
    "ServiceAddress": "10.100.199.200",
    "ServicePort": 80
  }
]

无论我们在哪里部署服务,始终可以从单个位置10.100.199.200进行访问(至少直到我们开始添加多个负载均衡器为止),并且始终可以从默认的HTTP端口80进行访问。nginx将确保将请求发送到在正确的IP和端口上提供正确的服务。

我们可以使用相同的原则部署另一项服务。 这次它将成为我们图书服务的前端。

ansible-playbook /vagrant/ansible/books-fe.yml -i /vagrant/ansible/hosts/prod

您可以通过在浏览器中打开http://10.100.199.200来查看结果。 这是一个AngularJS UI ,它使用我们之前部署的服务来检索所有可用的书。 与books-service一样 ,您可以运行以下命令来查看容器的部署位置。

docker ps | grep booksfe
curl http://localhost:8500/v1/catalog/service/books-fe-blue | jq .

这两个命令的输出应类似于以下内容。

vfarcic/books-fe:latest         10.100.199.201:32769->8080/tcp    swarm-node-01/booksfe_blue_1

[
  {
    "Node": "swarm-node-01",
    "Address": "10.100.199.201",
    "ServiceID": "swarm-node-01:booksfe_blue_1:8080",
    "ServiceName": "books-fe-blue",
    "ServiceTags": null,
    "ServiceAddress": "",
    "ServicePort": 32769
  }
]

现在,让我们想象有人更改了books-service的代码,并且我们想部署一个新版本。 程序与我们之前完全相同。

ansible-playbook /vagrant/ansible/books-service.yml -i /vagrant/ansible/hosts/prod

为了验证一切都按预期进行,我们可以查询Consul。

curl http://localhost:8500/v1/catalog/service/books-service-green | jq .

输出应类似于以下内容。

[
  {
    "Node": "swarm-node-02",
    "Address": "10.100.199.202",
    "ServiceID": "swarm-node-02:booksservice_green_1:8080",
    "ServiceName": "books-service-green",
    "ServiceTags": null,
    "ServiceAddress": "",
    "ServicePort": 32768
  }
]

蓝色版本发布在IP 10.100.199.203上时 ,这次容器已部署到10.100.199.202Docker Swarm检查了哪个服务器上运行的容器数量最少,并确定运行它的最佳位置是swarm-node-02

您可能已经猜到了,一开始很容易知道我们部署的是蓝色还是绿色。 但是,随着部署和服务数量的增加,我们将很快放松跟踪。 我们可以通过查询领事键来解决这个问题。

curl http://localhost:8500/v1/kv/services/books-service/color | jq .

Consul中的值以base64编码存储。 要仅查看该值,请运行以下命令。

curl http://localhost:8500/v1/kv/services/books-service/color?raw

命令的输出为green

詹金斯

完全实施的持续部署唯一缺少的是拥有可以检测到我们的源代码存储库中的更改,然后构建,测试和部署容器的东西。 使用Docker可以很容易地使所有构建,测试和部署遵循相同的标准。 对于本文,我仅创建了进行实际部署的作业。 当我们探索从故障中恢复的方法时,我们将在下一篇文章的稍后部分中使用它们。 在此之前,您可以通过打开http://10.100.199.200:8080/来查看正在运行的Jenkins实例。

未完待续

在下一篇文章中,我们将探讨Consul的其他功能,以及如何利用它们从故障中恢复。 每当某个容器停止工作时,Consul都会检测到该容器,并向Jenkins发送请求,Jenkins将重新部署发生故障的容器。 虽然为本文创建的Jenkins作业仅部署服务,但是您可以轻松地将其扩展为,例如,当Consul发出指示失败的请求时发送电子邮件。

我们将深入了解如何完成所有这些工作,并使用Docker Compose,Consul-Template,Registrator等显示手动命令。他们的理解是解释我们先前所见(并运行)的Ansible剧本的前提。

最后,我们将探索如何扩展同一应用程序的多个实例。

您已经了解 什么 ,现在该了解如何了

该故事在“ 手动部署服务”文章中继续进行。

翻译自: https://www.javacodegeeks.com/2015/07/scaling-to-infinity-with-docker-swarm-docker-compose-and-consul-part-14-a-taste-of-what-is-to-come.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值