搭建 Consul DataCenter
当一个 Consul agnet 启动时,它并不知道任何其他节点,它是一个孤立的集群,集群中只有它自己。 要让 agnet 获取集群中其它成员节点的信息,只要让它加入集群即 可。一旦加入集群后,agent 节点将依赖于 gossip 流言协议快速发现集群中的所有其它节点。Consul agent 可以加入任何其他 agnet,而不仅仅是 server monde 下的 agent。
集群中的每个节点都必须具有唯一的名称。 默认情况下,Consul 使用机器的主机名,可以使用 -node 命令行选项指定。
我们还可以使用 -bind 选项指定绑定地址:这是 Consul 侦听的地址,它必须可由集群中的所有其他节点访问。 虽然绑定地址不是绝对必要的,但最好提供一个绑定地址。 Consul 将默认尝试侦听系统上的所有 IPv4 接口,但如果找到多个专用IP,则将无法启动并报错。
第一个节点将作为我们集群中的唯一 server 节点,我们用 -server 选项来指示这一点。
-bootstrap-expect 标志向 Consul server 提示我们期望加入的其他 server 节点的数量。 此标志的目的是延迟复制日志的引导,直到预期的 server 数量已成功加入。 你 可以在 bootstrapping 指南中阅读更多。
-bootstrap-expect 和 -bootstrap 是冲突的。
搭建 Server 集群
配置文件启动
#server节点,使用配置文件启动简单样例
test@localhost:~$ cat /home/test/consul/conf/consul.json
{
"datacenter": "dc1", #自定义数据中心命名,区分该节点数据哪个数据中心。
"data_dir": "/home/push/consul/data", #Path to a data directory to store agent state。
"log_level": "INFO", "node_name": "push-uq24", "server": true,
"ui": true, "bootstrap_expect": 2,
#输出日志级别,默认是标准输出STD的方式。
#自定义节点名称,节点标识
#节点属性,server还是client。
#是否打开ui界面化访问
#通过bootstrap-expect: X(大于1的数字)打开。简单来说就是节点会“期待”有多少个节点加入,待有足够的节点加入后,才使用consul的算法选举leader。如果需要保持每个server节点的配置/启动方式一样,那么使bootstrap-expect模式是一个较好的选择。
"bind_addr": "0.0.0.0", "client_addr": "0.0.0.0", "retry_interval": "3s", "raft_protocol": 3, "enable_debug": false, "rejoin_after_leave": true, "enable_syslog": false
}
#server服务监听的ip地址 #client监听的ip地址 #两次join之间的时间间隔,默认是30s
注意:bootstrap不能和bootstrap_expect参数同时使用,通过bootstrap: true或者bootstrap-expect: 1打开。这个方式启动的consul server节点将可以自己选 举为leader(与master相似)。由于一个集群中只能存在一个leader,所以consul官方文档明确指出一个集群(datacenter)中只能有一个server节点处于bootstrap模 式。而且在要往一个已经稳定运行的集群中加入server节点,这个节点不能以bootstrap方式启动
test@localhost:~$ cat /home/test/consul/conf/consul.json
{
"datacenter": "dc1",
"data_dir": "/home/push/consul/data",
"log_level": "INFO",
"node_name": "push-uq20",
"server": false,
"bootstrap_expect": 0,
"retry_join": ["10.200.101.159 ","10.170.19.233","10.200.17.34"], "bind_addr": "10.170.17.28",
"client_addr": "10.170.17.28",
"retry_interval": "3s",
"raft_protocol": 3,
"enable_debug": false,
"rejoin_after_leave": true,
"enable_syslog": false
}
test@localhost:~$ cat /home/test/var/conf/supervisor/s_consul.conf
[program:consul]
command=/usr/local/bin/consul agent -config-dir /home/push/consul/conf process_name=%(program_name)s
user=push
numprocs=1
autostart=true
autorestart=true
startsecs=2
startretries=3
redirect_stderr=true
stdout_logfile_backups=10
stdout_logfile_maxbytes=300MB stdout_logfile=/home/push/var/log/supervisor/s_%(program_name)s.log
命令行启动
- Server node1 节点:
# mkdir /etc/consule.d
# consul agent -server -bootstrap-expect=3 \
-data-dir=/tmp/consul -config-dir=/etc/consul.d \
-bind=192.168.112.5 -client=192.168.112.5 \
-dns-port=53 -recursor=223.5.5.5 \
-datacenter=gd1 -domain=consul
- Server node2 节点:
# mkdir /etc/consule.d
# consul agent -server -bootstrap-expect=3 \
-data-dir=/tmp/consul -config-dir=/etc/consul.d \
-bind=192.168.112.5 -client=192.168.112.5 \
-dns-port=53 -recursor=223.5.5.5 \
-datacenter=gd1 -domain=consul
- Server node3 节点:
# mkdir /etc/consule.d
# consul agent -server -bootstrap-expect=3 \
-data-dir=/tmp/consul -config-dir=/etc/consul.d \
-bind=192.168.112.3 -client=192.168.112.3 \
-dns-port=53 -recursor=223.5.5.5 \
-datacenter=gd1 -domain=consul
此时,三个 server 节点还不知道其它 server 节点的存在,以 node1 节点为例:
# consul members -rpc-addr=192.168.112.5:8400
Node Address Status Type Build Protocol DC i-infra-112-05 192.168.112.5:8301 alive server 0.7.2 2 gd1 # consul info -rpc-addr=192.168.112.5:8400
agent:
check_ttls = 0
checks = 0
services = 1
build:
prerelease =
revision = 'a9afa0c'
version = 0.7.2
consul:
bootstrap = false
known_datacenters = 1
leader = false
leader_addr =
server = true
...
Supervisor consul.sh 脚本
#!/usr/bin/env bash
CONFIG_DIR="/etc/consul.d"
DATA_DIR="/tmp/consul"
for dir in $CONFIG_DIR $DATA_DIR
do
[ ! -e "$dir" ] && mkdir -p $dir
done
DATA_CENTER="GD1" ; DOMAIN="consul" ; BOOTSTRAP_EXPECT=3
IPADDR=$(ifconfig eth0 | grep -oP '\d.+(?= (Bcast:|netmask))')
server_vars=(
-server -ui
-bootstrap-expect=$BOOTSTRAP_EXPECT
)
agent_vars=(
-join 192.168.112.5
-join 192.168.112.4
-join 192.168.112.3
)
consul_agent() {
exec consul agent -data-dir=$DATA_DIR -config-dir=$CONFIG_DIR \
-bind=$IPADDR -client=$IPADDR \
-datacenter=$DATA_CENTER -domain=$DOMAIN \
-dns-port=53 -recursor=223.5.5.5 \
"$@" >/tmp/consul/consul.log 2>&1
}
if [ x"$1" == x"server" ] then
consul_agent ${server_vars[@]} elif [ x"$1" == x"agent" ]
then
consul_agent ${agent_vars[@]}
fi
systemd 脚本
支持 consul server 和 agent,更改 ExecStart 命令启动参数即可:
# cat consul-agent.service
[Unit]
Description=Consul agent server
After=network.target Wants=network.target
[Service]
EnvironmentFile=-/etc/consul/consul.conf
#ExecStart=/apex.fw/bin/consul.sh server
ExecStart=/apex.fw/bin/consul.sh agent Restart=on-failure
Type=simple
[Install]
WantedBy=multi-user.target
触发 lender 选举
在 node1 节点上,将其它 server 节点加入集群中:
# consul join -rpc-addr=192.168.112.5:8400 192.168.112.4 192.168.112.3
Successfully joined cluster by contacting 2 nodes.
- 查看 cluster mebers:
# consul members -rpc-addr=192.168.112.5:8400
Node Address Status Type Build Protocol DC
I-infra-112-03 192.168.112.3:8301 alive server 0.7.2 2 gd1
I-infra-112-04 192.168.112.4:8301 alive server 0.7.2 2 gd1
i-infra-112-05 192.168.112.5:8301 alive server 0.7.2 2 gd1
- 添加 client agent 节点
Consul 服务由 Supervisor 控制,通过传递 agent 参数,启动为 Consul client agent 节点。
# cat /etc/supervisord.d/consul.ini
[program:consul]
directory=/apex.fw/bin/
command=/bin/bash consul.sh agent
autorestart=true
DNS Caching
DNS 是 Consult提供的一个主要接口。使用 DNS 是一种不需要高度集成就可以将 Consul 集成到已有的基础设施中的简单方式。
默认情况下 Consul 服务的所有 DNS 查询数据不会长期保留(0 Time To Live),这防止了所有缓存。它的优势就是每个 DNS 查询都是重新获取的,这样就可以提供最及时的 DNS 信息。然后,这对每一个查找都会增加命中的延迟并且可能会降低整个集群查询的吞吐量。
为此,Consul提供了一些可选参数用来制定DNS查询的使用。
Stale Reads:读取陈旧数据
读取陈旧数据可以用来降低 DNS 查询时的延迟并提高吞吐量。默认情况下,所有的查询都由单一 leader 节点提供服务。这些读取可以保持强一致性,但受限于单一节点的 吞吐量。设置一个陈旧数据的读取可以允许任意的 Consul 服务提供查询,但非 lender 节点可能返回过时的数据。通过允许数据稍微过时,我们获得水平读取可伸缩性。 现在任何 Consul server 都可以为请求提供服务,因此我们通过集群中的 server 数量增加吞吐量。
用来控制陈旧数据读取的配置是 dns_config.allow_stale,这里需要设置为启用状态,并且 dns_config.max_stale 可以配置数据陈旧的最长时间。
从 Consul 的 0.7 版本开始,allow_stale 默认设置为开启状态,并且 max_stale 的默认配置时间为 5 秒,这意味着我们从任意的 Consul server 中读取到的数据都与 leader 中获取到的数据存在 5 秒的偏差。在 Consul 0.7.1 中,max_stale 的默认值已从 5 秒增加到接近不确定的阈值(10年),以允许在没有 leader 的长时间中断的情 况下继续提供 DNS 查询。 在 consul.dns.stale_queries 中还添加了一个新的遥测计数器,以跟踪 agnet 何时服务于陈旧时间超过 5 秒的 DNS 查询。
Negative Response Caching:拒绝响应缓存
一些 DNS 客户端缓存会拒绝响应,由于一个存在的服务没有处于健康的状态,Consul 会返回了一个 “not found” 格式的响应。这里意味着在执行过程中出现缓存拒绝响应,可能意味着服务出现了“未能正常运行”的时候,通过 DNS 进行服务发现时他们实际获取数据的数据还没有及时更正。
一个简单的例子,操作系统默认会缓存拒绝的响应 15 分钟。DNS 转发器也可能会缓存拒绝的响应造成同样的影响。为了避免这个问题,为你的客户端操作系统和任何介于 客户端与 Consul 之间的 DNS 转发器进行默认的拒绝响应缓存的检查并设置适当的缓存时间。在很多情况下“适当的”简单做法就是关闭拒绝响应缓存,当服务再次变成可用 时应用最好的恢复时间。
TTL Values
TTL 的值可以用来设置 Consul 用来缓存 DNS 结果的时间。 更高的 TTL 值减少了 Consul server 上的查找次数和客户端的速度查找,但代价是日益陈旧的结果。 默认情 况下,所有 TTL 为零,防止任何缓存。
要启用缓存节点查找(例如 “foo.node.consul”),我们可以设置 dns_config.node_ttl 值。 例如,这可以设置为 “10s”,并且所有节点查找将使用 10 秒 TTL 提供结 果。
可以以更精细的方式指定服务 TTL。 您可以设置每个服务的 TTL,使用通配符 TTL 作为默认值。 这是使用 dns_config.service_ttl 映射指定的。 “*” 服务是通配符服务。 例如,为服务提供通配符 TTL 和特定 TTL 的 dns_config 可能如下所示:
{
"dns_config": {
"service_ttl": {
"*": "5s",
"web": "30s"
}
}
}
这将所有查找设置为 “web.service.consul” 以使用 30 秒的 TTL,而查找 “db.service.consul” 或 “api.service.consul” 将使用通配符中的 5 秒 TTL。
Prepared Queries 提供了对 TTL 的额外级别的控制。 它们允许与查询一起定义 TTL,并且可以通过更新查询定义来即时更改 TTL。 如果没有为 Prepared Queries 配置TTL,则它将回退到如上所述的 Consul 代理中定义的服务特定配置,并且如果没有为 Consul 代理中的服务配置 TTL,则最终为 0。
DNS Forwarding
默认情况下,DNS 通过 53 端口提供服务。在多数操作系统中,这都需要很高的系统权限。通过另一个 DNS 服务器或者端口跳转,可以通过一个没有高级权限端口上运行 的 Consul 进行适当的 DNS 查询,而不需要运行在 administrative 或者 root 账号下的 Consul。
默认情况下,Consul 不提供不包含 .consul.DOMAIN 的 DNS 记录的解析,除非在配置文件中已经配置了 recursors。作为一个例子说明这个配置是怎么改变 Consul 的行 为的,假设一个 Consul 的 DNS 可以对一个没有指向 .consul 的顶级域名的的权威名称(CNAME)进行应答。通常这个 DNS 只会应答包含权威名称(CNAME)的记录。 作为比较,当 recursors 被设置并且 upstream 解析器运行正常的话,Consul 会尝试解析所有的权威名称(CNAME)和包含别名的记录(说明: IPV4 主机地址 (A),IPV6 主机地址(AAAA),解析 IP 的指针(PTR))用于它的DNS应答中。
更多文章详见: