Consul Service Discovery实践

1 介绍

Consul 是什么? 官方给出的答案是:

Consul is a service mesh solution providing a full featured control plane with service discovery, configuration, and segmentation functionality.

即提供服务发现,配置中心以及安全加密通信服务的Service Mesh解决方案。包含关键特性:

服务发现: Consul client注册服务,通过DNS或HTTP接口的形式访问Consul,获取服务列表;
健康检查: agent通过自定义的脚本检查service的健康,十分灵活,可以配合后端做负载均衡;
KV存储: 多级的kv存储;
加密认证通信: service之间的通信经过TLS加密并认证,intentions机制可以实时控制service之间通信权限;
多数据中心: 支持多数据中心

Consul系统结构

上图是Consul的系统架构,每个数据中心构建一个consul server集群,通过raft协议选举出leader,并保持数据一致性。Server之间通过gossip协议进行通信和数据同步。为了保证可靠性和性能,server数量为3到5台。Client主要负责本地服务的健康检查,向server注册服务,转发查询,数量可以任意拓展。

Consul 1.2版本之后 增加了connect特性,将agent拓展为sidecar,实现了一套Service Mesh的解决方案,本文未涉及到这一部分,只涉及Service Discovery部分。

2 Service Discovery 实践

2.1 Server Cluster 部署

Consul Agent以client或者server模式运行,每个数据中心配置一个server集群,包含至少一个server agent。我们选择部署三台机器 10.0.0.1,10.0.0.2,10.0.0.3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"datacenter" : "test_dc",
"node_name" : "node1",
"bind_addr": "10.0.0.1",
"retry_join" : ["10.0.0.1","10.0.0.2","10.0.0.3"],
"data_dir" : "data/",
"server" : true,
"bootstrap_expect" : 3,
"log_level": "INFO",
"ui": true,
"ports":{
"http":8081
}
}

配置文件中node_name为统一的前缀,方便后续acl策略控制,retry_join设置为集群的server地址。在三台机器上分别启动server agent.

1
./consul agent -config-dir=config/ -client=0.0.0.0

启动之后可以看到service中有三个consul实例。

UI

2.2 服务注册、健康检查、发现

(1)服务注册

Consul的服务注册通过client模式的agent进行。在service所在机器上启动client agent,加入到server集群中,该agent的存活状态是service的默认健康状态。

配置consul_client.json,启动client agent。

1
2
3
4
5
6
7
8
9
{
"datacenter" : "test_dc",
"node_name" : "node4",
"retry_join" : ["10.0.0.1","10.0.0.2","10.0.0.3"],
"bind_addr" : "10.0.0.4",
"data_dir" : "data/",
"enable_script_checks": true,
"log_level": "INFO"
}

1
./consul agent -config-dir=config/

service通过配置文件的形式定义,这里定义一个名为collector的服务,设置id,name,address,port

service.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"service": {
"id": "collector",
"name": "collector",
"tags": ["public"],
"address": "10.0.0.4",
"meta": {
"meta": "test meta"
},
"port": 2203,
"weights": {
"passing": 1,
"warning": 1
}
}
}

执行reload操作,此时UI可以看到service已经注册上来。
collector 默认状态

(2)健康检查

service中通过脚本做健康检查,可以添加任意的健康条件,示例中设置了三种状态检查,心跳、机器内存、服务负载。

service.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
{
"service": {
"id": "collector",
"name": "collector",
"tags": ["public"],
"address": "10.0.0.4",
"meta": {
"meta": "test meta"
},
"port": 2203,
"checks": [
{
"args": ["scripts/check_status.sh", "10000", "95", "1000"],
"interval": "5s"
},
{
"args": ["scripts/check_node.sh", "1"],
"interval": "5s"
},
{
"args": ["scripts/check_heartbeat.sh"],
"interval": "5s"
}
],
"weights": {
"passing": 1,
"warning": 1
}
}
}

check_heartbeat.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/sh
CODE=0
echo "check hearbeat"
ret=`curl -sSL http://localhost:12125/heartbeat`
echo $ret
if [ "$ret" = "ok" ]
then
CODE=0
else
CODE=-1
fi
echo "exit code" $CODE
exit $CODE

在上面配置了service之后,由于service未启动,健康检查不通过,service处于不可用状态。
collector健康状况

启动service后,三项健康检查通过后,service处于可用状态。

collector健康状况

(3)服务发现

服务发现可通过HTTP API或者DNS的形式获取。

1
2
3
GET /v1/health/node/:node
GET /v1/health/checks/:service
GET /v1/health/service/:service

HTTP API

DNS

2.3 KV存储

1
2
3
GET /v1/kv/:key
PUT /v1/kv/:key
DELETE /v1/kv/:key

2.4 ACL

Consul提供丰富的权限控制,用以控制数据访问,以及API读写权限。ACL的核心概念有policy和token,policy配置具体数据的读写权限,token则是应用于policy上,使用指定的token来执行对应的policy。

(1)bootstrap token

bootstrap token为管理员token,拥有最高权限,不要轻易将该token应用给某个policy。

开启ACL首先需要更改server配置文件,设置默认为deny

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"datacenter" : "test_dc",
"node_name" : "node1",
"bind_addr": "10.0.0.1",
"data_dir" : "data/",
"server" : true,
"bootstrap_expect" : 1,
"log_level": "INFO",
"ui": true,
"acl" : {
"enabled" : true,
"default_policy" : "deny",
"enable_token_persistence" : true
},
"ports":{
"http":8081
}
}

启动其中一台server,在初始启动之后,生成bootstrap token。

1
./consul acl bootstrap -http-addr="http://10.0.0.1:8081"

将得到的bootstrap token写到server配置文件acl_master_token字段中,重新启动server。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
"datacenter" : "test_dc",
"node_name" : "node1",
"bind_addr": "10.0.0.1",
"retry_join" : ["10.0.0.1","10.0.0.2","10.0.0.3"],
"acl_master_token" : "xxxxxxx-xxxxxx-xxxx-xxxx-xxxxxxxxx",
"data_dir" : "data/",
"server" : true,
"bootstrap_expect" : 3,
"log_level": "INFO",
"ui": true,
"acl" : {
"enabled" : true,
"default_policy" : "deny",
"enable_token_persistence" : true
},
"ports":{
"http":8081
}
}

UI中输入该bootstrap token,获得管理员权限
UI

(2) agent token

在开启了deny的策略后,agent之间通信也需要token。首先增加agent之间的访问策略,配置写权限,然后为该策略生成对应的token。
配置agent策略
应用token到agent策略
将token写到server配置文件acl_agent_token字段中,重新启动三个server agent。该token也需要配置在各个client agent中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
"datacenter" : "test_dc",
"node_name" : "node1",
"bind_addr": "10.0.0.1",
"retry_join" : ["10.0.0.1","10.0.0.2","10.0.0.3"],
"acl_agent_token" : "xxxxxxx-xxxxxx-xxxx-xxxx-xxxxxxxxx",
"acl_master_token" : "xxxxxxx-xxxxxx-xxxx-xxxx-xxxxxxxxx",
"data_dir" : "data/",
"server" : true,
"bootstrap_expect" : 3,
"log_level": "INFO",
"ui": true,
"acl" : {
"enabled" : true,
"default_policy" : "deny",
"enable_token_persistence" : true
},
"ports":{
"http":8081
}
}

(3)service token

service token用于client agent注册服务。如需要注册collector,则为collector分配写权限和token

1
2
3
service "collector" {
policy = "write"
}

在collector的描述文件中加入service token

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"service": {
"id": "collector",
"name": "collector",
"tags": ["public"],
"address": "10.0.0.4",
"token":"xxxxxxx-xxxxxx-xxxx-xxxx-xxxxxxxxx",
"meta": {
"meta": "test meta"
},
"port": 2203,
"enable_tag_override": false,
"weights": {
"passing": 1,
"warning": 1
}
}
}

(4)anonymous token

配置ACL后,命令行和http请求访问均需要带上对应的token才能访问对应的数据,但某些场景下我们可能不方便保管token,这时可以使用anonymous token开放某些权限。

匿名token是系统的内置不设防的令牌。比如,我们将kv的读权限开放,便可以使用匿名token。首先配置kv策略(注意还需要开放node读权限),然后将匿名token应用在该策略上。

1
2
3
4
5
6
7
node_prefix "" {
policy = "read"
}

key_prefix "" {
policy = "read"
}

参考

  1. Introduction to Consul - https://www.consul.io/intro/index.html
  2. HashiCorp Consul 1.2: Service Mesh - https://www.hashicorp.com/blog/consul-1-2-service-mesh/
  3. Secure Consul with ACLs - https://learn.hashicorp.com/consul/security-networking/production-acls