一、安装 Consul
Consul 下载地址:https://www.consul.io/downloads.html,下载后解压就是一个可执行的二进制文件consul
,配置好环境变量,检查 consul 是否可用:
[root@localhost ~]# consul
Usage: consul [--version] [--help] <command> [<args>]
Available commands are:
agent Runs a Consul agent
catalog Interact with the catalog
event Fire a new event
exec Executes a command on Consul nodes
force-leave Forces a member of the cluster to enter the "left" state
info Provides debugging information for operators.
join Tell Consul agent to join cluster
keygen Generates a new encryption key
keyring Manages gossip layer encryption keys
kv Interact with the key-value store
leave Gracefully leaves the Consul cluster and shuts down
lock Execute a command holding a lock
maint Controls node or service maintenance mode
members Lists the members of a Consul cluster
monitor Stream logs from a Consul agent
operator Provides cluster-level tools for Consul operators
reload Triggers the agent to reload configuration files
rtt Estimates network round trip time between nodes
snapshot Saves, restores and inspects snapshots of Consul server state
validate Validate config files/directories
version Prints the Consul version
watch Watch for changes in Consul
[root@localhost ~]#
如果出现上面这样代表consul
是没问题的。
二、运行 Consul Agent
Consul安装之后,代理必须运行。 代理可以在服务器或客户端模式下运行。 每个数据中心都必须至少有一台服务器,但推荐使用3台或5台服务器。 一个单一的服务器部署是非常不推荐的,因为在故障情况下数据丢失是不可避免的。
所有其他代理以客户端模式运行。 客户端是一个非常轻量级的进程,它注册服务,运行健康检查,并将查询转发给服务器。 代理程序必须在集群中的每个节点上运行。
三、启动 Agent
为了简单起见,我们现在将以开发模式启动Consul代理。 这种模式对于快速简单地启动单节点Consul环境非常有用。 它并不打算在生产中使用,因为它不会持续任何状态。
[root@localhost consul]# consul agent -dev
==> Starting Consul agent...
==> Consul agent running!
Version: 'v1.0.1'
Node ID: '590309a6-71f6-6145-fe40-d2c5e203687f'
Node name: 'localhost.localdomain'
Datacenter: 'dc1' (Segment: '<all>')
Server: true (Bootstrap: false)
Client Addr: [127.0.0.1] (HTTP: 8500, HTTPS: -1, DNS: 8600)
Cluster Addr: 127.0.0.1 (LAN: 8301, WAN: 8302)
Encrypt: Gossip: false, TLS-Outgoing: false, TLS-Incoming: false
==> Log data will now stream in as it occurs:
2017/11/25 15:15:54 [DEBUG] Using random ID "590309a6-71f6-6145-fe40-d2c5e203687f" as node ID
2017/11/25 15:15:54 [INFO] raft: Initial configuration (index=1): [{Suffrage:Voter ID:590309a6-71f6-6145-fe40-d2c5e203687f Address:127.0.0.1:8300}]
2017/11/25 15:15:54 [INFO] serf: EventMemberJoin: localhost.localdomain.dc1 127.0.0.1
2017/11/25 15:15:54 [INFO] serf: EventMemberJoin: localhost.localdomain 127.0.0.1
2017/11/25 15:15:54 [INFO] agent: Started DNS server 127.0.0.1:8600 (udp)
2017/11/25 15:15:54 [INFO] raft: Node at 127.0.0.1:8300 [Follower] entering Follower state (Leader: "")
2017/11/25 15:15:54 [INFO] consul: Adding LAN server localhost.localdomain (Addr: tcp/127.0.0.1:8300) (DC: dc1)
2017/11/25 15:15:54 [INFO] consul: Handled member-join event for server "localhost.localdomain.dc1" in area "wan"
2017/11/25 15:15:54 [INFO] agent: Started DNS server 127.0.0.1:8600 (tcp)
2017/11/25 15:15:54 [INFO] agent: Started HTTP server on 127.0.0.1:8500 (tcp)
2017/11/25 15:15:54 [INFO] agent: started state syncer
2017/11/25 15:15:54 [WARN] raft: Heartbeat timeout from "" reached, starting election
2017/11/25 15:15:54 [INFO] raft: Node at 127.0.0.1:8300 [Candidate] entering Candidate state in term 2
2017/11/25 15:15:54 [DEBUG] raft: Votes needed: 1
2017/11/25 15:15:54 [DEBUG] raft: Vote granted from 590309a6-71f6-6145-fe40-d2c5e203687f in term 2. Tally: 1
2017/11/25 15:15:54 [INFO] raft: Election won. Tally: 1
2017/11/25 15:15:54 [INFO] raft: Node at 127.0.0.1:8300 [Leader] entering Leader state
2017/11/25 15:15:54 [INFO] consul: cluster leadership acquired
2017/11/25 15:15:54 [DEBUG] consul: Skipping self join check for "localhost.localdomain" since the cluster is too small
2017/11/25 15:15:54 [INFO] consul: member 'localhost.localdomain' joined, marking health alive
2017/11/25 15:15:54 [INFO] consul: New leader elected: localhost.localdomain
2017/11/25 15:15:54 [DEBUG] Skipping remote check "serfHealth" since it is managed automatically
2017/11/25 15:15:54 [INFO] agent: Synced node info
2017/11/25 15:15:54 [DEBUG] agent: Node info in sync
2017/11/25 15:15:57 [DEBUG] Skipping remote check "serfHealth" since it is managed automatically
2017/11/25 15:15:57 [DEBUG] agent: Node info in sync
2017/11/25 15:16:54 [DEBUG] consul: Skipping self join check for "localhost.localdomain" since the cluster is too small
2017/11/25 15:17:51 [DEBUG] Skipping remote check "serfHealth" since it is managed automatically
2017/11/25 15:17:51 [DEBUG] agent: Node info in sync
2017/11/25 15:17:54 [DEBUG] manager: Rebalanced 1 servers, next active server is localhost.localdomain.dc1 (Addr: tcp/127.0.0.1:8300) (DC: dc1)
2017/11/25 15:17:54 [DEBUG] consul: Skipping self join check for "localhost.localdomain" since the cluster is too small
如您所见,Consul代理已经启动并输出了一些日志数据。 从日志数据中,您可以看到我们的代理正在服务器模式下运行,并声称拥有集群领导权。 此外,当地成员已被标记为该集群的健康成员。
四、集群成员
在另一个终端运行consul members
,可以看到Consul集群的成员。 应该只看到一个成员(你自己):
[root@localhost ~]# consul members
Node Address Status Type Build Protocol DC Segment
localhost.localdomain 127.0.0.1:8301 alive server 1.0.1 2 dc1 <all>
输出显示了我们自己的节点,它正在运行的地址,运行状况,在集群中的角色以及一些版本信息。 额外的元数据可以通过提供-detailed
标志来查看。
[root@localhost ~]# consul members -detailed
Node Address Status Tags
localhost.localdomain 127.0.0.1:8301 alive build=1.0.1:9564c29,dc=dc1,id=590309a6-71f6-6145-fe40-d2c5e203687f,port=8300,raft_vsn=3,role=consul,segment=<all>,vsn=2,vsn_max=3,vsn_min=2,wan_join_port=8302
members
命令的输出基于gossip协议,并最终一致。 也就是说,在任何时候,当地代理所看到的可能与服务器上的状态不完全一致。 要获得完全一致,请使用HTTP API再将HTTP请求转发给Consul服务器:
[root@localhost ~]# curl localhost:8500/v1/catalog/nodes
[
{
"ID": "590309a6-71f6-6145-fe40-d2c5e203687f",
"Node": "localhost.localdomain",
"Address": "127.0.0.1",
"Datacenter": "dc1",
"TaggedAddresses": {
"lan": "127.0.0.1",
"wan": "127.0.0.1"
},
"Meta": {
"consul-network-segment": ""
},
"CreateIndex": 5,
"ModifyIndex": 6
}
]
除了HTTP API之外,还可以使用DNS接口查询节点。 请注意,必须确保将DNS查找默认情况下指向在端口8600上运行的Consul代理的DNS服务器。 DNS条目的格式(如“Armons-MacBook-Air.node.consul”)将在后面详细介绍。
[root@localhost ~]# dig @127.0.0.1 -p 8600 localhost.localdomain.node.consul
'
; <<>> DiG 9.9.4-RedHat-9.9.4-51.el7 <<>> @127.0.0.1 -p 8600 localhost.localdomain.node.consul
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 43915
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;localhost.localdomain.node.consul. IN A
;; ANSWER SECTION:
localhost.localdomain.node.consul. 0 IN A 127.0.0.1
;; Query time: 0 msec
;; SERVER: 127.0.0.1#8600(127.0.0.1)
;; WHEN: 六 11月 25 15:39:49 CST 2017
;; MSG SIZE rcvd: 78
五、停止 Agent
可以使用Ctrl-C(中断信号)正常停止代理。 中断代理之后,您应该看到它离开集群并关闭。
通过优雅地离开,Consul通知其他集群成员该节点离开。 如果强行杀死了代理进程,则集群的其他成员将检测到该节点失败。 成员离开时,其服务和检查将从目录中删除。 当一个成员失败时,其健康被简单地标记为关键,但不会从目录中删除。 Consul将自动尝试重新连接到失败的节点,使其能够从特定的网络条件恢复,而不再联系离开的节点。
此外,如果代理正在作为服务器运行,那么优雅的离开对于避免造成影响一致协议的潜在可用性中断很重要。 有关如何安全地添加和删除服务器的详细信息,请参阅指南部分。
六、注册服务
1、服务定义
服务可以通过提供服务定义或通过对HTTP API进行适当的调用来注册。
服务定义是注册服务最常用的方式,所以我们将在这一步中使用这种方法。 我们将建立在上一步中介绍的代理配置。
首先,为Consul配置创建一个目录。 Consul将所有配置文件加载到配置目录中,因此Unix系统上的一个通用约定是将目录命名为/etc/consul.d(.d后缀意味着“该目录包含一组配置文件”)。
[root@localhost etc]# sudo mkdir /etc/consul.d
接下来,我们将编写一个服务定义配置文件。 假设我们有一个名为“web”的服务在端口80上运行。另外,我们给它一个标签,我们可以使用它作为查询服务的附加方式:
[root@localhost ~]# echo '{"service": {"name": "web", "tags": ["rails"], "port": 80}}' | sudo tee /etc/consul.d/web.json
现在,重新启动代理程序,提供配置目录:
[root@localhost ~]# consul agent -dev -config-dir=/etc/consul.d
==> Starting Consul agent...
==> Consul agent running!
Version: 'v1.0.1'
Node ID: '94236f1c-2a29-85c5-b235-dd916485be5b'
Node name: 'localhost.localdomain'
Datacenter: 'dc1' (Segment: '<all>')
Server: true (Bootstrap: false)
Client Addr: [127.0.0.1] (HTTP: 8500, HTTPS: -1, DNS: 8600)
Cluster Addr: 127.0.0.1 (LAN: 8301, WAN: 8302)
Encrypt: Gossip: false, TLS-Outgoing: false, TLS-Incoming: false
==> Log data will now stream in as it occurs:
2017/11/25 16:16:51 [DEBUG] Using random ID "94236f1c-2a29-85c5-b235-dd916485be5b" as node ID
2017/11/25 16:16:51 [INFO] raft: Initial configuration (index=1): [{Suffrage:Voter ID:94236f1c-2a29-85c5-b235-dd916485be5b Address:127.0.0.1:8300}]
2017/11/25 16:16:51 [INFO] serf: EventMemberJoin: localhost.localdomain.dc1 127.0.0.1
2017/11/25 16:16:51 [INFO] serf: EventMemberJoin: localhost.localdomain 127.0.0.1
2017/11/25 16:16:51 [INFO] agent: Started DNS server 127.0.0.1:8600 (udp)
2017/11/25 16:16:51 [INFO] raft: Node at 127.0.0.1:8300 [Follower] entering Follower state (Leader: "")
2017/11/25 16:16:51 [INFO] consul: Adding LAN server localhost.localdomain (Addr: tcp/127.0.0.1:8300) (DC: dc1)
2017/11/25 16:16:51 [INFO] consul: Handled member-join event for server "localhost.localdomain.dc1" in area "wan"
2017/11/25 16:16:51 [INFO] agent: Started DNS server 127.0.0.1:8600 (tcp)
2017/11/25 16:16:51 [INFO] agent: Started HTTP server on 127.0.0.1:8500 (tcp)
2017/11/25 16:16:51 [INFO] agent: started state syncer
2017/11/25 16:16:52 [WARN] raft: Heartbeat timeout from "" reached, starting election
2017/11/25 16:16:52 [INFO] raft: Node at 127.0.0.1:8300 [Candidate] entering Candidate state in term 2
2017/11/25 16:16:52 [DEBUG] raft: Votes needed: 1
2017/11/25 16:16:52 [DEBUG] raft: Vote granted from 94236f1c-2a29-85c5-b235-dd916485be5b in term 2. Tally: 1
2017/11/25 16:16:52 [INFO] raft: Election won. Tally: 1
2017/11/25 16:16:52 [INFO] raft: Node at 127.0.0.1:8300 [Leader] entering Leader state
2017/11/25 16:16:52 [INFO] consul: cluster leadership acquired
2017/11/25 16:16:52 [DEBUG] consul: Skipping self join check for "localhost.localdomain" since the cluster is too small
2017/11/25 16:16:52 [INFO] consul: member 'localhost.localdomain' joined, marking health alive
2017/11/25 16:16:52 [INFO] consul: New leader elected: localhost.localdomain
2017/11/25 16:16:52 [DEBUG] Skipping remote check "serfHealth" since it is managed automatically
2017/11/25 16:16:52 [INFO] agent: Synced service "web"
2017/11/25 16:16:52 [DEBUG] agent: Node info in sync
2017/11/25 16:16:52 [DEBUG] agent: Service "web" in sync
2017/11/25 16:16:52 [DEBUG] agent: Node info in sync
2017/11/25 16:16:52 [DEBUG] Skipping remote check "serfHealth" since it is managed automatically
2017/11/25 16:16:52 [DEBUG] agent: Service "web" in sync
2017/11/25 16:16:52 [DEBUG] agent: Node info in sync
您会注意到它在输出中“同步”了Web服务。 这意味着代理程序从配置文件加载了服务定义,并已成功将其注册到服务目录中。
如果您想注册多个服务,您可以在Consul配置目录中创建多个服务定义文件。
2、查询服务
一旦代理启动并且服务同步,我们可以使用DNS或HTTP API来查询服务。
DNS API
我们首先使用DNS API来查询我们的服务。 对于DNS API,服务的DNS名称是NAME.service.consul。 默认情况下,所有DNS名称始终在consul命名空间中,尽管这是可配置的。 服务子域告诉Consul我们正在查询服务,NAME是服务的名称。
对于我们注册的Web服务,这些约定和设置会生成web.service.consul的完全限定的域名:
[root@localhost ~]# dig @127.0.0.1 -p 8600 web.service.consul
; <<>> DiG 9.9.4-RedHat-9.9.4-51.el7 <<>> @127.0.0.1 -p 8600 web.service.consul
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 58483
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;web.service.consul. IN A
;; ANSWER SECTION:
web.service.consul. 0 IN A 127.0.0.1
;; Query time: 0 msec
;; SERVER: 127.0.0.1#8600(127.0.0.1)
;; WHEN: 六 11月 25 16:22:29 CST 2017
;; MSG SIZE rcvd: 63
正如你所看到的,一个A记录返回了服务可用的节点的IP地址。 A记录只能保存IP地址。
您也可以使用DNS API来检索整个地址/端口对作为SRV记录:
[root@localhost ~]# dig @127.0.0.1 -p 8600 web.service.consul SRV
; <<>> DiG 9.9.4-RedHat-9.9.4-51.el7 <<>> @127.0.0.1 -p 8600 web.service.consul SRV
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 65288
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 3
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;web.service.consul. IN SRV
;; ANSWER SECTION:
web.service.consul. 0 IN SRV 1 1 80 localhost.localdomain.node.dc1.consul.
;; ADDITIONAL SECTION:
localhost.localdomain.node.dc1.consul. 0 IN A 127.0.0.1
localhost.localdomain.node.dc1.consul. 0 IN TXT "consul-network-segment="
;; Query time: 0 msec
;; SERVER: 127.0.0.1#8600(127.0.0.1)
;; WHEN: 六 11月 25 16:25:21 CST 2017
;; MSG SIZE rcvd: 156
SRV记录表示Web服务正在端口80上运行,并且存在于节点localhost.localdomain.node.dc1.consul.上。DNS使用该记录的A记录返回附加部分。
最后,我们也可以使用DNS API来按标签过滤服务。 基于标记的服务查询的格式是TAG.NAME.service.consul。 在下面的例子中,我们向Consul询问所有带有“rails”标签的web服务。 自从我们使用该标签注册我们的服务后,我们得到了成功的回应:
[root@localhost ~]# dig @127.0.0.1 -p 8600 rails.web.service.consul
; <<>> DiG 9.9.4-RedHat-9.9.4-51.el7 <<>> @127.0.0.1 -p 8600 rails.web.service.consul
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 41016
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;rails.web.service.consul. IN A
;; ANSWER SECTION:
rails.web.service.consul. 0 IN A 127.0.0.1
;; Query time: 0 msec
;; SERVER: 127.0.0.1#8600(127.0.0.1)
;; WHEN: 六 11月 25 16:29:10 CST 2017
;; MSG SIZE rcvd: 69
HTTP API
除了DNS API之外,HTTP API还可以用来查询服务:
[root@localhost ~]# curl http://localhost:8500/v1/catalog/service/web
[
{
"ID": "94236f1c-2a29-85c5-b235-dd916485be5b",
"Node": "localhost.localdomain",
"Address": "127.0.0.1",
"Datacenter": "dc1",
"TaggedAddresses": {
"lan": "127.0.0.1",
"wan": "127.0.0.1"
},
"NodeMeta": {
"consul-network-segment": ""
},
"ServiceID": "web",
"ServiceName": "web",
"ServiceTags": [
"rails"
],
"ServiceAddress": "",
"ServicePort": 80,
"ServiceEnableTagOverride": false,
"CreateIndex": 6,
"ModifyIndex": 6
}
]
目录API提供了托管给定服务的所有节点。 正如我们稍后将看到的健康检查一样,您通常只需要查询检查通过的健康实例。 这是DNS正在做的事情。 这是一个查询只查找健康的实例:
[root@localhost ~]# curl 'http://localhost:8500/v1/health/service/web?passing'
[
{
"Node": {
"ID": "94236f1c-2a29-85c5-b235-dd916485be5b",
"Node": "localhost.localdomain",
"Address": "127.0.0.1",
"Datacenter": "dc1",
"TaggedAddresses": {
"lan": "127.0.0.1",
"wan": "127.0.0.1"
},
"Meta": {
"consul-network-segment": ""
},
"CreateIndex": 5,
"ModifyIndex": 6
},
"Service": {
"ID": "web",
"Service": "web",
"Tags": [
"rails"
],
"Address": "",
"Port": 80,
"EnableTagOverride": false,
"CreateIndex": 6,
"ModifyIndex": 6
},
"Checks": [
{
"Node": "localhost.localdomain",
"CheckID": "serfHealth",
"Name": "Serf Health Status",
"Status": "passing",
"Notes": "",
"Output": "Agent alive and reachable",
"ServiceID": "",
"ServiceName": "",
"ServiceTags": [],
"Definition": {},
"CreateIndex": 5,
"ModifyIndex": 5
}
]
}
]
3、更新服务
服务定义可以通过更改配置文件并向代理发送SIGHUP来更新。 这使您可以更新服务,而不会出现任何停机或无法提供服务查询的情况。
或者,可以使用HTTP API动态地添加,删除和修改服务。
七、Consul 集群
我们已经开始了我们的第一个代理,并注册和查询该代理的服务。 这显示了使用Consul是多么的容易,但并没有表明如何将其扩展到可扩展的生产级服务发现基础设施。 在这一步中,我们将创建我们的第一个真正的集群与多个成员。
当一个Consul代理启动时,它不知道任何其他节点:它是一个孤立的集群。 要了解其他集群成员,代理必须加入现有集群。 要加入现有的集群,只需要知道一个现有的成员。 代理加入后,会与该成员通讯,并迅速发现集群中的其他成员。 Consul代理可以加入任何其他代理,而不仅仅是服务器模式下的代理。
1、启动代理
在我们之前的例子中,我们使用了-dev标志来快速设置一个开发服务器。 但是,这不足以在集群环境中使用。 我们将从这里省略-dev标志,而是指定我们的集群标志。
集群中的每个节点都必须具有唯一的名称。 默认情况下,Consul使用机器的主机名,但我们将使用-node
命令行选项手动覆盖它。
我们还将指定一个-bind
:这是Consul侦听的地址,它必须可以被集群中的所有其他节点访问。 虽然绑定地址不是绝对必要的,但最好提供一个。 Consul将默认尝试侦听系统上的所有IPv4接口,但如果找到多个私有IP,将无法启动错误。 由于生产服务器通常具有多个接口,因此指定一个绑定地址可确保您永远不会将Consul绑定到错误的接口。
第一个节点将作为我们在这个集群中唯一的服务器,我们用-server
来指明这一点。
-bootstrap-expect
选项向Consul服务器提示我们期望加入的其他服务器节点的数量。 此选项的用途是延迟复制日志的引导,直到预期数量的服务器成功加入。
我们已经将-enable_script_checks
选项设置为true,以启用可以执行外部脚本的运行状况检查。 这将在后面的例子中使用。 对于生产用途,您希望将ACL配置为与此配合使用,以控制注册任意脚本的能力。
最后,我们添加-config-dir
选项,标记可以找到服务和检查定义的位置。
总而言之,这些设置产生一个这样的consul代理命令:
[root@localhost ~]# consul agent -server -bootstrap-expect=1 -data-dir=/tmp/consul -node=agent-one -bind=192.168.100.101 -enable-script-checks=true -config-dir=/etc/consul.d
现在,在另一个终端中,我们将连接到第二个节点。
这次,我们将-bind
设置为第二个节点的IP,并将-node
设置为agent-two。 由于这个节点不会是Consul服务器,所以我们不提供-server
。
总而言之,这些设置产生一个这样的consul代理命令:
[root@localhost ~]# consul agent -data-dir=/tmp/consul -node=agent-two -bind=192.168.100.102 -enable-script-checks=true -config-dir=/etc/consul.d
此时,您有两个Consul代理正在运行:一个服务器和一个客户端。 两个Consul代理人对彼此还是一无所知,都是他们自己的单节点集群的一部分。 您可以通过对每个代理运行consul members
来验证这一点,并注意到每个代理只能看到一个成员。
2、加入集群
现在,我们将通过在新终端中运行以下命令来告诉第一个代理加入第二个代理:
[root@localhost ~]# consul join 192.168.100.101
Successfully joined cluster by contacting 1 nodes.
如果在虚拟机里面运行上面的命令提示下面的失败的话,在每台虚拟机上执行下这个命令:
[root@localhost ~]# consul join 192.168.100.101
Error joining address '192.168.100.101': Unexpected response code: 500 (1 error(s) occurred:
* Failed to join 192.168.100.101: dial tcp 192.168.100.101:8301: getsockopt: no route to host)
Failed to join any nodes.
[root@localhost ~]# sudo iptables -F
您应该在每个代理日志中看到一些日志输出。 如果仔细阅读,您会看到他们收到了加入信息。 如果你对每个代理执行consul members
,你会看到两个代理人现在彼此了解:
[root@localhost ~]# consul members
Node Address Status Type Build Protocol DC Segment
agent-one 192.168.100.101:8301 alive server 1.0.1 2 dc1 <all>
agent-two 192.168.100.102:8301 alive client 1.0.1 2 dc1 <default>
记住:要加入集群,Consul代理只需要了解一个现有的成员。 加入集群后,代理人互相传播完整的会员信息。
3、在启动时自动加入集群
理想情况下,每当新节点出现在您的数据中心时,它就会自动加入Consul集群,无需人工干预。 Consul通过启用AWS,Google Cloud或Azure中的实例的自动发现功能,使用给定的标签 key/value来促进自动加入。 要使用集成,请将retry_join_ec2
,retry_join_gce
或retry_join_azure
嵌套对象添加到您的Consul配置文件。 这将允许新的节点加入集群,而不需要任何硬编码的配置。 或者,您可以在启动时使用-join
选项或start_join
设置以及其他已知Consul代理的硬编码地址加入集群。
4、查询节点
就像查询服务一样,Consul也有查询节点的API。 您可以通过DNS或HTTP API执行此操作。
对于DNS API,名称的结构是NAME.node.consul或NAME.node.DATACENTER.consul。 如果数据中心被省略,Consul将仅搜索本地数据中心。
例如,从“agent-one”中,我们可以查询节点“agent-two”的地址:
[root@localhost etc]# dig @127.0.0.1 -p 8600 agent-two.node.consul
; <<>> DiG 9.9.4-RedHat-9.9.4-51.el7 <<>> @127.0.0.1 -p 8600 agent-two.node.consul
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 57127
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;agent-two.node.consul. IN A
;; ANSWER SECTION:
agent-two.node.consul. 0 IN A 192.168.100.102
;; Query time: 0 msec
;; SERVER: 127.0.0.1#8600(127.0.0.1)
;; WHEN: 六 11月 25 17:31:29 CST 2017
;; MSG SIZE rcvd: 66
除了服务之外,查找节点的能力对于系统管理任务来说是非常有用的。 例如,知道要通过SSH连接的节点的地址与将节点作为Consul集群的一部分并查询它一样简单。
5、离开集群
要离开集群,可以正常退出代理(使用Ctrl-C)或强制终止其中一个代理。 优雅地离开允许节点转换到离开状态; 否则,其他节点将检测到它失败。
八、健康检查
现在我们已经看到了运行Consul,添加节点和服务以及查询这些节点和服务的简单性。 在本节中,我们将介绍为节点和服务添加健康检查。 健康检查是服务发现的关键组件,可以防止使用不健康的服务。
此步骤建立在之前创建的Consul集群上。 此时,您应该运行一个双节点集群。
1、检查定义
与服务类似,可以通过提供检查定义或通过对HTTP API进行适当的调用来注册检查。
我们将使用检查定义方法,因为就像服务一样,定义是设置检查最常用的方法。
在第二个节点的Consul配置目录中创建两个定义文件:
[root@localhost ~]# echo '{"check": {"name": "ping", "script": "ping -c1 google.com >/dev/null", "interval": "30s"}}' >/etc/consul.d/ping.json
[root@localhost ~]# echo '{"service": {"name": "web", "tags": ["rails"], "port": 80, "check": {"script": "curl localhost >/dev/null 2>&1", "interval": "10s"}}}' >/etc/consul.d/web.json
第一个定义添加了一个名为“ping”的主机级别的检查。 此检查运行间隔30秒,调用ping -c1 google.com
。 在基于脚本的运行状况检查上,检查以与启动Consul进程相同的用户身份运行。 如果该命令以非零退出码退出,则该节点将被标记为不健康。 这是任何基于脚本的健康检查的约定。
第二个命令修改名为web的服务,添加一个检查,每隔10秒通过curl发送一个请求,以验证Web服务器是否可访问。 与主机级运行状况检查一样,如果脚本以非零退出代码退出,服务将被标记为不健康。
现在,重新启动第二个代理,用consul reload
加载它,或者发送一个SIGHUP信号。 您应该看到以下日志行:
[root@localhost ~]# consul reload
Configuration reload triggered
2017/11/26 10:47:41 [INFO] Reloading configuration...
2017/11/26 10:47:41 [WARN] agent: check "service:web" has the 'script' field, which has been deprecated and replaced with the 'args' field. See https://www.consul.io/docs/agent/checks.html
2017/11/26 10:47:41 [WARN] agent: check "service:web" has the 'script' field, which has been deprecated and replaced with the 'args' field. See https://www.consul.io/docs/agent/checks.html
2017/11/26 10:47:41 [WARN] agent: check "ping" has the 'script' field, which has been deprecated and replaced with the 'args' field. See https://www.consul.io/docs/agent/checks.html
2017/11/26 10:47:41 [WARN] agent: check "ping" has the 'script' field, which has been deprecated and replaced with the 'args' field. See https://www.consul.io/docs/agent/checks.html
2017/11/26 10:47:41 [INFO] agent: Synced service "web"
2017/11/26 10:47:41 [INFO] agent: Synced check "ping"
2017/11/26 10:47:47 [WARN] agent: Check "service:web" is now critical
2017/11/26 10:47:57 [WARN] agent: Check "service:web" is now critical
2017/11/26 10:48:04 [WARN] agent: Check "ping" is now warning
2017/11/26 10:48:04 [INFO] agent: Synced check "ping"
2017/11/26 10:48:07 [WARN] agent: Check "service:web" is now critical
2017/11/26 10:48:17 [WARN] agent: Check "service:web" is now critical
2017/11/26 10:48:27 [WARN] agent: Check "service:web" is now critical
前几行表示代理已经同步了新的定义。 最后一行表明我们为Web服务添加的检查是至关重要的。 这是因为我们实际上没有运行Web服务器,所以curl测试失败了!
2、检查健康状态
现在我们已经添加了一些简单的检查,我们可以使用HTTP API来检查它们。 首先,我们可以使用这个命令查找任何失败的检查(注意,这可以在任一节点上运行):
[root@localhost etc]# curl http://localhost:8500/v1/health/state/critical
[{"Node":"agent-two","CheckID":"service:web","Name":"Service 'web' check","Status":"critical","Notes":"","Output":"","ServiceID":"web","ServiceName":"web","ServiceTags":["rails"],"Definition":{},"CreateIndex":230,"ModifyIndex":262}]
我们可以看到,只有一个检查,我们的Web服务检查,在危险(critical)状态。
另外,我们可以尝试使用DNS查询Web服务。 由于服务不健康,Consul不会返回任何结果:
[root@localhost ~]# dig @127.0.0.1 -p 8600 web.service.consul
; <<>> DiG 9.9.4-RedHat-9.9.4-51.el7 <<>> @127.0.0.1 -p 8600 web.service.consul
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 38998
;; flags: qr aa rd; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;web.service.consul. IN A
;; AUTHORITY SECTION:
consul. 0 IN SOA ns.consul. hostmaster.consul. 1511666146 3600 600 86400 0
;; Query time: 1 msec
;; SERVER: 127.0.0.1#8600(127.0.0.1)
;; WHEN: 日 11月 26 11:15:46 CST 2017
;; MSG SIZE rcvd: 97
九、KV Data
Consul除了提供服务发现和综合健康检查之外,还提供一个易于使用的KV存储。 这可以用来保存动态配置,协助服务协调,建立leader选举,并使开发人员可以考虑构建的任何东西。
1、简单使用
为了演示有多简单,我们将操作K / V存储中的几个键。 有两种方式与Consul KV存储进行交互:通过HTTP API和Consul KV CLI。 以下示例显示使用Consul KV CLI,因为它是最容易入门的。 对于更高级的集成,您可能需要使用Consul KV HTTP API。
首先让我们探索KV存储。 我们可以向Consul询问名为redis / config / minconns
的路径上的key的值:
[root@localhost ~]# consul kv get redis/config/minconns
Error! No key exists at: redis/config/minconns
正如你所看到的,我们没有得到任何结果,这是合理的,因为KV存储没有数据。 接下来,我们可以insert或put 值到 KV 存储中。
[root@localhost ~]# consul kv put redis/config/minconns 1
Success! Data written to: redis/config/minconns
[root@localhost ~]# consul kv put redis/config/maxconns 25
Success! Data written to: redis/config/maxconns
[root@localhost ~]# consul kv put -flags=42 redis/config/users/admin abcd1234
Success! Data written to: redis/config/users/admin
现在我们在存储中有key,我们可以查询单个 key 的 value:
[root@localhost ~]# consul kv get redis/config/minconns
1
Consul保留有关使用-detailed
标志检索的字段的其他元数据:
[root@localhost ~]# consul kv get -detailed redis/config/minconns
CreateIndex 517
Flags 0
Key redis/config/minconns
LockIndex 0
ModifyIndex 517
Session -
Value 1
对于“redis / config / users / admin”这个键,我们设置了一个标志值42。所有的键都支持设置一个64位的整数标志值。 这不是Consul在内部使用的,但客户可以使用它为任何KV添加有意义的元数据。
可以使用递归选项列出存储的所有 key和 value。 结果将以字典顺序返回:
[root@localhost ~]# consul kv get -recurse
redis/config/maxconns:25
redis/config/minconns:1
redis/config/users/admin:abcd1234
要从Consul KV中删除一个 key,发出“删除” 命令:
[root@localhost ~]# consul kv delete redis/config/minconns
Success! Deleted key: redis/config/minconns
也可以使用递归选项删除整个前缀:
[root@localhost ~]# consul kv delete -recurse redis
Success! Deleted keys with prefix: redis
要更新现有key的值,请在相同路径上put一个值:
[root@localhost ~]# consul kv put foo bar
Success! Data written to: foo
[root@localhost ~]# consul kv get foo
bar
[root@localhost ~]# consul kv put foo zip
Success! Data written to: foo
[root@localhost ~]# consul kv get foo
zip
Consul可以使用Check-And-Set操作提供原子键更新。 要执行CAS操作,请指定-cas选项:
[root@localhost ~]# consul kv get -detailed foo
CreateIndex 710
Flags 0
Key foo
LockIndex 0
ModifyIndex 716
Session -
Value bar
[root@localhost ~]# consul kv put -cas -modify-index=716 foo bar
Success! Data written to: foo
[root@localhost ~]# consul kv put -cas -modify-index=716 foo bar
Error! Did not write to foo: CAS failed
在这种情况下,第一个CAS更新成功,因为索引是716。第二个操作失败,因为索引不再是716。
十、Consul Web UI
Consul支持web ui界面。UI可用于查看所有服务和节点,查看所有运行状况检查及其当前状态,以及读取和设置键/值数据。 用户界面自动支持多数据中心。
要设置自带的UI,请使用-ui
参数启动Consul代理:
consul agent -ui
UI可以在与HTTP API相同的端口上的/ui
路径中使用。 默认情况下,这是http://localhost:8500/ui
。
您可以在这里查看Consul Web UI的现场演示。
注意:如果在虚拟机上安装的 Consul,在主机上访问不到时,可以在虚拟机里执行iptables -F
命令。