天天看點

Consul叢集部署

在「Consul入門」一文中我們對Consul的基本知識點和單節點部署做了一些介紹,今天我們來講講Consul叢集的部署方法。

Consul架構說明

Consul叢集部署

上圖是官網提供的一個事例系統圖,圖中的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叢集

環境準備

  • 系統環境
主機名 IP位址 Consul角色
dev-master-01 192.168.2.210 Server
dev-node-01 192.168.2.211
dev-node-02 192.168.2.212
dev-node-03 192.168.2.213 Client
  • 建立相應的資料和配置目錄
$ mkdir -p /opt/consul/web
$ mkdir -p /opt/consul/data
$ mkdir -p /opt/consul/conf
$ mkdir -p /opt/consul/run/      
  • 下載下傳Web-UI(可選)

Consul提供了用于狀态監控Web伺服器,将Web UI工具下載下傳到

-ui-dir

指定的目錄,即可以建立可視化的管理頁面。Consul 0.8.2版本已經自帶了,不用在單獨下載下傳。

$ wget https://releases.hashicorp.com/consul/0.8.1/consul_0.8.1_web_ui.zip
$ unzip consul_0.8.1_web_ui.zip -d /opt/consul/web/      
以上幾項操作在所有節點上都要進行。

安裝Consul

Consul安裝非常簡單,如果你還沒有安裝好Consul,可先參考「Consul入門」一文。

Conusl指令行

consul是隻有一個指令行應用,就是consul指令。consul指令可以包含agent、members等參數進行使用,下面我們介紹下常用的幾個指令:

通過

consul -h

可看到consul所支援的所有子指令。

$ consul -h
usage: consul [--version] [--help] <command> [<args>]

Available commands are:
   agent          Runs a Consul agent
   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 key-value 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
   snapshot       Saves, restores and inspects snapshots of Consul server state
   validate       Validate config files/directories
   version        Prints the Consul version
   watch          Watch for changes in Consul      

簡單說下幾個常用指令的用途:

  • agent指令是consul的核心,它運作agent來維護成員的重要資訊、運作檢查、服務宣布、查詢處理等等。
  • event指令提供了一種機制,用來fire自定義的使用者事件,這些事件對consul來說是不透明的,但它們可以用來建構自動部署、重新開機服務或者其他行動的腳本。
  • exec指令提供了一種遠端執行機制,比如你要在所有的機器上執行uptime指令,遠端執行的工作通過job來指定,存儲在KV中。agent使用event系統可以快速的知道有新的job産生,消息是通過gossip協定來傳遞的,是以消息傳遞是最佳的,但是并不保證指令的執行。事件通過gossip來驅動,遠端執行依賴KV存儲系統(就像消息代理一樣)。
  • force-leave可以強制consul叢集中的成員進入left狀态(空閑狀态),記住,即使一個成員處于活躍狀态,它仍舊可以再次加入叢集中,這個方法的真實目的是強制移除failed的節點。如果failed的節點還是網絡的一部分,則consul會周期性的重新連結failed的節點,如果經過一段時間後(預設是72小時),consul則會宣布停止嘗試連結failed的節點。force-leave指令可以快速的把failed節點轉換到left狀态。
  • info指令提供了各種操作時可以用到的debug資訊,對于client和server,info有傳回不同的子系統資訊,目前有以下幾個KV資訊:agent(提供agent資訊),consul(提供consul庫的資訊),raft(提供raft庫的資訊),serf_lan(提供LAN gossip pool),serf_wan(提供WAN gossip pool)。
  • join指令告訴consul agent加入一個已經存在的叢集中,一個新的consul agent必須加入一個已經有至少一個成員的叢集中,這樣它才能加入已經存在的叢集中,如果你不加入一個已經存在的叢集,則agent是它自身叢集的一部分,其他agent則可以加入進來。agent可以加入其他agent多次。如果你想加入多個叢集,則可以寫多個位址,consul會加入所有的位址。
  • keygen指令生成加密的密鑰,可以用在consul agent通訊加密。
  • leave指令觸發一個優雅的離開動作并關閉agent,節點離開後不會嘗試重新加入叢集中。運作在server狀态的節點,節點會被優雅的删除,這是很嚴重的,在某些情況下一個不優雅的離開會影響到叢集的可用性。
  • members指令輸出consul agent目前所知道的所有的成員以及它們的狀态,節點的狀态隻有alive、left、failed三種狀态。
  • monitor指令用來連結運作的agent,并顯示日志。monitor會顯示最近的日志,并持續的顯示日志流,不會自動退出,除非你手動或者遠端agent自己退出。
  • reload指令可以重新加載agent的配置檔案。SIGHUP指令在重新加載配置檔案時使用,任何重新加載的錯誤都會寫在agent的log檔案中,并不會列印到螢幕。
  • version指令用作列印consul的版本
  • watch指令提供了一個機制,用來監視實際資料視圖的改變(節點清單、成員服務、KV),如果沒有指定程序,目前值會被dump出來。
Consul Agent配置說明

在部署Consul叢集時,主要用到的是agent指令。這裡重點講一下agent指令的參數,agent有各種各樣的配置項可以在指令行或者配置檔案進行定義,所有的配置項都是可選擇的。存在相同配置定義時,後面定義的配置會合并前面定義的配置,但大多數情況下合并的意思是後面定義的配置會覆寫前面定義的配置。

  • 指令行參數
  1. -advertise:通知展現位址用來改變我們給叢集中的其他節點展現的位址,一般情況下-bind位址就是展現位址
  2. -bootstrap:用來控制一個server是否在bootstrap模式,在一個datacenter中隻能有一個server處于bootstrap模式,當一個server處于bootstrap模式時,可以自己選舉為raft leader。
  3. -bootstrap-expect:在一個datacenter中期望提供的server節點數目,當該值提供的時候,consul一直等到達到指定sever數目的時候才會引導整個叢集,該标記不能和bootstrap公用。
  4. -bind:該位址用來在叢集内部的通訊,叢集内的所有節點到位址都必須是可達的,預設是0.0.0.0。
  5. -client:consul綁定在哪個client位址上,這個位址提供HTTP、DNS、RPC等服務,預設是127.0.0.1。
  6. -config-file:明确的指定要加載哪個配置檔案
  7. -config-dir:配置檔案目錄,裡面所有以.json結尾的檔案都會被加載
  8. -data-dir:提供一個目錄用來存放agent的狀态,所有的agent都需要該目錄,該目錄必須是穩定的,系統重新開機後都繼續存在。
  9. -dc:該标記控制agent的datacenter的名稱,預設是dc1。
  10. -encrypt:指定secret key,使consul在通訊時進行加密,key可以通過consul keygen生成,同一個叢集中的節點必須使用相同的key。
  11. -join:加入一個已經啟動的agent的ip位址,可以多次指定多個agent的位址。如果consul不能加入任何指定的位址中,則agent會啟動失敗。預設agent啟動時不會加入任何節點。
  12. -retry-join:和join類似,但是允許你在第一次失敗後進行嘗試。
  13. -retry-interval:兩次join之間的時間間隔,預設是30s。
  14. -retry-max:嘗試重複join的次數,預設是0,也就是無限次嘗試。
  15. -log-level:consul agent啟動後顯示的日志資訊級别。預設是info,可選:trace、debug、info、warn、err。
  16. -node:節點在叢集中的名稱,在一個叢集中必須是唯一的,預設是該節點的主機名。
  17. -protocol:consul使用的協定版本。
  18. -rejoin:使consul忽略先前的離開,在再次啟動後仍舊嘗試加入叢集中。
  19. -server:定義agent運作在server模式,每個叢集至少有一個server,建議每個叢集的server不要超過5個。
  20. -syslog:開啟系統日志功能,隻在linux/osx上生效。
  21. -ui-dir:提供存放web ui資源的路徑,該目錄必須是可讀的。
  22. -pid-file:提供一個路徑來存放pid檔案,可以使用該檔案進行SIGINT/SIGHUP(關閉/更新)agent。

更多參數說明可參考:https://www.consul.io/docs/agent/options.html

  • 配置檔案

除了指令行參數外,配置也可以寫入檔案中。配置檔案是json格式的,很容易編寫。配置檔案不僅被用來設定agent的啟動,也可以用來提供健康檢測和服務發現的定義。

配置檔案詳細參數說明:

  1. acl_datacenter:隻用于server,指定的datacenter的權威ACL資訊,所有的servers和datacenter必須同意ACL datacenter
  2. acl_default_policy:預設是allow。
  3. acl_token:agent會使用這個token和consul server進行請求。
  4. acl_ttl:控制TTL的cache,預設是30s。
  5. addresses:一個嵌套對象,可以設定以下key:dns、http、rpc。
  6. advertise_addr:等同于-advertise。
  7. bootstrap:等同于-bootstrap。
  8. bootstrap_expect:等同于-bootstrap-expect。
  9. bind_addr:等同于-bind。
  10. ca_file:提供CA檔案路徑,用來檢查用戶端或者服務端的連結。
  11. cert_file:必須和key_file一起。
  12. client_addr:等同于-client。
  13. datacenter:等同于-dc。
  14. data_dir:等同于-data-dir。
  15. disable_anonymous_signature:在進行更新檢查時禁止匿名簽名。
  16. disable_remote_exec:禁止支援遠端執行,設定為true,agent會忽視所有進入的遠端執行請求。
  17. disable_update_check:禁止自動檢查安全公告和新版本資訊。
  18. dns_config:是一個嵌套對象,可以設定以下參數:allow_stale、max_stale、node_ttl 、service_ttl、enable_truncate。
  19. domain:預設情況下consul在進行DNS查詢時查詢的是consul域,可以通過該參數進行修改。
  20. enable_debug:開啟debug模式。
  21. enable_syslog:等同于-syslog。
  22. encrypt:等同于-encrypt。
  23. key_file:提供私鑰的路徑。
  24. leave_on_terminate:預設是false,如果為true,當agent收到一個TERM信号的時候,它會發送leave資訊到叢集中的其他節點上。
  25. log_level:等同于-log-level。
  26. node_name:等同于-node。
  27. ports:這是一個嵌套對象,可以設定以下key:dns(dns位址:8600)、http(http api位址:8500)、rpc(rpc:8400)、serf_lan(lan port:8301)、serf_wan(wan port:8302)、server(server rpc:8300)。
  28. protocol:等同于-protocol。
  29. rejoin_after_leave:等同于-rejoin。
  30. retry_join:等同于-retry-join。
  31. retry_interval:等同于-retry-interval。
  32. server:等同于-server。
  33. server_name:會覆寫TLS CA的node_name,可以用來确認CA name和hostname相比對。
  34. skip_leave_on_interrupt:和leave_on_terminate比較類似,不過隻影響目前句柄。
  35. start_join:一個字元數組提供的節點位址會在啟動時被加入。
  36. syslog_facility:當enable_syslog被提供後,該參數控制哪個級别的資訊被發送,預設Local0。
  37. ui_dir:等同于-ui-dir。
  38. verify_incoming:預設false,如果為true,則所有進傳入連結接都需要使用TLS,需要用戶端使用ca_file提供ca檔案。隻用于consul server端,因為client從來沒有進入的連結。
  39. verify_outgoing:預設false,如果為true,則所有出去連結都需要使用TLS,需要服務端使用ca_file提供ca檔案,consul server和client都需要使用,因為兩者都有出去的連結。
  40. watches:watch一個詳細名單。

以啟動agent為例:

# 建立配置檔案
$ vim /opt/consul/conf/server.json

{
  "datacenter": "dc1",
  "data_dir": "/opt/consul/data",
  "log_level": "INFO",
  "node_name": "consul-server01",
  "server": true,
  "bootstrap_expect": 1,
  "bind_addr": "192.168.2.210",
  "client_addr": "192.168.2.210",
  "ui_dir": "/opt/consul/web",
  "retry_join": ["192.168.2.210","192.168.2.211","192.168.2.212"],
  "retry_interval": "30s",
  "enable_debug": false,
  "rejoin_after_leave": true,
  "start_join": ["192.168.2.210","192.168.2.211","192.168.2.212"],
  "enable_syslog": true,
  "syslog_facility": "local0"
}

# consul從配置目錄加載配置
$ consul agent -config-dir /opt/consul/conf/
# consul從配置檔案加載配置
$ consul agent -config-file=server.json      

Consul常用端口說明

  1. dns - The DNS server, -1 to disable. Default 8600.
  2. http - The HTTP API, -1 to disable. Default 8500.
  3. https - The HTTPS API, -1 to disable. Default -1 (disabled).
  4. rpc - The CLI RPC endpoint. Default 8400.
  5. serf_lan - The Serf LAN port. Default 8301.
  6. serf_wan - The Serf WAN port. Default 8302.
  7. server - Server RPC address. Default 8300.

部署叢集

部署Server端

這裡我們一共要部署三個Server端,具體如下:

  • 在dev-master-01上部署
$ consul agent -server -bootstrap -syslog \
    -ui-dir=/opt/consul/web \
    -data-dir=/opt/consul/data \
    -config-dir=/opt/consul/conf \
    -pid-file=/opt/consul/run/consul.pid \
    -client=192.168.2.210 \
    -bind=192.168.2.210 \
    -node=consul-server01 \
    -disable-host-node-id      

小提示:

  1. -bootstrap一般隻在叢集初始化時使用一次。
  2. 最新版本是内置了Web的,直接使用

    -ui

    參數啟用就行了。
  • 在dev-node-01上部署
$ consul agent -server -syslog \
    -ui \
    -data-dir=/opt/consul/data \
    -config-dir=/opt/consul/conf \
    -pid-file=/opt/consul/run/consul.pid \
    -client=192.168.2.211 \
    -bind=192.168.2.211 \
    -node=consul-server02 \
    -disable-host-node-id      
  • 在dev-node-02上部署
$ consul agent -server -syslog \
    -ui \
    -data-dir=/opt/consul/data \
    -config-dir=/opt/consul/conf \
    -pid-file=/opt/consul/run/consul.pid \
    -client=192.168.2.212 \
    -bind=192.168.2.212 \
    -node=consul-server03 \
    -disable-host-node-id      

到此我們已經啟動了三個Consul Server,這三個Consul Server現在還對彼此沒有任何感覺。它們都為單節點的叢集,每個叢集都僅包含一個成員。運作

consul members

來驗證下。

由于啟動Agent時綁定了IP位址,是以下面需要顯示指定IP位址。預設連接配接位址是

127.0.0.1:8500

# dev-master-01
$ consul members --http-addr 192.168.2.210:8500
Node             Address             Status  Type    Build  Protocol  DC
consul-server01  192.168.2.210:8301  alive   server  0.8.1  2         dc1

# dev-node-01
$ consul members --http-addr 192.168.2.211:8500
Node             Address             Status  Type    Build  Protocol  DC
consul-server02  192.168.2.211:8301  alive   server  0.8.1  2         dc1

# dev-node-02
$ consul members --http-addr 192.168.2.212:8500
Node             Address             Status  Type    Build  Protocol  DC
consul-server03  192.168.2.212:8301  alive   server  0.8.1  2         dc1      
  • 加入叢集

Consul發現機制

  • 當一個Consul代理啟動後,它并不知道其它節點的存在,它是一個孤立的單節點叢集。
  • 如果想感覺到其它節點的存在,它必須加入到一個現存的叢集。
  • 要加入到一個現存的叢集,它隻用加入叢集中任意一個現存的成員。
  • 當加入一個現存的成員後,會通過成員間的通訊很快發現叢集中的其它成員。
  • 一個Consul代理可以加入任意一個代理,而不僅僅是服務節點。

為了讓三個Server間能互相感覺,這裡就要讓其它二個Server加入同一個叢集中。

a) Server02加入Server01

$ consul join --http-addr 192.168.2.211:8500 192.168.2.210      

我的環境是三台連結克隆的虛拟機,會報如下錯:

* Failed to join 192.168.2.210: Member 'consul-server01' has conflicting node ID 'b76ff298-accd-05ff-8c64-5d79d866dfa9' with this agent's ID      

大緻的意思是uuid沖突了,預設情況下Consul将使用Consul資料目錄下node-id檔案中的id,可能是虛拟機原因我三台node-id居然是一樣的。

解決方法有兩種:

一是在啟動agent的時候加入

-disable-host-node-id

參數,禁止生成node-id。類似這樣:

$ consul agent -server -bootstrap -syslog \
    -ui \
    -data-dir=/opt/consul/data \
    -config-dir=/opt/consul/conf \
    -pid-file=/opt/consul/run/consul.pid \
    -client=192.168.2.210 \
    -bind=192.168.2.210 \
    -node=consul-server01 \
    -disable-host-node-id      

二是可以用

-node-id

生成一個新的node-id,類似這樣:

$ consul agent -server -bootstrap -syslog \
    -ui-dir=/opt/consul/web \
    -data-dir=/opt/consul/data \
    -config-dir=/opt/consul/conf \
    -pid-file=/opt/consul/run/consul.pid \
    -client=192.168.2.210 \
    -bind=192.168.2.210 \
    -node=consul-server01 \
    -node-id=$(uuidgen | awk '{print tolower($0)}')      

再次加入叢集:

$ consul join --http-addr 192.168.2.211:8500 192.168.2.210
Successfully joined cluster by contacting 1 nodes.      

b) Server03加入Server01

$ consul join --http-addr 192.168.2.212:8500 192.168.2.210
Successfully joined cluster by contacting 1 nodes.      

成功加入Server01節點後,從Server01上日志可以看出leader已選取出來:

...
    2017/05/10 13:54:37 [INFO] consul: cluster leadership acquired
    2017/05/10 13:54:37 [INFO] consul: New leader elected: consul-server01
    2017/05/10 13:54:37 [INFO] consul: member 'consul-server01' joined, marking health alive
...      

此時在

dev-master-01

節點上檢視成員狀态,彼此都能互識。

# dev-master-01
$ consul members --http-addr 192.168.2.210:8500
Node             Address             Status  Type    Build  Protocol  DC
consul-server01  192.168.2.210:8301  alive   server  0.8.1  2         dc1
consul-server02  192.168.2.211:8301  alive   server  0.8.1  2         dc1
consul-server03  192.168.2.212:8301  alive   server  0.8.1  2         dc1      

通過HTTP API方式查詢,在三個節點上任意一個節點執行:

# 查詢叢集leader
$ curl 192.168.2.210:8500/v1/status/leader
"192.168.2.210:8300"

# 查詢叢集成員
$ curl 192.168.2.210:8500/v1/status/peers
["192.168.2.210:8300","192.168.2.211:8300","192.168.2.212:8300"]      

通過DNS方式來查詢節點資訊

查詢結構為

NAME.node.consul

NAME.node.DATACENTER.consul

。以查詢

consul-server01

為例:

$ dig @192.168.2.210 -p 8600 consul-server01.node.consul

;; QUESTION SECTION:
;consul-server01.node.consul.    IN    A

;; ANSWER SECTION:
consul-server01.node.consul. 0    IN    A    192.168.2.210

;; Query time: 1 msec
;; SERVER: 192.168.2.210#8600(192.168.2.210)
;; WHEN: Wed May 10 16:54:08 CST 2017
;; MSG SIZE  rcvd: 61

$ dig  @192.168.2.210 -p 8600 consul-server01.node.dc1.consul

;; QUESTION SECTION:
;consul-server01.node.dc1.consul. IN    A

;; ANSWER SECTION:
consul-server01.node.dc1.consul. 0 IN    A    192.168.2.210

;; Query time: 0 msec
;; SERVER: 192.168.2.210#8600(192.168.2.210)
;; WHEN: Wed May 10 16:55:50 CST 2017
;; MSG SIZE  rcvd: 65      

注意:

  • 如果有多個成員,也隻用加入一個節點,其它節點會在這個節點加入叢集後通過成員間的通訊互相發現。
  • 確定所有節點TCP或UDP的8301是開放的,節點間的通訊得依賴這個端口,否則無法加入。
  • 確定所有節點TCP的8300是開放的,因為Client向Server的RPC得依賴這個端口,不打開無法同步。
部署Client端

該節點是Client角色,是以我們不指定它啟動為伺服器模式。

# 在dev-node-03上部署
$ consul agent -syslog \
    -data-dir=/opt/consul/data \
    -config-dir=/opt/consul/conf \
    -pid-file=/opt/consul/run/consul.pid \
    -client=192.168.2.213 \
    -bind=192.168.2.213 \
    -join=192.168.2.210 \
    -node=consul-client01 \
    -disable-host-node-id      

這裡啟動的時候就會自動加入一個已有叢集,因為啟動時加入了

-join

參數,該參數可以自動加入一個已知Consul叢集。啟動Server角色的Agent的也是可以自動加入的,上面手動加入是為了更好的說明整個過程。

# 查詢叢集成員
$ consul members --http-addr 192.168.2.210:8500
Node             Address             Status  Type    Build  Protocol  DC
consul-client01  192.168.2.213:8301  alive   client  0.8.1  2         dc1
consul-server01  192.168.2.210:8301  alive   server  0.8.1  2         dc1
consul-server02  192.168.2.211:8301  alive   server  0.8.1  2         dc1
consul-server03  192.168.2.212:8301  alive   server  0.8.1  2         dc1      
服務注冊

consul進行服務注冊提供了兩種方式(HTTP API以及配置檔案指定),在這裡我們使用配置檔案的方式:

在dev-master-01上的consul配置目錄下建立一個服務檔案:

$ vim /opt/consul/conf/web.json
{"service": {"name": "web", "tags": ["master"], "port": 8080,
"check": {"http": "http://127.0.0.1:8080", "interval": "10s"}}}      

這個服務檔案的大意是:注冊了一個名稱是web,運作在8080端口的服務。并且義了一個健康檢查。

consul reload

進行熱注冊

$ consul reload --http-addr=192.168.2.210:8500
Configuration reload triggered      

此時consul會不斷的進行報錯,因為這裡進行了健康檢查。

$ tail -f  /var/log/consul/consul.log
May 11 11:45:36 dev-master-01 consul[11226]: agent: http request failed 'http://127.0.0.1:8080': Get http://127.0.0.1:8080: dial tcp 127.0.0.1:8080: getsockopt: connection refused      

用Python啟動一個SimpleHTTPServer進行驗證。

$ python -m SimpleHTTPServer 8080
Serving HTTP on 0.0.0.0 port 8080 ...      

再次檢查consul日志,一切正常。

$ tail -f  /var/log/consul/consul.log
May 11 11:50:57 dev-master-01 consul[11226]: agent: Synced check 'service:web'      
注:這裡日志是啟用了Syslog的情況,是以日志位置在

/var/log/consul/consul.log

。在沒有啟用Syslog的情況下,預設會直接輸出到終端的。有關Syslog日志啟用方法本文後面會講。
服務發現

服務發現也可以通過HTTP API和DNS兩種方式進行,所有查詢都在Consul Client角色的機器上進行,以驗證Client的正常工作情況。這裡以DNS查詢方式為例:

$ dig @192.168.2.213 -p 8600 web.service.consul SRV

;; QUESTION SECTION:
;web.service.consul.        IN    SRV

;; ANSWER SECTION:
web.service.consul.    0    IN    SRV    1 1 8080 consul-server01.node.dc1.consul.

;; ADDITIONAL SECTION:
consul-server01.node.dc1.consul. 0 IN    A    192.168.2.210      

停掉剛才啟動的web服務,再次查詢就沒有的web服務了。

$ ps uax|grep python
root     12764  0.4  0.6  41120 13136 pts/0    S+   12:04   0:00 python -m SimpleHTTPServer 8080
$ kill 12764
$ dig @192.168.2.213 -p 8600 web.service.consul SRV
 ;; QUESTION SECTION:
 ;web.service.consul.        IN    SRV

 ;; AUTHORITY SECTION:
 consul.            0    IN    SOA    ns.consul. postmaster.consul. 1494475592 3600 600 86400 0      

最後在Consul Web界面看一下成果

Consul叢集部署
脫離叢集

可以使用

Ctrl-C

來平滑退出,也可以強行Kill退出。差別是主動告知其它節點自己的離開,和被其它節點标記為失效。這裡要注意,在叢集中平滑退出是很重要的。

一些技巧

給Consul建立Systemd服務

Consul預設是在前台運作的,為了友善管理我們建立一個Systemd服務。

這裡以建立一個Consul Server端為例:

  • 建立一個用于啟動Consul的專有使用者
$ useradd -M -s /sbin/nologin consul
$ chown -R consul.consul /opt/consul/      
  • 建立配置檔案

這個配置檔案裡面内容是啟動Consul Agent的參數。

$ vim /etc/default/consul
CONSUL_FLAGS="-server -bootstrap -syslog -ui -data-dir=/opt/consul/data -config-dir=/opt/consul/conf -pid-file=/opt/consul/run/consul.pid -client=192.168.2.210 -bind=192.168.2.210 -node=consul-server01 -disable-host-node-id"      
  • 建立Systemd配置檔案
$ vim /etc/systemd/system/consul.service

[Unit]
Description=Consul service discovery agent
Requires=network-online.target
After=network-online.target

[Service]
User=consul
Group=consul
EnvironmentFile=-/etc/default/consul
Environment=GOMAXPROCS=2
Restart=on-failure
ExecStartPre=[ -f "/opt/consul/run/consul.pid" ] && /usr/bin/rm -f /opt/consul/run/consul.pid
ExecStartPre=/usr/local/bin/consul configtest -config-dir=/opt/consul/conf
ExecStart=/usr/local/bin/consul agent $CONSUL_FLAGS
ExecReload=/bin/kill -HUP $MAINPID
KillSignal=SIGTERM
TimeoutStopSec=5

[Install]
WantedBy=multi-user.target      

這時Kill用的

SIGTERM

信号,因為

SIGTERM

信号在叢集環境下可以避免leader重選。SIGINT和SIGTERM的差別:

  1. SIGINT與字元ctrl+c關聯,SIGTERM沒有任何控制字元關聯。
  2. SIGINT隻能結束前台程序,SIGTERM則不是。
  3. SIGTERM可以被阻塞、處理和忽略。KILL指令的預設不帶參數發送的信号就是SIGTERM,SIGTERM可以讓程式優雅的退出。
  • 啟動Consul
$ systemctl start consul.service      
  • 驗證是否啟動成功
$ systemctl status  consul.service
● consul.service - Consul service discovery agent
   Loaded: loaded (/etc/systemd/system/consul.service; disabled; vendor preset: enabled)
   Active: active (running) since Thu 2017-05-11 10:50:14 CST; 4s ago
  Process: 8894 ExecStartPre=/usr/local/bin/consul configtest -config-dir=/opt/consul/conf (code=exited, status=0/SUCCESS)
 Main PID: 8902 (consul)
    Tasks: 9
   Memory: 4.7M
      CPU: 154ms
   CGroup: /system.slice/consul.service
           └─8902 /usr/local/bin/consul agent -server -bootstrap -syslog -ui -data-dir=/opt/consul/data -config-dir=/opt/consul/conf -pid-file=/opt/consul/run/consul.pid -client=192.168.2.210 -bind=192.168.2.210 -node=consul-server01 -disable-host-node-id

May 11 10:50:14 dev-master-01 consul[8902]:       Cluster Addr: 192.168.2.210 (LAN: 8301, WAN: 8302)
May 11 10:50:14 dev-master-01 consul[8902]:     Gossip encrypt: false, RPC-TLS: false, TLS-Incoming: false
May 11 10:50:14 dev-master-01 consul[8902]:              Atlas: <disabled>
May 11 10:50:14 dev-master-01 consul[8902]: ==> Log data will now stream in as it occurs:
May 11 10:50:14 dev-master-01 consul[8902]:     2017/05/11 10:50:14 [INFO] raft: Initial configuration (index=1): [{Suffrage:Voter ID:192.168.2.210:8300 Address:192.168.2.210:8300}]
May 11 10:50:14 dev-master-01 consul[8902]:     2017/05/11 10:50:14 [INFO] raft: Node at 192.168.2.210:8300 [Follower] entering Follower state (Leader: "")
May 11 10:50:14 dev-master-01 consul[8902]:     2017/05/11 10:50:14 [INFO] serf: EventMemberJoin: consul-server01 192.168.2.210
May 11 10:50:14 dev-master-01 consul[8902]:     2017/05/11 10:50:14 [INFO] consul: Adding LAN server consul-server01 (Addr: tcp/192.168.2.210:8300) (DC: dc1)
May 11 10:50:14 dev-master-01 consul[8902]:     2017/05/11 10:50:14 [INFO] serf: EventMemberJoin: consul-server01.dc1 192.168.2.210
May 11 10:50:14 dev-master-01 consul[8902]:     2017/05/11 10:50:14 [INFO] consul: Handled member-join event for server "consul-server01.dc1" in area "wan"      

給Consul配置Syslog日志

Consul預設是把日志輸出到前台,為了友善管理我們用Syslog将日志管理起來。

  • 建立日志存放目錄并賦權
$ mkdir -p /var/log/consul/
$ chown -R syslog.syslog /var/log/consul/      
  • 啟用系統日志
# 建立日志配置檔案
$ cat >/etc/rsyslog.d/consul.conf <<EOF
local0.* /var/log/consul/consul.log
EOF

# 修改預設配置檔案中的以下内容
$ vim /etc/rsyslog.d/50-default.conf

# 變更前
*.*;auth,authpriv.none          -/var/log/syslog

# 變更後
*.*;auth,authpriv.none,local0.none          -/var/log/syslog

# 重新開機rsyslog讓配置生效。
$ systemctl restart rsyslog

# 建立日志輪循規則
$ cat >/etc/logrotate.d/consul <<EOF
/var/log/consul/*log {
missingok
compress
notifempty
daily
rotate 5
create 0600 root root
}
EOF      
  • 配置Consul

如果要在

consul agent

中啟用Syslog日志,一定要在啟動時加入

-syslog

參數。類似這樣:

$ consul agent -server -bootstrap -syslog -ui -data-dir=/opt/consul/data -config-dir=/opt/consul/conf -pid-file=/opt/consul/run/consul.pid -client=192.168.2.210 -bind=192.168.2.210 -node=consul-server01 -disable-host-node-id      
$ tail -f  /var/log/consul/consul.log
May 11 11:06:05 dev-master-01 consul[9891]: serf: Failed to re-join any previously known node
May 11 11:06:05 dev-master-01 consul[9891]: consul: Handled member-join event for server "consul-server01.dc1" in area "wan"
May 11 11:06:12 dev-master-01 consul[9891]: agent: failed to sync remote state: No cluster leader
May 11 11:06:13 dev-master-01 consul[9891]: raft: Heartbeat timeout from "" reached, starting election
May 11 11:06:13 dev-master-01 consul[9891]: raft: Node at 192.168.2.210:8300 [Candidate] entering Candidate state in term 4
May 11 11:06:13 dev-master-01 consul[9891]: raft: Election won. Tally: 1
May 11 11:06:13 dev-master-01 consul[9891]: raft: Node at 192.168.2.210:8300 [Leader] entering Leader state
May 11 11:06:13 dev-master-01 consul[9891]: consul: cluster leadership acquired
May 11 11:06:13 dev-master-01 consul[9891]: consul: New leader elected: consul-server01
May 11 11:06:14 dev-master-01 consul[9891]: agent: Synced node i