Consul1.7 多数据中心 新Hashicorp学习指南_第1张图片

服务多,问题多

  1. 随着互联网分布式系统的普及和微服务的盛行,如何提高服务与服务之间的伸缩性和可扩展性?
  2. 如何在服务端做变更时候,尽可能的减小对依赖服务的影响?
  3. 如何在开发或者客户端不知道的时候悄悄的变更服务信息?
  4. 在Nginx实现的负载均衡背后,如何减少修改配置和重载Nginx服务?
  5. 如果使用Prometheus监控容器或者服务?你真的需要写一大堆的配置?如果1000个服务你要怎么监控?当一些服务被"优化"掉之后,你是否需要一个一个的从监控服务的配置文件中将其摘除?
  6. ...

在微服务化的趋势下,为了最大限度增加扩容缩容的灵活性,名字服务和服务发现等方式就越来越受到青睐了。目前,主流的服务发现组件有:consul、etcd、zookeeper,其中的区别这里就不展开说明了,可以在官网查看这些服务之间的区别。

consul是什么

Consul 是 HashiCorp 公司推出的开源工具,用于实现分布式系统的服务发现与注册中心。与其他分布式服务注册与发现的方案,Consul 的方案更“一站式”,内置了服务注册与发现框 架、分布一致性协议实现、健康检查、Key/Value 存储、访问控制、多数据中心方案,不再需要依赖其他工具(比如 ZooKeeper 等)。使用起来也较 为简单。Consul使用Go语言编写,因此具有天然可移植性(支持Linux、windows和Mac OS X);安装包仅包含一个可执行文件,方便部署,与 Docker 等轻量级容器可无缝配合。

consul优势

  1. 使用 Raft 算法来保证一致性, 比复杂的 Paxos 算法更直接. 相比较而言, zookeeper 采用的是 Paxos, 而 etcd 使用的则是 Raft。
  2. 支持多数据中心,内外网的服务采用不同的端口进行监听。 多数据中心集群可以避免单数据中心的单点故障,而其部署则需要考虑网络延迟, 分片等情况等。 zookeeper 和 etcd 均不提供多数据中心功能的支持。
  3. 支持健康检查。 etcd 不提供此功能。
  4. 支持 http 和 dns 协议接口。 zookeeper 的集成较为复杂, etcd 只支持 http 协议。
  5. 官方提供 web 管理界面, etcd 无此功能。

consul服务架构和核心概念

Consul1.7 多数据中心 新Hashicorp学习指南_第2张图片

图中的SERVER是consul服务端高可用集群,CLIENT是consul客户端。consul客户端不保存数据,客户端将接收到的请求转发给响应的Server端。Server之间通过局域网或广域网通信实现数据一致性。每个Server或Client都是一个consul agent,或者说server和client只是agent所扮演的不同角色。
Consul利用两个不同的gossip pool。我们分别把他们称为局域网池(LAN Gossip Pool)或广域网池(WAN Gossip Pool)。每个Consul数据中心(Datacenter)都有一个包含所有成员(Server和Client)的LAN gossip pool。

LAN Pool有如下目的:

  1. 成员关系允许Client自动发现Server节点,减少所需的配置量
  2. 分布式故障检测允许的故障检测的工作在某几个Server几点执行,而不是集中整个集群所有节点上
  3. gossip允许可靠和快速的事件广播,比如Leader选举

WAN Pool是全局唯一的,无论属于哪一个数据中心,所有Server应该加入到WAN Pool。由WAN Pool提供会员信息让Server节点可以执行跨数据中心的请求。也就是说这个Pool不同于LAN Pool,它的目的是为了允许数据中心能够以low-touch的方式发现彼此。当数据中心的server收到来自不同数据中心的请求时,它可转发请求到数据中心的leader

在每个数据中心,client和server是混合的。一般建议有3-5台server。这是基于有故障情况下的可用性和性能之间的权衡结果,因为越多的机器加入达成共识越慢。然而,并不限制client的数量,它们可以很容易的扩展到数千或者数万台。

consul集群搭建

环境 服务器IP 节点名称 角色 DC
ubuntu16.04 192.168.99.128 Node1 Server BJ
ubuntu16.04 192.168.99.129 Node2 Server BJ
ubuntu16.04 192.168.99.130 node3 Server BJ
ubuntu16.04 192.168.99.131 Node4 Server SH

当前我们使用最新的版本用于测试调研:

wget https://releases.hashicorp.com/consul/1.7.2/consul_1.7.2_linux_amd64.zip
apt-get install unzip && unzip consul_1.7.2_linux_amd64.zip && mv consul /usr/local/bin/
for ip in 129 130 131
do
  scp /usr/local/bin/consul [email protected].$i:/usr/local/bin/
done

在准备好consul的二进制包之后,我们先在每个机器上运行consul服务实例:

#node1
consul agent -server -bootstrap-expect=3 -data-dir=/tmp/consul -node=192.168.99.128 -bind=192.168.99.128 -client=0.0.0.0 -datacenter=BJ -ui
#node2
consul agent -server -bootstrap-expect=3 -data-dir=/tmp/consul -node=192.168.99.129 -bind=192.168.99.129 -client=0.0.0.0 -datacenter=BJ -ui
#node3
consul agent -server -bootstrap-expect=3 -data-dir=/tmp/consul -node=192.168.99.130 -bind=192.168.99.130 -client=0.0.0.0 -datacenter=BJ -ui

一般喜欢通过--help查看选项的命令,这里就当做是凑字数吧!

  1. server: 以server身份启动。默认是client
  2. bootstrap-expect:集群要求的最少server数量,当低于这个数量,集群即失效。
  3. data-dir:data存放的目录,更多信息请参阅consul数据同步机制
  4. node:节点id,集群中的每个node必须有一个唯一的名称。默认情况下,Consul使用机器的hostname
  5. bind:监听的ip地址。默认绑定0.0.0.0,可以不指定。表示Consul监听的地址,而且它必须能够被集群中的其他节点访问。Consul默认会监听第一个private IP,但最好还是提供一个。生产设备上的服务器通常有好几个网卡,所以指定一个不会出错
  6. client: 客户端的ip地址,0.0.0.0是指谁都可以访问(不加这个,下面的ui :8500无法访问)
  7. ui: 可以访问UI界面
  8. -config-dir指定配置文件夹,Consul会加载其中的所有文件
  9. -datacenter 指定数据中心名称,默认是dc1
    当我们启动consul服务实例完成之后,会发现有报错的日志,这是因为此时三台机器还没有join,不能算是一个集群,三台机器上的consul均不能正常工作,因为leader未选出
    2020-04-13T08:55:43.821-0400 [INFO]  agent.server.raft: entering follower state: follower="Node at 192.168.99.128:8300 [Follower]" leader=
    2020-04-13T08:55:43.823-0400 [INFO]  agent.server: Adding LAN server: server="192.168.99.128 (Addr: tcp/192.168.99.128:8300) (DC: bj)"
    2020-04-13T08:55:43.823-0400 [INFO]  agent.server: Handled event for server in area: event=member-join server=192.168.99.128.bj area=wan
    2020-04-13T08:55:43.824-0400 [INFO]  agent: Started DNS server: address=0.0.0.0:8600 network=tcp
    2020-04-13T08:55:43.825-0400 [INFO]  agent: Started HTTP server: address=[::]:8500 network=tcp
    2020-04-13T08:55:43.825-0400 [INFO]  agent: started state syncer
==> Consul agent running!
    2020-04-13T08:55:50.370-0400 [WARN]  agent.server.raft: no known peers, aborting election
    2020-04-13T08:55:50.833-0400 [ERROR] agent.anti_entropy: failed to sync remote state: error="No cluster leader"
    2020-04-13T08:56:07.711-0400 [ERROR] agent: Coordinate update error: error="No cluster leader"
    2020-04-13T08:56:18.200-0400 [ERROR] agent.anti_entropy: failed to sync remote state: error="No cluster leader"
    2020-04-13T08:56:37.477-0400 [ERROR] agent: Coordinate update error: error="No cluster leader"
    2020-04-13T08:56:50.035-0400 [ERROR] agent.anti_entropy: failed to sync remote state: error="No cluster leader"
    2020-04-13T08:57:13.322-0400 [ERROR] agent: Coordinate update error: error="No cluster leader"
    2020-04-13T08:57:27.154-0400 [ERROR] agent.anti_entropy: failed to sync remote state: error="No cluster leader"
    2020-04-13T08:57:38.397-0400 [ERROR] agent: Coordinate update error: error="No cluster leader"
    2020-04-13T08:57:58.613-0400 [ERROR] agent.anti_entropy: failed to sync remote state: error="No cluster leader"

当一个consul agent启动后,它不知道任何其他节点,要学习到集群中的其他节点,agent必须加入一个已经存在的集群(cluster)。要加入这样的集群,它只需要知道这个集群中的一个节点即可。它加入后,将会和这个member gossip(交谈)并迅速发现集群中的其他节点。一个consul agent可以加入任何类型的其他agent,而不只是那些运行于server mode的agent。所以我们把192.168.99.129192.168.99.130加入到192.168.99.128

# node2
consul join 192.168.99.128
# node3
consul join 192.168.99.128
# 此时就已经加入到集群中了
[email protected]:~# consul members
Node            Address              Status  Type    Build  Protocol  DC  Segment
192.168.99.128  192.168.99.128:8301  alive   server  1.7.2  2         bj  
192.168.99.129  192.168.99.129:8301  alive   server  1.7.2  2         bj  
192.168.99.130  192.168.99.130:8301  alive   server  1.7.2  2         bj  
[email protected]:~# consul operator raft list-peers
Node            ID                                    Address              State     Voter  RaftProtocol
192.168.99.128  9095c165-7f5f-6892-e9bc-722c3a08ebf0  192.168.99.128:8300  leader    true   3
192.168.99.129  7234405d-cde5-e0ef-56b1-55e958de5b6c  192.168.99.129:8300  follower  true   3
192.168.99.130  8bbc7729-e41c-e548-c9a8-9bf9c01fdb54  192.168.99.130:8300  follower  true   3

consul支持多数据中心节点,在上文就提过,consul是通过WAN pool发现多数据中心节点的,因此我们加一个SH的consul节点:

#node4
consul agent -server -bootstrap-expect 3 -data-dir /tmp/consul -node=192.168.99.131 -bind=192.168.99.131 -datacenter SH -ui
root@node4-99-131:~# consul join -wan 192.168.99.128
Successfully joined cluster by contacting 1 nodes.
root@node4-99-131:~# consul members -wan
Node               Address              Status  Type    Build  Protocol  DC  Segment
192.168.99.128.bj  192.168.99.128:8302  alive   server  1.7.2  2         bj  
192.168.99.129.bj  192.168.99.129:8302  alive   server  1.7.2  2         bj  
192.168.99.130.bj  192.168.99.130:8302  alive   server  1.7.2  2         bj  
192.168.99.131.sh  192.168.99.131:8302  alive   server  1.7.2  2         sh  

这样就配置好了多数据中心节点集群。我们就可以在consul的web界面上看到集群信息了。

Consul1.7 多数据中心 新Hashicorp学习指南_第3张图片
Consul1.7 多数据中心 新Hashicorp学习指南_第4张图片