Consul 集群

单个节点的 consul agent 在测试时非常容易使用,但是如果想要在生产环境中搭建一个稳定的可靠的 consul 服务还需要对 consul cluster 有深入了解。

当一个 consul agent 启动时,它本身对其它 consul 节点是一无所知的,这一个节点组成了一个独立的集群。如果想要知道其它的集群成员,这个 agent 必须在启动时加入一个已经存在集群。为了加入一个集群,这个 agent 必须知道至少一个独立存在的 agent member,待加入之后,这个 agent 会和这个节点进行通讯获取其它节点信息。

一个 consul 的 agent 可以加入任何一个 agent,不仅包括 server mode 的 agent。

启动多个 agent

为了模拟一个真实的集群,我们将启动通过 vagrant 启动两个节点,vagrantfile 见 demo section of the Consul repo

vagrant 的下载配置非常简单,进入 https://www.vagrantup.com/downloads.html 选择所需要的版本,安装即可,注意翻墙。

首先启动两个节点:

1
vagrant up

待系统可用之后,就可以进入机器进行集群相关的配置:

1
vagrant ssh n1

在前文中我们为了测试方便使用的 -dev flag 来启动一个 development server,但是在生产环境中我们将去掉这个参数。

每个在 cluster 中的 node 必须要有唯一的名字,默认情况下 consul 使用 hostname,但是我们也可以使用 -node command-line option 进行覆盖。

启动我们也可以指定 consul listen on 的地址,这个地址必须能被 cluster 中其它节点连接和使用。虽然 bind address 不是严格要求,但是最佳实践中总是推荐必须指定一个,consul 默认会监听所有 ipv4 的 interface,如果发现了多个 私有 ip,则停止 bind。

第一个节点在我们整个 cluster 中将是一个单独的 server ,详见 server switch。

-bootstrap-expect flag 揭示了整个 cluster 中其它 server node 的数量,这个 flag 的目的是为了延迟 replicated log 复制,直到指定数量的 server 全部加入 cluster,详见 bootstrapping guide

在这个 cluster 例子中,我们启用了 -enable-script-checks flag 来执行内部的脚本进行 health check。在生产环境中个,你可以配置 ACLs来配合这个 flag 来注册任意的脚本。

1
2
3
4
vagrant@n1:~$ consul agent -server -bootstrap-expect=1 \
-data-dir=/tmp/consul -node=agent-one -bind=172.20.20.10 \
-enable-script-checks=true -config-dir=/etc/consul.d
...

然后我们再进入第二个 node:

1
vagrant ssh n2

第二个agent 启动时我们指定了 vargrantfile 中指定的 ip 和 node name,由于这个 node 不是 server,所以我们不必提供 server switch。

1
2
3
vagrant@n2:~$ consul agent -data-dir=/tmp/consul -node=agent-two \
-bind=172.20.20.11 -enable-script-checks=true -config-dir=/etc/consul.d
...

至此,我们有两个 consul agent 启动,一个是 server,一个是 client,两个 agent 彼此之间互相不知道,各自形成一个独立的 单节点 cluster,可以使用 consul members 命令来验证这一点。

加入 cluster

现在,我们来告诉第一个 agent 加入第二个 agent:

1
2
3
4
$ vagrant ssh n1
...
vagrant@n1:~$ consul join 172.20.20.11
Successfully joined cluster by contacting 1 nodes.

我们可以在两个 agent logs 看到它们彼此加入的信息:

1
2
3
4
2018/05/16 10:02:33 [INFO] agent: (LAN) joining: [172.20.20.11]
2018/05/16 10:02:33 [INFO] serf: EventMemberJoin: agent-two 172.20.20.11
2018/05/16 10:02:33 [INFO] agent: (LAN) joined: 1 Err: <nil>
2018/05/16 10:02:33 [INFO] consul: member 'agent-two' joined, marking health alive

再次执行 consul members 可以进行验证,两个节点已经相互知道彼此了:

1
2
3
4
vagrant@n1:~$ consul members
Node Address Status Type Build Protocol DC Segment
agent-one 172.20.20.10:8301 alive server 1.1.0 2 dc1 <all>
agent-two 172.20.20.11:8301 alive client 1.1.0 2 dc1 <default>

记住,为了加入一个集群,consul agent 仅仅只需要知道一个已经存在的 member 即可。

在 agent 启动时自动加入 cluster

理想的情况下,一个 agent 启动时应该自动加入 cluster 而不需要人工进行干预,consul 可以在各个云平台通过给定的 tag 进行自动发现。我们也可以在 agent 启动时手动指定节点信息 -join flag。

查询节点

和查询 service 类似,consul 也提供了类似的 API 通过 DNS 和 HTTP 的方式来查询节点信息,对 DNS API 来说,结构是 NAME.node.consul orNAME.node.DATACENTER.consul,如果 datacenter 被移除,consul 只会在本地 datacenter 查询:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
vagrant@n1:~$ dig @127.0.0.1 -p 8600 agent-two.node.consul
; <<>> DiG 9.9.5-9+deb8u14-Debian <<>> @127.0.0.1 -p 8600 agent-two.node.consul
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 46375
;; 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 172.20.20.11

;; Query time: 0 msec
;; SERVER: 127.0.0.1#8600(127.0.0.1)
;; WHEN: Wed May 16 10:06:26 GMT 2018
;; MSG SIZE rcvd: 66

查询节点信息对系统管理员特别有用,可以快速获得节点地址。

离开 cluster

如果想让 agent 离开节点,可以使用 ctrl-c 或者强制 agent 退出,gracefully 退出能够让节点过渡到 left 的状态,其它强制手段执行退出,其它节点会自动检测并标记节点为 failed。

参考资料

三月沙 wechat
扫描关注 wecatch 的公众号