# Consul ![](../images/Consul/consul-architecture.png) 上图是官网提供的一个事例系统图,图中的Server是consul服务端高可用集群,Client是consul客户端。consul客户端不保存数据,客户端将接收到的请求转发给响应的Server端。Server之间通过局域网或广域网通信实现数据一致性。每个Server或Client都是一个consul agent。 Consul集群间使用了GOSSIP协议通信和raft一致性算法。上面这张图涉及到了很多术语: - Agent——agent是一直运行在Consul集群中每个成员上的守护进程。通过运行consul agent来启动。agent可以运行在client或者server模式。指定节点作为client或者server是非常简单的,除非有其他agent实例。所有的agent都能运行DNS或者HTTP接口,并负责运行时检查和保持服务同步。 - Client——一个Client是一个转发所有RPC到server的代理。这个client是相对无状态的。client唯一执行的后台活动是加入LAN gossip池。这有一个最低的资源开销并且仅消耗少量的网络带宽。 - Server——一个server是一个有一组扩展功能的代理,这些功能包括参与Raft选举,维护集群状态,响应RPC查询,与其他数据中心交互WAN gossip和转发查询给leader或者远程数据中心。 - DataCenter——虽然数据中心的定义是显而易见的,但是有一些细微的细节必须考虑。例如,在EC2中,多个可用区域被认为组成一个数据中心。我们定义数据中心为一个私有的,低延迟和高带宽的一个网络环境。这不包括访问公共网络,但是对于我们而言,同一个EC2中的多个可用区域可以被认为是一个数据中心的一部分。 - Consensus——一致性,使用Consensus来表明就leader选举和事务的顺序达成一致。为了以容错方式达成一致,一般有超过半数一致则可以认为整体一致。Consul使用Raft实现一致性,进行leader选举,在consul中的使用bootstrap时,可以进行自选,其他server加入进来后bootstrap就可以取消。 - Gossip——Consul建立在Serf的基础之上,它提供了一个用于多播目的的完整的gossip协议。Serf提供成员关系,故障检测和事件广播。Serf是去中心化的服务发现和编制的解决方案,节点失败侦测与发现,具有容错、轻量、高可用的特点。 - LAN Gossip——它包含所有位于同一个局域网或者数据中心的所有节点。 - WAN Gossip——它只包含Server。这些server主要分布在不同的数据中心并且通常通过因特网或者广域网通信。 - RPC——远程过程调用。这是一个允许client请求server的请求/响应机制。 在每个数据中心,client和server是混合的。一般建议有3-5台server。这是基于有故障情况下的可用性和性能之间的权衡结果,因为越多的机器加入达成共识越慢。然而,并不限制client的数量,它们可以很容易的扩展到数千或者数万台。 同一个数据中心的所有节点都必须加入gossip协议。这意味着gossip协议包含一个给定数据中心的所有节点。这服务于几个目的:第一,不需要在client上配置server地址。发现都是自动完成的。第二,检测节点故障的工作不是放在server上,而是分布式的。这使的故障检测相比心跳机制有更高的可扩展性。第三:它用来作为一个消息层来通知事件,比如leader选举发生时。 每个数据中心的server都是Raft节点集合的一部分。这意味着它们一起工作并选出一个leader,一个有额外工作的server。leader负责处理所有的查询和事务。作为一致性协议的一部分,事务也必须被复制到所有其他的节点。因为这一要求,当一个非leader得server收到一个RPC请求时,它将请求转发给集群leader。 server节点也作为WAN gossip Pool的一部分。这个Pool不同于LAN Pool,因为它是为了优化互联网更高的延迟,并且它只包含其他Consul server节点。这个Pool的目的是为了允许数据中心能够以low-touch的方式发现彼此。这使得一个新的数据中心可以很容易的加入现存的WAN gossip。因为server都运行在这个pool中,它也支持跨数据中心请求。当一个server收到来自另一个数据中心的请求时,它随即转发给正确数据中心一个server。该server再转发给本地leader。 这使得数据中心之间只有一个很低的耦合,但是由于故障检测,连接缓存和复用,跨数据中心的请求都是相对快速和可靠的。 ### Consul集群安装环境 此处启动的是单实例多端口,如果你是多实例,请自行更改相关配置 | ServerName | IP Addr & Port | Consul Roles | | :------------ | :----------------- | :------------ | | server1 | 192.168.1.153:8500 | Server1 | | server2 | 192.168.1.154:8500 | Server2 | | server3 | 192.168.1.155:8500 | Server3 | | node-exporter | 192.168.1.151:9100 | Node-Exporter | #### 二进制安装Consul 1.7.7 配置为systemd启动 ```bash # 下载consul CONSUL_VERSION='1.7.7' wget https://releases.hashicorp.com/consul/${CONSUL_VERSION}/consul_${CONSUL_VERSION}_linux_amd64.zip # 解压安装 unzip consul_${CONSUL_VERSION}_linux_amd64.zip chown root:root consul mv consul /usr/local/bin/ consul --version # 启用自动补全 consul -autocomplete-install complete -C /usr/local/bin/consul consul # 创建用户和目录 useradd -M -s /sbin/nologin consul mkdir -p /data/consul/server/{data,config} chown -R consul.consul /data/consul/ # 配置Systemd # consul-server1 cat > /lib/systemd/system/consul-server1.service << EOF [Unit] Description="consul server1" Requires=network-online.target After=network-online.target [Service] User=consul Group=consul ExecStart=/usr/local/bin/consul agent -config-dir=/data/consul/server/config ExecReload=/usr/local/bin/consul reload KillMode=process Restart=on-failure LimitNOFILE=65536 [Install] WantedBy=multi-user.target EOF # consul-server2 cat > /lib/systemd/system/consul-server2.service << EOF [Unit] Description="consul server2" Requires=network-online.target After=network-online.target [Service] User=consul Group=consul ExecStart=/usr/local/bin/consul agent -config-dir=/data/consul/server/config ExecReload=/usr/local/bin/consul reload KillMode=process Restart=on-failure LimitNOFILE=65536 [Install] WantedBy=multi-user.target EOF # consul-server3 cat > /lib/systemd/system/consul-server3.service << EOF [Unit] Description="consul server3" Requires=network-online.target After=network-online.target [Service] User=consul Group=consul ExecStart=/usr/local/bin/consul agent -config-dir=/data/consul/server/config ExecReload=/usr/local/bin/consul reload KillMode=process Restart=on-failure LimitNOFILE=65536 [Install] WantedBy=multi-user.target EOF ``` #### 创建Server{1-3}配置文件 ```bash # 生成密钥 CONSUL_KEY=`consul keygen` # node_id 一定不可以重复,server name可以随便定义 # 创建server1配置文件 cat > /data/consul/server/config/config.json << EOF { "datacenter": "prometheus", "bind_addr":"192.168.1.153", "log_level": "INFO", "node_id":"09d82408-bc4f-49e0-1111-61ef1d4842f7", "node_name": "server1", "data_dir":"/data/consul/server/data", "server": true, "bootstrap_expect": 3, "encrypt": "${CONSUL_KEY}", "ui":true, "client_addr":"0.0.0.0", "retry_join":["192.168.1.153:8301","192.168.1.154:8301","192.168.1.155:8301"], "ports": { "http": 8500, "dns": 8600, "serf_lan":8301, "serf_wan":8302, "server":8300, "grpc":8400 }, "acl": { "enabled": true, "default_policy": "deny", "down_policy": "extend-cache", "tokens":{ "master":"${CONSUL_HTTP_TOKEN}", "agent":"${CONSUL_HTTP_TOKEN}" } } } EOF # 创建server2配置文件 cat > /data/consul/server/config/config.json << EOF { "datacenter": "prometheus", "bind_addr":"192.168.1.154", "log_level": "INFO", "node_id":"613ccd6e-68d1-3bbd-2222-3cbc450f019d", "node_name": "server2", "data_dir":"/data/consul/server/data", "server": true, "bootstrap_expect": 3, "encrypt": "${CONSUL_KEY}", "ui":true, "client_addr":"0.0.0.0", "retry_join":["192.168.1.153:8301","192.168.1.154:8301","192.168.1.155:8301"], "ports": { "http": 8500, "dns": 8600, "serf_lan":8301, "serf_wan":8302, "server":8300, "grpc":8400 }, "acl": { "enabled": true, "default_policy": "deny", "down_policy": "extend-cache", "tokens":{ "master":"${CONSUL_HTTP_TOKEN}", "agent":"${CONSUL_HTTP_TOKEN}" } } } EOF # 创建server3配置文件 cat > /data/consul/server/config/config.json << EOF { "datacenter": "prometheus", "bind_addr":"192.168.1.155", "log_level": "INFO", "node_id":"d8a09ffd-7ccb-84bd-3333-8d8b7a01951e", "node_name": "server3", "data_dir":"/data/consul/server/data", "server": true, "bootstrap_expect": 3, "encrypt": "${CONSUL_KEY}", "ui":true, "client_addr":"0.0.0.0", "retry_join":["192.168.1.153:8301","192.168.1.154:8301","192.168.1.155:8301"], "ports": { "http": 8500, "dns": 8600, "serf_lan":8301, "serf_wan":8302, "server":8300, "grpc":8400 }, "acl": { "enabled": true, "default_policy": "deny", "down_policy": "extend-cache", "tokens":{ "master":"${CONSUL_HTTP_TOKEN}", "agent":"${CONSUL_HTTP_TOKEN}" } } } EOF ``` #### 启动服务 ```bash systemctl enable consul-server1 && systemctl start consul-server1 systemctl enable consul-server2 && systemctl start consul-server2 systemctl enable consul-server3 && systemctl start consul-server3 systemctl status consul-server1 ``` 生成http_acl_token,写入config.jso中的tokens数组中的master与agent。`注意,consul acl bootstrap只能执行一次.` ```bash consul acl bootstrap AccessorID: ae4f5026-73e7-ff56-548c-3ae0fc76022f SecretID: 08ad8862-f702-eb26-0276-d8255b11267e Description: Bootstrap Token (Global Management) Local: false Create Time: 2020-09-02 23:25:47.533701389 +0800 CST Policies: 00000000-0000-0000-0000-000000000001 - global-management AccessorID: ae4f5026-73e7-ff56-548c-3ae0fc76022f SecretID: 08ad8862-f702-eb26-0276-d8255b11267e export CONSUL_HTTP_TOKEN='your_token' ``` #### 查看集群 返回空节点是正常的,因为开启了ACL,所以访问的时候需要加入token,如果`CONSUL_HTTP_TOKEN`变量已经加入profile,不需要在指定token。 ```bash # 环境变量 cat >> /etc/profile << EOF export CONSUL_HTTP_TOKEN='08ad8862-f702-eb26-0276-d8255b11267e' EOF # consul members --token='08ad8862-f702-eb26-0276-d8255b11267e' Node Address Status Type Build Protocol DC Segment server1 192.168.1.153:8301 alive server 1.7.7 2 prometheus server2 192.168.1.154:8301 alive server 1.7.7 2 prometheus server3 192.168.1.155:8301 alive server 1.7.7 2 prometheus # 验证集群UI 在页面http://127.0.0.1:8500/ui/prometheus/acls/tokens 输入配置中的 master token,再刷新界面可以在services和nodes中查看到信息 # 验证API,通过在header中增加x-consul-token则可返回节点列表 curl http://127.0.0.1:8500/v1/catalog/nodes -H 'x-consul-token: ${CONSUL_HTTP_TOKEN}' ``` #### 将Consul日志加入Syslog 此处为可选项,如果你需要单独将日志输出到ELK,那么此项配置非常有必要,因为默认的日志都打到syslog中了。 ```bash # 创建目录&赋权 mkdir -p /var/log/consul/ chown -R syslog.syslog /var/log/consul/ # 创建日志配置文件 cat >/etc/rsyslog.d/consul.conf </etc/logrotate.d/consul <> /data/prometheus/conf/prometheus.yml < # 设置基本的认证用户名和密码。 -consul-addr=
# 设置Consul实例的地址。 -max-stale= # 查询过期的最大频率,默认是1s。 -dedup # 启用重复数据删除,当许多consul template实例渲染一个模板的时候可以降低consul的负载。 -consul-ssl # 使用https连接Consul。 -consul-ssl-verify # 通过SSL连接的时候检查证书。 -consul-ssl-cert # SSL客户端证书发送给服务器。 -consul-ssl-key # 客户端认证时使用的SSL/TLS私钥。 -consul-ssl-ca-cert # 验证服务器的CA证书列表。 -consul-token= # 设置Consul API的token。 -syslog # 把标准输出和标准错误重定向到syslog,syslog的默认级别是local0。 -syslog-facility= # 设置syslog级别,默认是local0,必须和-syslog配合使用。 -template=