什么是Consul?
Consul是一个用来实现分布式系统的服务发现与配置的开源工具。他主要由多个组成部分:
- 服务发现:客户端通过Consul提供服务,类似于API,MySQL,或者其他客户端可以使用Consul发现服务的提供者。使用类似DNS或者HTTP,应用程序和可以很轻松的发现他们依赖的服务。
- 检查健康:Consul客户端可以提供与给定服务相关的健康检查(Web服务器返回200 ok)或者本地节点(“内存利用率低于90%”)。这些信息可以监控集群的运行情况,并且使访问远离不健康的主机组件。
- 键值对存储:应用程序可以使用Cousul的层级键值对。
- 多数据中心:Consul有开箱及用的多数据中心。
Consul内幕
术语
- 代理(agent):代理是Consul集群上每个成员的守护进程,它是由consul agent开始运行。代理能够以客户端或服务器模式运行。由于所有节点都必须运行代理,所以将节点引用为客户端或服务器更为简单,但还有其他实例的代理。所有代理可以运行DNS或HTTP接口,并负责运行检查和保持服务同步。
- 客户端:客户端可以将所有RPC请求转发到服务器的代理。客户端是相对无状态的。客户端执行的唯一后台活动是LANgossip池。它消耗最小的资源开销和少量的网络带宽。
- 服务器端:服务器端是具有扩展的功能的代理,它主要参与维护集群状态,响应RPC查询,与其他数据中心交换WAN gossip ,以及向上级或远程数据中心转发查询。
- 数据中心:虽然数据中心的定义似乎很明显,但仍有一些细微的细节必须考虑。我们将一个数据中心定义为一个私有、低延迟和高带宽的网络环境。这不包括通过公共互联网的通信,但是为了我们的目的,单个EC2区域内的多个可用区域将被视为单个数据中心的一部分
- Gossip:consul是建立在serf之上的,它提供了一个完整的gossip协议,用在很多地方。Serf提供了成员,故障检测和事件广播。Gossip的节点到节点之间的通信使用了UDP协议。
- LAN Gossip:指在同一局域网或数据中心的节点上的LAN Gossip池。
- WAN Gossip****:指包含服务器的WAN Gossip池,这些服务器在不同的数据中心,通过网络进行通信。
架构图
![img](file:////Users/luohao/Library/Group%20Containers/UBF8T346G9.Office/msoclip1/01/clip_image002.png)
图中有两个数据中心,分别为Datacenter1和Datacenter2。Consul一层支持多个数据中心,每个数据中心内,有客户端和服务器端,服务区端一般为3~5个,这样可以在稳定和性能上达到平衡,因为更多的机器会使数据同步很慢。不过客户端是没有限制的,可以有成千上万个。
数据中心到所有节点都使用的时候Gossip协议。这就意味着有一个Gossip池,其中包含给定数据中心所有的节点。客户端不需要去配置服务器地址信息,发现服务会自动完成;检测故障节点的工作不是放在服务器端,而是分布式的;数据中心被用作消息层,以便在选择leader这种重要的事情发生的时候做通知。
每个数据中心都是都是单个Raft对等设备的一部分。这意味着他们一起工作,选择一个单一的领导者——一个具有额外职责的选定的服务器。leader负责处理所有查询和事物。事物也必须作为同步协议的一部分复制到所有对等体。由于这个要求,当非领导服务器端接收到RPC请求时,就会将请求其转发给集群leader。
服务器端节点作为WANGossip池的一部分运行,WAN池和LAN池不同的是,针对网络高延迟做了优化,而且只包含其他Consul服务器的节点。这个池的目的是允许数据中心以最少的消耗方式发现对方。在线启动新的数据中心与加入现有的WAN Gossip一样简单。因为这些服务器都在这个池中运行,它还支持跨数据中心请求。当服务器收到对不同数据中心的请求时,它会将其转发到正确数据中心中的随机服务器。那个服务器可能会转发给本地的leader。
这样会使数据中心的耦合非常低,由于故障检测,连接缓存和复用,跨数据中心请求相对快速可靠。
Gossip协议(流言传播协议)
Consul使用Gossip协议来管理成员和集群广播消息,这些都是通过使用Serf库的。Serf所使用的Gossip协议基于SWIM:可伸缩的弱一致的感染模式的过程组成员协议”,并做了一些细微的修改。
Consul中的Gossip
Consul使用了两个不同的Gossip池,称为LAN池和WAN池。每个数据中心都有一个LAN池,其中包含数据中心的所有成员,包括服务器端和客户端。LAN的成员客户端可以自动发现服务器,减少所需配置的数量。分布式故障检测可以让故障检测的工具被整个集群共享,Gossip池可以快速可靠的将事件广播,比如选择leader。
WAN池是全局唯一的,所有的服务器都应该在WAN池中,而不关系数据中心在哪里。WAN池提供的成员信息允许服务器执行跨数据中心请求。集成的故障检测功能使Consul能够优雅地处理整个数据中心或者远程数据中心的一个服务器失连。
Lifeguard Enhancements
在分组软实时处理可能的情况下,SWIN假设本地节点是健康的。但在本地节点遇到CPU或者网络节点资源匮乏的时候,可能不会认为节点不健康。结果是安全检测状态可能会偶尔瘫痪,导致虚假报警。Lifeguard解决了这个问题。
Consensus 协议
Consul通过Consensus协议来提供一致性(由CAP定义)。Consensus协议是基于Raft——查找可理解的一致性算法。
Raft协议概述
Raft是一种基于Paxos的一致性算法。与Paxos相比,Raft被设计成更少的状态和更简单、更易于理解的算法。
Raft节点有三种状态:follower,candidate,leader.所有的节点初始被置于follower,在这个状态下的节点都可以收到来自leader的Log并反馈。如果在一段时间没有收到任何信息,那么他就会变成candidate状态。在candidate状态下,一个节点向其他节点发送请求,这个节点就成为了leader。Leader必须接收新Log并复制其到其他follower那里。PS:只有leader才能进行读取Log。
一旦一个集群有一个leader,他就可以接受新的Log条目。一个客户端可以请求leader附加新的Log条目。这个leader随后将Log条目写入持久存储,并复制到follower。一旦Log条目被认为已经提交,它就会被用于有限状态机。有限状态机是相对于特定应用的,对于Consul而言,我们使用MenDB来维护集群状态。
显然,我们不需要无限制的复制日志。Raft提供了一种机制,通过这种机制,让状态被记录时这个Log就会被压缩。
网络坐标
Consul使用网络断层成像系统计算集群中的节点的网络坐标。这些坐标可以计算在任何两个节点之间估计网络往返时间。这有很多有用的应用,例如找到最靠近请求节点的服务节点,或者找到在下一个失效的最接近的数据中心中的服务器。
Consul的网络坐标
在Consul里,网络坐标有几种形式:
consul rtt命令可以查询任意两个节点的网络往返之间。
显示端点和端点运行状况端点可以使用“?near =”参数根据给定节点的网络往返时间对查询的结果进行排序。
查询可以根据网络往返时间将请求从故障的数据中心服务器中转移。
坐标终点显示用于其他应用程序的原始网络坐标。
Session
Consul提供了Session机制用于构建分布式锁,Session作为节点之间的绑定,运行状况检查和键值对数据。
Session设计
Consul的session代表了具体语义一个Session中包含了节点名称,列表的健康性,行为,TTL和lock-delay。新建的Session中提供了一个可以用来识别它的ID。这个ID可与存储的键值对一起使用以获取锁定:相互排斥的咨询机制。
下图是组件之间的关系图:
Consul定制的标准在下列情况下,被定义为无效:
- 节点被注销
- 所有的健康检查都被注销
- 所有健康检查都在危险状态
- Session被明确销毁了
- TTL过期
Session无效的时候,将会被销毁,关联锁是创建的指定行为,Consul支持发布和删除。Consul支持释放和删除行为,如果没有特别指定,默认的行为为释放。
如果正在执行释放操作,与Session相关的所有的锁都会被释放掉,并且键的索引无法递增。在删除行为执行的时候,则锁和键都会被删除。这可以用于Consul自动删除条目。
这种设计常用于流言传播的故障检测器的健康监测。在默认情况下,使用基于留言传播的故障检测器作为故障检测器用来进行相关的健康检查。该故障检测器允许Consul检测持有锁的节点在发生故障时自动释放锁。这种机制让consul发生故障或者其他失败的情况下,可以继续运行下去。但是,由于,没有完美的故障检测器,有的时候,检测到的故障并不存在,也会导致锁的释放。这就意味着他并不是绝对安全的。
相反的,可以创建一个无关联的健康检测的session。这就提供了对安全性要求的虚假的不健康检测的消除提供了可能。即使现有的锁的持有者执行出现故障,你也可以自己确定是否释放Consul的锁。由于Consul的API可以强制销毁session,所以我们可以在发生故障的时候进行人为干预,防止split-brain。
第三个健康检测机制是session的TTL。当创建一个session的时候,一个TTL也被指定。如果这个TTL的间隔时间到而没有更新,则session过期,并且无法早触发。这种类型的故障检测器叫做心跳检测器。他想必基于流言传播的故障检测器的可扩展性低,因为他会对服务器造成更大的负担,但是在一些情况下很有用。TTL是session过期的时间,在到达TTL之前,consul不会让session过去,但是consul允许延迟过期。在session创建初期,session更新和leader故障转移的时候,TTL会更新。当一个TTL被使用的时候,客户端应当注意时间的偏差——时间不可能会像consul Server上那样在客户端上以相同的速率进展。我们最好设置保守的TTL值,TTL更新之前考虑时间的偏差。
最后的细微差别为session会提供锁定延迟。这个延迟会持续0-60秒。当有无效的session时,consul会防止ssession在锁定延时的时间内重新获取之前的保存的所有锁。这种延迟的目录是允许潜在的leader检测到无效后,停止并导致状态不一致的请求。虽然不是一个彻底的方式,但是可以减少很多问题。延迟默认为15秒,客户端可以将延迟设置为0来取消这个机制。
安全模型
Consul使用了流言传播协议和RPC来提供各种功能。这两个系统在设计上采用了不同的安全机制,但是,Consul的安全机制完成的共同目标为:提供机密性,完整性和认证。流言传播协议由serf提供支持,serf使用对称秘钥或者共享密码系统。RPC支持使用可选客户端认证的端到端的TLS。
这就意味着Consul有完善的安全机制可以使其在不可信的网络上运行。
威胁模型
以下是威胁模型:
- 非成员可以访问数据
- 由于恶意邮件导致集群被操控
- 恶意邮件造成的虚假数据
- 对接点拒接服务
命令行
Consul命令行
Consul使用命令行非常容易操作,我们可以通过命令consul进行命令行申请。然后接着使用agent或者member之类的子命令。只要运行不带参数的consul命令就可以查看命令列表。
$ consul
usage: consul [--version] [--help] <command> [<args>]
Available commands are:
agent Runs a Consul agent
configtest Validate config file
event Fire a new event
exec Executes a command on Consul nodes
force-leave Forces a member of the cluster to enter the "left" state
info Provides debugging information for operators
join Tell Consul agent to join cluster
keygen Generates a new encryption key
keyring Manages gossip layer encryption keys
kv Interact with the KV store
leave Gracefully leaves the Consul cluster and shuts down
lock Execute a command holding a lock
maint Controls node or service maintenance mode
members Lists the members of a Consul cluster
monitor Stream logs from a Consul agent
operator Provides cluster-level tools for Consul operators
reload Triggers the agent to reload configuration files
rtt Estimates network round trip time between nodes
version Prints the Consul version
watch Watch for changes in Consul
想要获得的顶的命令的帮助,可以使用-h获取帮助,如下:
$ consul join -h
Agent
Agent是Consul的核心,用来运行代理者,维护成员的信息,运行检测,处理查询信息等。
catalog
consul catalog
该命令用来接Consul目录进行交互。
列出数据中心
consul catalog datacenters
列出节点
consul catalog nodes
列出所有提供服务的节点
consul catalog nodes -service=redis
列出所有的服务器
consul catalog services
Event
consul event
event提供了一种将自定义用户事件触发到整个数据中心的机制,这些事件对Consul是不透明的,但它们可用于构建脚本基础架构,以进行自动部署,重新启动服务或执行任何其他编排操作。Event可以通过使用watch来处理。event的传播是通过流言传播协议的。
Exec
consul exec
exec命令提供了远程执行的机制。下表显示了执行此命令索要的ACL。
ACL Required | 范围 |
---|---|
agent:read | 本地agent |
session:write | 本地agent |
key:write | "_rexec"字首 |
event:write | "_rexec"字首 |
info
consul info
info命令提供了对运算符有用的各种调试信息。根据代理是客户端还是服务器,将返回不同的子系统信息。目前有几个顶级的键:
- agent:提供有关agent的信息
- consul:有关consul的信息——客户端或者服务器端
- raft:提供有关Raft公共信息
- serf_lan:提供有关LAN流言池的信息
- serf_wandf:提供有关WAN流言池的信息
join
consul join
join命令让Consul代理加入一个现有集群,新的Consul代理必须与集群的至少一个现有成员共同参与现有的集群。加入该成员后,流言层接管,跨集群传播更新成员的资格状态。如果没有加入现有的集群,则代理是自己的孤立集群的一部分,其他节点可以加入。
代理可以加入其它的代理。如果已经是集群的一部分的节点加入了另一个节点,则两个节点的集群将加入成为一个集群。
Keygen
consul keygen
keygen命令生成可用于Consul代理流量加密的加密秘钥。
Keyring
consul keyring
keyring命令用于检查和修改Consul的流言池中使用的加密密钥。
Lock
lock命令提供了简单分布式锁定的机制。在KV存储中的给定前缀创建锁(或信号量),只有当被保持时,才会调用子进程。如果锁丢失或通信中断,则子进程终止。锁定器的数量可以使用-n标志进行配置。默认情况下,允许单个持有人,并且使用锁来进行互斥。这使用leader选举算法。
member
menber命令输出Consul代理人知道的当前成员名单及其状态。节点的状态只能是“alive”,“left”或“failed”。
Monitor
monitor命令用于连接和跟踪正在运行的Consul代理的日志。Monitor将显示最近的日志,然后继续遵循日志,不会退出直到中断或直到远程代理退出。
reload
reload命令触发代理程序重新加载配置文件。
Snapshot
snapshot命令具有用于保存,恢复和检查Consul服务器的状态用于容灾恢复的子命令。这些是原子的时间点快照,其中包括键值条目,服务目录,准备好的查询,会话和ACL。 Consul 0.7.1及更高版本中提供此命令。
Agent
Consul的Agent是Consul的核心。Agent维护成员的信息,注册服务,运行检测,响应查询。Agent必须作为Consul集群的一部分的每个节点上运行。任何代理可以以两种模式之一运行:客户端或者服务器。服务器节点承担了协商一致性的功能。这些节点参与了Raft,并在故障下提供了强大的一致性和可用性。服务器节点负担越来越大意味着需要在专用的实例上运行——他们比客户端节点更为资源密集。客户端节点构成了大多数的集群,并且它们很轻量,因为它们大多数操作的是服务器节点接口,维护自己状态的时间很少。