Consul 是一個分布式,高可用,支持多數據中心的服務發現和配置共享的服務軟件,由 HashiCorp 公司用 Go 語言開發, 基於 Mozilla Public License 2.0 的協議進行開源。 在Consul的文檔上,Consul 支持Service Discovery, Health Checking, Key/Value Store, Multi DataCenter。運用Consul,可以在系統中build復雜的應用和服務的發現等。
Consul 的優勢
- 使用 Raft 算法來保證一致性, 比復雜的 Paxos 算法更直接. 相比較而言, zookeeper 采用的是 Paxos, 而 etcd 使用的則是 Raft.
- 支持多數據中心,內外網的服務采用不同的端口進行監聽。 多數據中心集群可以避免單數據中心的單點故障,而其部署則需要考慮網絡延遲, 分片等情況等. zookeeper 和 etcd 均不提供多數據中心功能的支持.
- 支持健康檢查. etcd 不提供此功能.
- 支持 http 和 dns 協議接口. zookeeper 的集成較為復雜, etcd 只支持 http 協議.
- 官方提供web管理界面, etcd 無此功能.
consul 架構
從圖中可以看出,consul是支持多數據中心的,並且多數據中心是一個非常common的用戶場景。公司的項目中采用consul這是比較重要的一個考慮,之前的項目一直用的是zookeeper,實現多數據中心會有比較多的問題。
-
Agent - 運行在consul集群的每個node上的daemon,agent可以run在server或者是client上,每個agent都可以提供DNS或者是HTTP的接口,負責health check和service發現等。用consul agent命令可以啟動,具體可run "consul agent --help"查看參數。
- Client - client把所有的RPCs轉發到server端,是相對無狀態的。唯一在后台運行的時client端執行了LAN gossip pool,只消耗極少的資源和網絡帶寬。
- Server - server 負責維護cluster state, RPC quiries, 和其他數據中心交換WAN gossip,轉發queries給leader或者其他數據中心。
-
Datacenter -這里文檔里面指的時網絡環境是私有,低延遲,高帶寬的,排除和公網的通信。其實我認為和vmware的概念有些類似,vmware的一台server下面的虛擬機也可以定義為一個datacenter,不同的server可以構成不同的datacenter,這里面還包含邏輯功能的划分。對於我們測試人員來說,單個人的測試環境可以作為一個datacenter。
-
Serf:consul是基於Serf上實現的,Serf是一個服務發現,編配(應用集群管理等)工具,它去中心化,高可用並且能故障恢復(容忍), Serf使用Gossip協議,采用Go語言編寫。Serf提供成員關系,糾錯檢查,廣播的功能。gossip包含的任意node-to-node間的通信,主要是基於UDP。
-
LAN Gossip - 指 LAN gossip pool 包含哪些都在同一局域網或者是datacenter的node。which contains nodes that are all located on the same local area network or datacenter.
-
WAN Gossip - 指 WAN gossip pool 包含哪些都在同一局域網或者是datacenter的node。
-
RPC - Remote Procedure Call. 客戶端和服務器端的請求/應答機制。

在這篇文檔中,我會介紹Consul的一些基本用法,以及把Consul用在production的環境中。
Consul 測試環境
一開始要研究consul的時候,用vagrant搭建了4個虛擬機,有個問題沒有解決。我的vagrant的虛擬機是在mac上創建的,eth0就是mac的網絡,eth1才是我們創建的private network。但是consul默認就綁定eth0的,這樣4台機子沒辦法通過eth0來通信,consul有相關的參數可以來修改bind的IP和端口,這個會再以后的文章中介紹。所以我這里還是用了現有的4台centos的vmware的虛擬機做的測試。
Node Type
server1 server
server2 server
server2 server
agent1 agent
Consul 在CentOS上的安裝
安裝非常簡單,安裝完成后,就可以run Consul命令啦。
cd /usr/local/bin wget https://dl.bintray.com/mitchellh/consul/0.5.0_linux_amd64.zip unzip *.zip rm *.zip
consul命令行運行的方式非常簡單,可以看到以下的參數,也可以參考consul的用戶文檔。
$ consul usage: consul [--version] [--help] <command> [<args>] Available commands are: agent Runs a Consul agent 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 leave Gracefully leaves the Consul cluster and shuts down members Lists the members of a Consul cluster monitor Stream logs from a Consul agent reload Triggers the agent to reload configuration files version Prints the Consul version
開啟Bootstrap Server
一開始學習consul, 我們需要讓consul 運行起來。consul server推薦至少在3~5個之間,推薦的方法是一開始啟動其中一台server,並且配置到bootstrap的模式,該模式node可以指定自己作為leader,而不用進行選舉。然后再依次啟動其他server,配置為非bootstrap的模式。最后把第一個serverbootstrap模式停止,重新以非bootstrap模式啟動,這樣server之間就可以自動選舉leader。
在上面的表中,我們需要指定server 1 做為bootstrap server,可以run下面的命令,以下是啟動的過程。可以看到bootstrap模式下配置自己為leader。
[admin@localhost ~]$ consul agent -server -bootstrap -data-dir /tmp/consul ==> WARNING: Bootstrap mode enabled! Do not enable unless necessary ==> WARNING: It is highly recommended to set GOMAXPROCS higher than 1 ==> Starting Consul agent... ==> Starting Consul agent RPC... ==> Consul agent running! Node name: 'localhost.localdomain' Datacenter: 'dc1' Server: true (bootstrap: true) Client Addr: 127.0.0.1 (HTTP: 8500, HTTPS: -1, DNS: 8600, RPC: 8400) Cluster Addr: 10.74.15.87 (LAN: 8301, WAN: 8302) Gossip encrypt: false, RPC-TLS: false, TLS-Incoming: false Atlas: <disabled> ==> Log data will now stream in as it occurs: 2015/05/11 02:58:06 [INFO] raft: Node at 10.74.15.87:8300 [Follower] entering Follower state 2015/05/11 02:58:06 [INFO] serf: EventMemberJoin: localhost.localdomain 10.74.15.87 2015/05/11 02:58:06 [INFO] serf: EventMemberJoin: localhost.localdomain.dc1 10.74.15.87 2015/05/11 02:58:06 [INFO] consul: adding server localhost.localdomain (Addr: 10.74.15.87:8300) (DC: dc1) 2015/05/11 02:58:06 [INFO] consul: adding server localhost.localdomain.dc1 (Addr: 10.74.15.87:8300) (DC: dc1) 2015/05/11 02:58:06 [ERR] agent: failed to sync remote state: No cluster leader 2015/05/11 02:58:08 [WARN] raft: Heartbeat timeout reached, starting election 2015/05/11 02:58:08 [INFO] raft: Node at 10.74.15.87:8300 [Candidate] entering Candidate state 2015/05/11 02:58:08 [INFO] raft: Election won. Tally: 1 2015/05/11 02:58:08 [INFO] raft: Node at 10.74.15.87:8300 [Leader] entering Leader state 2015/05/11 02:58:08 [INFO] consul: cluster leadership acquired 2015/05/11 02:58:08 [INFO] consul: New leader elected: localhost.localdomain 2015/05/11 02:58:08 [INFO] raft: Disabling EnableSingleNode (bootstrap) 2015/05/11 02:58:08 [INFO] consul: member 'localhost.localdomain' joined, marking health alive 2015/05/11 02:58:08 [INFO] agent: Synced service 'consul'
啟動其他servers,在 server2 and server3, 我們用以下命令啟動consul,不需要帶bootstrap 選項。
[admin@localhost ~]$ consul agent -server -data-dir /tmp/consul ==> WARNING: It is highly recommended to set GOMAXPROCS higher than 1 ==> Starting Consul agent... ==> Starting Consul agent RPC... ==> Consul agent running! Node name: 'localhost.localdomain' Datacenter: 'dc1' Server: true (bootstrap: false) Client Addr: 127.0.0.1 (HTTP: 8500, HTTPS: -1, DNS: 8600, RPC: 8400) Cluster Addr: 10.74.15.87 (LAN: 8301, WAN: 8302) Gossip encrypt: false, RPC-TLS: false, TLS-Incoming: false Atlas: <disabled> ==> Log data will now stream in as it occurs: 2015/05/11 03:01:54 [INFO] serf: EventMemberJoin: localhost.localdomain 10.74.15.87 2015/05/11 03:01:54 [INFO] serf: EventMemberJoin: localhost.localdomain.dc1 10.74.15.87 2015/05/11 03:01:54 [INFO] raft: Node at 10.74.15.87:8300 [Follower] entering Follower state 2015/05/11 03:01:54 [INFO] consul: adding server localhost.localdomain (Addr: 10.74.15.87:8300) (DC: dc1) 2015/05/11 03:01:54 [INFO] consul: adding server localhost.localdomain.dc1 (Addr: 10.74.15.87:8300) (DC: dc1) 2015/05/11 03:01:54 [ERR] agent: failed to sync remote state: No cluster leader 2015/05/11 03:01:55 [WARN] raft: EnableSingleNode disabled, and no known peers. Aborting election.
可以從log中看到,無法找到cluster leader和無法配置自己為leader,server2還沒有和server1通信。這時,需要run下面的命令加入到server1的集群。
consul join 192.0.2.2 192.0.2.3 consul members //查看現有的cluster下面的node
當3台機子都加入到集群,我們需要配置這3台機子為同等的server,並且讓它們自己選擇leader,這時可以停止第一台的consul,然后再用以下命令啟動:
consul agent -server -data-dir /tmp/consul consul join 192.0.2.2 192.0.2.3
現在,3太機子會互相復制信息,或者可以處理某台機子掛掉后的情況。當有其他server需要加入時,重復上面的操作就可以。
Reference
http://blog.coding.net/blog/intro-consul?type=hot
http://liubin.org/2014/02/22/first-serf-experience/
