简介
Consul 是一个分布式、高可用、数据中心感知的服务发现和配置系统。它可以用来呈现服务和节点,提供灵活和强大的接口,使客户端始终能够获取其所属基础设施的最新视图。
Consul 提供了许多不同的功能,用于提供关于基础设施的一致和可用信息。这包括服务和节点发现机制、标记系统、健康检查、基于共识的选举例程、系统范围的键/值存储等。通过在组织内利用 consul,您可以轻松地为您的应用程序和服务构建复杂的感知水平。
在本指南中,我们将介绍使用 consul 的一些基础知识。我们将涵盖在服务器上运行 consul 进行测试所需的一般程序。在下一个指南中,我们将专注于在生产环境中设置 consul。
先决条件和目标
在本指南中,我们将熟悉使用 consul 构建基础设施的服务发现和配置系统。
在我们的演示中,我们将配置三个服务器和一个客户端。服务器用于处理查询并维护系统的一致视图。客户端也是系统的成员,并且可以连接到服务器以获取有关基础设施的信息。客户端还可能包含将由 consul 监控的服务。
为了本指南和整个系列的目的,我们将配置 4 台计算机。前三台将是如上所述的 consul 服务器。最后一台将是充当客户端的 consul 代理,可用于查询有关系统的信息。
为了在稍后实施一些安全机制,我们需要将所有计算机命名为单个域内的机器。这样我们就可以在将来利用通配符 SSL 证书。
我们的机器的详细信息如下:
主机名 | IP 地址 | 角色 |
server1.example.com | 192.0.2.1 | 引导 consul 服务器 |
server2.example.com | 192.0.2.2 | consul 服务器 |
server3.example.com | 192.0.2.3 | consul 服务器 |
agent1.example.com | 192.0.2.50 | consul 客户端 |
我们将在本演示中使用 64 位 Ubuntu 14.04 服务器,但任何现代 Linux 服务器都应该同样适用。
下载和安装 Consul
我们需要采取的第一步是在我们的每台机器上下载和安装 consul 软件。以下步骤应在上述 每台 机器上执行。您应以 root 用户身份登录。
在查看 consul 应用程序之前,我们需要获取 unzip
以解压可执行文件。我们还将使用 screen
应用程序,以便在单个终端窗口中轻松拥有多个会话。这对我们的介绍很有用,因为 consul 通常在不作为服务运行时占据整个屏幕。
更新本地系统的软件包缓存,然后使用 apt
安装软件包:
apt-get update apt-get install unzip screen
为了不会忘记稍后执行此操作,请立即启动 screen 会话:
screen
如果出现版权信息,请按 Enter。您将被放回到终端窗口,但现在您已经在一个 screen 会话中。
现在,我们可以获取 consul 程序。consul 项目页面提供了 Windows、OS X 和 Linux 的二进制软件包下载链接。
转到上述页面,在代表您的服务器的操作系统和架构上右键单击。在本指南中,由于我们使用的是 64 位服务器,我们将使用 “linux” 下的 “amd64” 链接。选择 “复制链接地址” 或您的浏览器提供的类似选项。
在终端中,移动到 /usr/local/bin
目录,我们将在其中保存可执行文件。键入 wget
和一个空格,然后粘贴从网站上复制的 URL:
cd /usr/local/bin wget https://dl.bintray.com/mitchellh/consul/0.3.0_linux_amd64.zip
现在,我们可以使用我们之前安装的 unzip
命令来解压二进制软件包。然后我们可以删除压缩文件:
unzip *.zip rm *.zip
现在,您应该在所有服务器上都可以使用 consul
命令。
启动引导服务器
要开始使用 consul,我们需要启动我们的 consul 服务器。在推荐的多服务器环境中配置时,此步骤将需要分阶段完成。
我们需要做的第一件事是在我们的服务器中的一个上以 server
和 bootstrap
模式启动 consul 程序。服务器模式意味着 consul 将作为服务器实例而不是客户端启动。引导选项用于第一个服务器。这允许它在没有选举的情况下(因为它将是唯一可用的服务器)将自己指定为集群的 “领导者”。
在指定我们的主机的表中,我们将我们的 server1
指定为引导服务器。在 server1 上,输入以下命令启动引导实例:
consul agent -server -bootstrap -data-dir /tmp/consul
服务器将在当前终端中启动,并且随着事件的发生,日志数据将被输出。在日志数据的末尾,您将看到以下行:
. . . 2014/07/07 14:32:15 [ERR] agent: failed to sync remote state: No cluster leader 2014/07/07 14:32:17 [WARN] raft: Heartbeat timeout reached, starting election 2014/07/07 14:32:17 [INFO] raft: Node at 192.0.2.1:8300 [Candidate] entering Candidate state 2014/07/07 14:32:17 [INFO] raft: Election won. Tally: 1 2014/07/07 14:32:17 [INFO] raft: Node at 192.0.2.1:8300 [Leader] entering Leader state 2014/07/07 14:32:17 [INFO] consul: cluster leadership acquired 2014/07/07 14:32:17 [INFO] consul: New leader elected: server1.example.com 2014/07/07 14:32:17 [INFO] consul: member 'server1.example.com' joined, marking health alive
如您所见,由于这是初始节点,找不到集群领导者。但是,由于我们启用了引导选项,此服务器能够自行进入领导者状态,以启动具有单个主机的集群。
启动其他服务器
在 server2
和 server3
上,我们可以通过以下命令启动 consul 服务,不使用引导选项:
consul agent -server -data-dir /tmp/consul
对于这些服务器,您将看到日志条目。在接近末尾时,您将看到以下消息:
. . . 2014/07/07 14:37:25 [ERR] agent: failed to sync remote state: No cluster leader 2014/07/07 14:37:27 [WARN] raft: EnableSingleNode disabled, and no known peers. Aborting election. 2014/07/07 14:37:53 [ERR] agent: failed to sync remote state: No cluster leader
这是因为它无法找到集群领导者,并且未启用成为领导者自身。这种状态发生是因为我们的第二和第三台服务器已启用,但我们的服务器尚未相互连接。
要相互连接,我们需要将这些服务器加入到彼此之间。这可以在任何方向上完成,但最简单的方法是从我们的 server1
机器开始。
由于我们在当前 server1
的终端窗口中运行 consul 服务器,我们需要使用 screen
创建另一个终端以进行额外的工作。通过输入以下命令在现有 server1
的 screen 会话中创建一个新的终端窗口:
CTRL-A C
这将在保持先前会话运行的同时打开一个新的终端实例。您可以通过输入以下命令在每个现有终端会话之间切换:
CTRL-A N
在新的终端中,通过引用它们的 IP 地址,加入其他两个实例,如下所示:
consul join 192.0.2.2 192.0.2.3
这应该立即将所有三台服务器加入到同一个集群中。您可以通过输入以下命令来双重检查:
consul members
Node Address Status Type Build Protocol server1.example.com 192.0.2.1:8301 alive server 0.3.0 2 server2.example.com 192.0.2.2:8301 alive server 0.3.0 2 server3.example.com 192.0.2.3:8301 alive server 0.3.0 2
您还可以通过在其他任何服务器上创建一个新的终端会话,如上所述,发出相同的命令来获取此信息。
移除引导服务器并重新加入作为常规服务器
我们已经将我们的三台服务器加入了集群,但工作还没有完成。
当前,由于 server1
是以引导模式启动的,它有权在不咨询其他服务器的情况下做出决定。由于它们应该作为平等的运行并通过法定人数做出决定,我们希望在集群引导完成后移除此特权。
为此,我们需要停止 server1
上的 consul 服务。这将允许剩余的机器选择一个新的领导者。然后,我们可以在 server1
上重新启动 consul 服务,不使用引导选项并重新加入集群。
在 server1 上,切换回运行 consul 的终端:
CTRL-A N
通过输入以下命令停止服务:
CTRL-C
现在,重新启动不使用引导选项的服务:
consul agent -server -data-dir /tmp/consul
切换回您打开的终端,并通过连接到集群中的其中一个服务器来重新加入集群:
CTRL-A N consul join 192.0.2.2
现在,您应该拥有三台服务器处于平等地位。它们将相互复制信息,并处理单个服务器不可用的情况。其他服务器现在也可以通过简单地启动服务器而不使用引导并加入集群。
作为客户端加入集群并提供 Web UI 服务
现在,服务器集群可用,我们可以继续使用客户端机器连接。
我们将在客户端机器上放置 consul web UI,以便我们可以与集群进行交互并监视其健康状况。为此,请访问 web UI 的下载页面。右键单击下载按钮,然后选择“复制链接位置”或您可用的类似选项。
在您的客户端机器上,切换到您的主目录。键入 wget
,然后加上您从页面上复制的 URL:
cd ~ wget https://dl.bintray.com/mitchellh/consul/0.3.0_web_ui.zip
下载完成后,解压缩并删除存档:
unzip *.zip rm *.zip
将会有一个名为 dist
的目录,其中包含呈现 consul web UI 所需的所有文件。我们只需要在连接到集群时指定此目录。
要连接到集群,我们将使用类似于我们用于服务器的 consul agent 调用,但是我们将使用不同的标志。
我们不会使用 server
标志,因为我们希望以客户端模式运行。默认情况下,每个节点的客户端接口可以使用本地回环接口访问。由于我们希望远程访问 web UI,我们将不得不指定客户端的公共 IP 地址。
我们将不得不指向包含 web UI 的目录以提供该内容。此外,我们将立即通过传递集群中一个服务器的 IP 地址来加入集群。这将允许我们避免之后再加入。我们也可以在之前的服务器示例中执行此操作。
最终,我们的连接命令相当长。它将如下所示:
consul agent -data-dir /tmp/consul -client 192.0.2.50 -ui-dir /home/your_user/dir -join 192.0.2.1
这将将我们的客户端机器连接到集群作为常规的非服务器代理。该代理将响应其公共 IP 地址上的请求,而不是通常的 127.0.0.1
接口。因此,您将需要向指定了您选择的 rpc-addr
的任何 consul 命令添加额外的标志。
例如,如果您想从客户端查询成员列表,您将不得不通过传递您选择的备用接口和端口来执行此操作:
consul members -rpc-addr=192.0.2.50:8400
Node Address Status Type Build Protocol agent1 192.0.2.50:8301 alive client 0.3.0 2 server2 192.0.2.2:8301 alive server 0.3.0 2 server1 192.0.2.1:8301 alive server 0.3.0 2 server3 192.0.2.3:8301 alive server 0.3.0 2
这可能看起来有点麻烦,但它为我们提供了访问 consul web 界面的机会。您可以通过在您的客户端的 IP 地址后面,加上 :8500/ui
,在您的 web 浏览器中访问到 web 界面:
http://192.0.2.50:8500/ui
主界面将如下所示:
!Consul web UI landing page
您可以浏览各种菜单并探索界面。这为您提供了一种良好的方式来可视化您的集群以及您的机器和服务的健康状况。
添加服务和检查
现在,我们想要向 Consul 添加服务,这是设置 Consul 的主要用例。您可以以多种方式添加服务,但最简单的方法是创建一个配置目录来存储您的服务定义。
服务与包含服务定义的节点相关联。因此,如果我们有一个 Web 服务器,我们应该在该服务器上安装 Consul 代理,并在那里创建一个服务定义文件。
为了演示这一点,我们将在我们的客户端上安装 Nginx。通过输入以下命令来终止当前的客户端会话:
CTRL-C
通过输入以下命令在客户端上安装 Nginx:
apt-get install nginx
现在,我们可以创建一个配置目录来存储我们的服务定义:
mkdir ~/services
在这个目录中,我们将创建一个描述我们 Web 服务的 JSON 文件。我们将其命名为 web.json
:
nano ~/services/web.json
在这个文件中,我们需要包含一个结构来定义我们的服务。在这个结构内部,我们将定义一个用于对服务进行可靠运行检查的子结构。
基本的大纲如下:
{ "service": { . . . "check": { . . . } } }
对于服务,我们需要定义服务的名称,并告诉 Consul应该检查哪个端口。此外,我们可以为其提供一个标签列表,以便我们可以将服务任意分类以进行排序。
对于我们的示例,看起来是这样的:
{ "service": { "name": "web 服务器", "port": 80, "tags": ["nginx", "演示"], "check": { . . . } } }
这就是我们定义服务本身所需要的全部内容。但是,我们还希望定义 Consul 可以验证服务健康状况的方法。这通常相当简单,并将复制正常系统管理员的手动检查。
对于我们的服务,我们将使用 curl
执行一个简单的 Web 请求,就像 Consul 项目在其文档中列出的那样。我们实际上不需要知道 curl 能够检索到什么,我们只关心命令是否能够在没有任何错误的情况下执行。因此,我们可以丢弃任何输出。
我们还需要设置检查运行的间隔。这总是性能和实时信息之间的折衷。我们将使用 10 秒,因为我们希望相对快速地知道是否出现了问题:
{ "service": { "name": "web 服务器", "port": 80, "tags": ["nginx", "演示"], "check": { "script": "curl localhost:80 > /dev/null 2>&1", "interval": "10s" } } }
完成后保存并关闭文件。
现在,我们可以简单地重新启动客户端 Consul 会话,并指向该目录作为服务定义的位置:
consul agent -data-dir /tmp/consul -client 192.0.2.50 -ui-dir /home/your_user/dist -join 192.0.2.1 -config-dir /home/your_user/services
这将重新启动节点并将其连接到集群。如果您返回到 Web 界面,您现在应该能够看到一个服务:
!Consul intro service
回到您的客户端,您可以创建一个新的终端并临时停止 Web 服务器:
CTRL-A C service nginx stop
当您刷新 Web UI 时,您会看到 Web 服务检查现在失败了,这是预期的:
!Consul intro failed service
这表明我们的健康检查正在按预期工作。
结论
现在,您应该对 Consul 的工作原理有了基本的了解。我们在本指南中提供的演示并不是在生产环境中处理 Consul 的最佳方式,但是用于让您快速了解软件的有用功能。
在下一个指南中,我们将介绍如何在生产环境中使用 Consul。我们将把所有配置细节放在文件中以便参考,并创建启动脚本以在启动时启动服务。