一、概述
consul是google開源的一個使用go語言開發的服務發現、配置管理中心服務。內置了服務注冊與發現框 架、分布一致性協議實現、健康檢查、Key/Value存儲、多數據中心方案,不再需要依賴其他工具(比如ZooKeeper等)。服務部署簡單,只有一個可運行的二進制的包。每個節點都需要運行agent,他有兩種運行模式server和client。每個數據中心官方建議需要3或5個server節點以保證數據安全,同時保證server-leader的選舉能夠正確的進行。
@client
CLIENT表示consul的client模式,就是客戶端模式。是consul節點的一種模式,這種模式下,所有注冊到當前節點的服務會被轉發到SERVER,本身是不持久化這些信息。
@server
SERVER表示consul的server模式,表明這個consul是個server,這種模式下,功能和CLIENT都一樣,唯一不同的是,它會把所有的信息持久化的本地,這樣遇到故障,信息是可以被保留的。
@server-leader
中間那個SERVER下面有LEADER的字眼,表明這個SERVER是它們的老大,它和其它SERVER不一樣的一點是,它需要負責同步注冊的信息給其它的SERVER,同時也要負責各個節點的健康監測。
@raft
server節點之間的數據一致性保證,一致性協議使用的是raft,而zookeeper用的paxos,etcd采用的也是raft。
@服務發現協議
consul采用http和dns協議,etcd只支持http
@服務注冊
consul支持兩種方式實現服務注冊,一種是通過consul的服務注冊http API,由服務自己調用API實現注冊,另一種方式是通過json個是的配置文件實現注冊,將需要注冊的服務以json格式的配置文件給出。consul官方建議使用第二種方式。
@服務發現
consul支持兩種方式實現服務發現,一種是通過http API來查詢有哪些服務,另外一種是通過consul agent 自帶的DNS(8600端口),域名是以NAME.service.consul的形式給出,NAME即在定義的服務配置文件中,服務的名稱。DNS方式可以通過check的方式檢查服務。
@服務間的通信協議
Consul使用gossip協議管理成員關系、廣播消息到整個集群,他有兩個gossip pool(LAN pool和WAN pool),LAN pool是同一個數據中心內部通信的,WAN pool是多個數據中心通信的,LAN pool有多個,WAN pool只有一個。
二、consul集群搭建
1)安裝
首先去官網現在合適的consul包:https://www.consul.io/downloads.html
安裝直接下載zip包,解壓后只有一個可執行的文件consul,將consul添加到系統的環境變量里面。
#unzip consul_1.2.3_linux_amd64.zip
#cp -a consul /usr/bin
#consul
Usage: consul [--version] [--help] <command> [<args>] Available commands are: agent Runs a Consul agent catalog Interact with the catalog connect Interact with Consul Connect 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. intention Interact with Connect service intentions 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
輸入consul,出現上面的內容證明安裝成功。
2)啟動
consul必須啟動agent才能使用,有兩種啟動模式server和client,還有一個官方自帶的ui。server用與持久化服務信息,集群官方建議3或5個節點。client只用與於server交互。ui可以查看集群情況的。
server:
cn1:
#consul agent -bootstrap-expect 2 -server -data-dir /data/consul0 -node=cn1 -bind=192.168.1.202 -config-dir /etc/consul.d -enable-script-checks=true -datacenter=dc1
cn2:
#consul agent -server -data-dir /data/consul0 -node=cn2 -bind=192.168.1.201 -config-dir /etc/consul.d -enable-script-checks=true -datacenter=dc1 -join 192.168.1.202
cn3:
#consul agent -server -data-dir /data/consul0 -node=cn3 -bind=192.168.1.200 -config-dir /etc/consul.d -enable-script-checks=true -datacenter=dc1 -join 192.168.1.202
參數解釋:
-bootstrap-expect:集群期望的節點數,只有節點數量達到這個值才會選舉leader。
-server: 運行在server模式
-data-dir:指定數據目錄,其他的節點對於這個目錄必須有讀的權限
-node:指定節點的名稱
-bind:為該節點綁定一個地址
-config-dir:指定配置文件,定義服務的,默認所有一.json結尾的文件都會讀
-enable-script-checks=true:設置檢查服務為可用
-datacenter: 數據中心沒名稱,
-join:加入到已有的集群中
client:
#consul agent -data-dir /data/consul0 -node=cn4 -bind=192.168.1.199 -config-dir /etc/consul.d -enable-script-checks=true -datacenter=dc1 -join 192.168.1.202
client節點可以有多個,自己根據服務指定即可。
ui:
#consul agent -ui -data-dir /data/consul0 -node=cn4 -bind=192.168.1.198 -client 192.168.1.198 -config-dir /etc/consul.d -enable-script-checks=true -datacenter=dc1 -join 192.168.1.202
-ui:使用自帶的ui,
-ui-dir:指定ui的目錄,使用自己定義的ui
-client:指定web ui、的監聽地址,默認127.0.0.1只能本機訪問。
集群創建完成后:
使用一些常用的命令檢查集群的狀態:
#consul info
可以在raft:stat看到此節點的狀態是Fllower或者leader
#consul members
Node Address Status Type Build Protocol DC Segment
cn1 192.168.1.202:8301 alive server 1.0.2 2 dc1 <all>
cn2 192.168.1.201:8301 alive server 1.0.2 2 dc1 <all>
cn3 192.168.1.200:8301 alive client 1.0.2 2 dc1 <default>
新加入一個節點有幾種方式;
1、這種方式,重啟后不會自動加入集群
#consul join 192.168.1.202
2、#在啟動的時候使用-join指定一個集群
#consul agent -ui -data-dir /data/consul0 -node=cn4 -bind=192.168.1.198 -config-dir /etc/consul.d -enable-script-checks=true -datacenter=dc1 -join 192.168.1.202
3、使用-startjoin或-rejoin
#consul agent -ui -data-dir /data/consul0 -node=cn4 -bind=192.168.1.198 -config-dir /etc/consul.d -enable-script-checks=true -datacenter=dc1 -rejoin
訪問ui:
http://192.168.1.198:8500/ui
端口:
8300:consul agent服務relplaction、rpc(client-server)
8301:lan gossip
8302:wan gossip
8500:http api端口
8600:DNS服務端口
3)服務注冊
采用的是配置文件的方式,(官方推薦)首先創建一個目錄用於存放定義服務的配置文件
#mkdir /etc/consul.d/
啟動服務的時候要使用-config-dir 參數指定。
下面給出一個服務定義:
#cat web.json
{ "service":{ "name":"web", "tags":[ "rails" ], "port":80, "check":{ "name":"ping", "script":"curl -s localhost:80", "interval":"3s" } } }
如果這樣啟動consul后,會發現consul的日志里面一直報錯,因為我們沒有啟動80端口的服務,下面給出我寫的一個go程序:
#cat web.go
package main import ( "io"
"log"
"net/http"
"strconv"
"fmt" ) var iCnt int = 0; func helloHandler(w http.ResponseWriter, r*http.request) { iCnt++; str :="Hell eorld ! friend("+ strconv.Itoa(iCnt)+")" io.WriteString(w,str) fmt.Println(str) } func main(){ ht :=http.HanderFunc(helloHandler) if ht != nil { http.Handle("/hello",ht) } err := http.ListenAndServe(":80",nil) if err != nil{ log.Fatal("ListenAndserve:",err.Error()) } }
#需要一個goalong的環境:
#go build -o web web.go
#./web
此時就可以在沒有運行web服務的機器上面執行DNS查詢:
# dig @127.0.0.1 -p 8600 web.service.consul SRV
;; ANSWER SECTION:
web.service.consul. 0 IN SRV 1 1 80 cn2.node.dc1.consul.
web.service.consul. 0 IN SRV 1 1 80 cn3.node.dc1.consul.
;; ADDITIONAL SECTION:
cn2.node.dc1.consul. 0 IN A 192.168.1.201
cn2.node.dc1.consul. 0 IN TXT "consul-network-segment="
cn3.node.dc1.consul. 0 IN A 192.168.1.200
cn3.node.dc1.consul. 0 IN TXT "consul-network-segment="
;; Query time: 17 msec
;; SERVER: 127.0.0.1#8600(127.0.0.1)
;; WHEN: 四 1月 04 14:39:32 CST 2018
;; MSG SIZE rcvd: 229
可以看到服務已經注冊到集群里面了。
使用dns查詢,默認域名格式NAME.service.consul,NAME就是web.json里面定義的service的name。可以自己指定域和端口:-domain、-dns-port 53
為了方便使用consul集群的注冊使用,所以寫了一個三節點client的注冊腳本,方便統一注冊服務和管理。還利用到了nfs,將服務文件共享到集群。
#!/usr/bin/env python #encoding: utf8 #decription: registered a service to consul
from subprocess import call import sys hosts = {"b1":"10.10.1.01:8500","b2":"10.10.7.1:8500","b3":"10.10.8.21:8500"} def consul_relaod(): if (len(sys.argv) != 2) or sys.argv[1] == '-h': print(("Usage: {0} [option] :{1} ,if you wang update all of them,you must use 'all'").format(sys.argv[0],hosts.keys())) sys.exit() elif(sys.argv[1] == 'all'): for i in hosts.keys(): call(("consul reload -http-addr {}").format(hosts[i]),shell=True) else: call(("consul reload -http-addr {}").format(hosts[sys.argv[1]]),shell=True) if __name__ == '__main__': consul_relaod()
hosts是client節點列表。可以只注冊其中的一個節點,輸入hosts中對應的key,也可以輸入all,注冊到所有節點;nfs共享的是/etc/consul.d目錄。
4)健康檢查
check使用來做服務的健康檢查的,可以擁有多個,也可以不使用支持多種方式檢查。check必須是script或者TTL類型,如果是TTL類型則ttl變量必須被提供。script是consul主動去檢查服務的健康狀況,ttl是服務主動向consul報告自己的狀況。新版本的consul不在使用script來表示,使用args,如果是https服務的健康檢查,可以使用args這種腳本的方式實現,因為consul默認不支持https的健康檢查。
script check:
"check": {
"args": ["/data/scripts/kubeadm-ha-0.sh",""],
"interval": "10s"
}
http check:
{
"check": {
"id": "api",
"name": "HTTP API 500",
"http": "http://loclhost:500/health",
"interval": "10s",
"timeout": "1s"
}
}
tcp check:
{
"check": {
"id": "ssh",
"name": "ssh TCP 26622",
"tcp": "localhost:26622",
"interval": "10s",
"timeout": "1s"
}
}
ttl check:
{
"check": {
"id": "web-app",
"name": "Web APP status",
"notes": "Web APP does a curl internally every 10 seconds",
"ttl": "30s"
}
}
三、更新consul版本為最新版本1.2.3.
版本更新特性:
https://github.com/hashicorp/consul/blob/v1.2.3/CHANGELOG.md
FEATURES:
agent: New Cloud Auto-join provider: Kubernetes (K8S) [GH-4635]
http: Added support for "Authorization: Bearer" head in addition to the X-Consul-Token header. [GH-4483]
dns: Added a way to specify SRV weights for each service instance to allow weighted DNS load-balancing. [GH-4198]
dns: Include EDNS-ECS options in EDNS responses where appropriate: see RFC 7871 [GH-4647]
IMPROVEMENTS:
ui: Switch to fullscreen layout for lists and detail, left aligned forms [GH-4435]
connect: TLS certificate readiness now performs x509 certificate verification to determine whether the cert is usable. [GH-4540]
ui: The syntax highlighting/code editor is now on by default [GH-4651]
ui: Fallback to showing Node.Address if Service.Address is not set [GH-4579]
ui較之前有很大改變: