這一節內容有點長,咱們將介紹如何基於docker搭建一client一server的consul測試環境,以及如何搭建多server consul測試集羣.在基於docker搭建多server的consul集羣時出碰到了一些坑,這對咱們是頗有益的提醒,不少時候咱們不能僅僅知足於最小化的環境搭建及簡單使用,而是要朝着接近生產環境的方向努力.同時,咱們這裏基於docker搭建集羣其實和在宿主機上直接搭建並無太大區別,也就是咱們僅僅把docker看成相似虛擬機來使用,本系列咱們屢次強調新瓶裝老酒,咱們要真正思考新的技術方案到底能爲咱們的項目帶來什麼,如何充分利用新技術新方案來更好的服務於咱們的項目.後面咱們會基於k8s來搭建一個接近生產環境的集羣,實現節點節點自動組成集羣,某個節點掛掉後新增補的節點如何自動加入原有集羣.後來咱們還會探索如何使用k8s的服務發現功能,實現consul節點的自動擴容.相比傳統的方法手動啓動宕掉的節點或者使用腳原本實現自動化,咱們徹底基於kubernetes的能力來實現自動化.閒言少敘.咱們進入正題,開始講如何使用docker來搭建consul測試集羣.後面的具體章節咱們再詳細介紹這裏討論的內容.html
前面咱們介紹了在windows下部署dev環境的consul,咱們僅部署了一個節點,其實這個節點是一個client節點,不對數據作持久化存儲,僅保存在內存中.生產環境須要持久化存儲數據,所以須要server模式,本篇介紹如何使用consul docker鏡像部署一個server和一個clientnode
使用docker pull consul
命令來拉取consul的docker鏡像.linux
經過如下命令啓動server端git
docker run -d -p 1234:8500 -h node1 --name node1 consul agent -server -bootstrap-expect=1 -node=node1 -client 0.0.0.0 -ui
執行命令後,docker返回容器idgithub
d107a4eda2f84bee09c0ae9044a22aa99249d144a1751e270ef6641fead79884
注意這個數字是隨機的,讀者要看本身的docker實際返回的idweb
而後咱們執行docker ps查看以上容器是否在運行docker
λ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d107a4eda2f8 consul "docker-entrypoint.s…" 4 seconds ago Up 3 seconds 8300-8302/tcp, 8301-8302/udp, 8600/tcp, 8600/udp, 0.0.0.0:1234->8500/tcp node1
能夠看到它已經在運行了.shell
此節點是server端,client須要加入它組成集羣,client加入須要知道server的ip.咱們有兩種方式獲取server的ip,實際上就是server所在容器的ipjson
經過docker inspect -f '{{.NetworkSettings.IPAddress}}' node1
來查看查看server端的ip.bootstrap
經過docker exec -it node1 /bin/sh
進入到容器內部的交互shell,經過ip a
命令獲取容器ip
我獲取到的ip爲172.17.0.2
.
經過如下命令
docker run -d -p 8600:8600 -p 8300:8500 -p 8600:53/udp --name client1 -h client1 consul agent -ui -node=client1 -join=172.17.0.2
啓動client端,這裏啓動時自動加入node1組成集羣,啓動client和server的區別在於server啓動的時候帶有-server選項.
經過以上操做,咱們在宿主機訪問localhost:1234
就能夠訪問到consul web管理界面了.
前面咱們使用docker部署了一server一client的集羣.很是順利,也很容易理解,本節部署多server集羣,其實和前面也基本相似,只要知道了主節點的ip,新的節點即可以在運行時使用join ip
的形式加入到集羣中.可是在實際部署中,包括後面的k8s部署,因爲節點數增長,不少坑便暴露出來.這裏和後面使用k8s部署都會講到其中的坑.以供你們參考,方便你們在本身的部署中減小沒必要要麻煩,快速上線產品.
坑一.
* Failed to join X.X.X.X: Member 'consul-deployment-2927201250-tlj1h' has conflicting node ID 'bd203bf1-2d59-42b0-901c-2a5dedf99c86' with this agent's ID) Failed to join any nodes.
經過以上內容能夠看到是節點的id衝突.經過查詢官方文檔,官方文檔裏描述說 node id是一個隨機生成的uuid.然而這個id並非每次建立都隨機生成的,而是從宿主機獲取到的一個隨機字符串,這樣同一臺機器上啓動多個consul容器實例就會出現衝突.k8s中部署也一樣會有此問題.
須要注意的是,以上問題僅出如今同一個機器上啓動多個consul節點,實際生產環境中,爲了保證高可用,是要避免在同一臺主機上部署多個server的.
以上問題請參看
解決方案有兩種第一種是啓動consul的時候指定node-id,並生成一個隨機nodeid
docker run -d --name=node2 consul agent -server -bind=172.17.0.3 -join=172.17.0.2 -node-id=$(uuidgen | awk '{print tolower($0)}') -node=node2
注意以上生成uuid和awk命令都是在執行命令的時候生成的,也就是在宿主機生成的,而不是在容器生成後執行的,所以須要容器宿主機支持
uuidgen
和awk
命令,在docker for windows下是沒法執行經過的.
第二種解決辦法是在啓動consul時加上-disable-host-node-id
選項.
坑二. 沒法訪問ui
前面咱們在windows上部署時候,直接經過consul agent -dev
命令即可以啓動consul,而且能夠訪問web管理界面.可是在集羣部署時若是不指定-ui選項,則沒法訪問web管理界面(僅僅是web界面不能訪問,其它路由仍是能夠正常訪問)
訪問web管理界面還必須指定client綁定,不然也沒法正常訪問
下面咱們搭建一個3個server節點,一個client節點的集羣.
docker run -d -p 8500:8500 -e --name=node1 consul agent -server -bootstrap-expect=3 -node=node1 -client=0.0.0.0 -ui
以上爲了測試方便,防止暴露過多端口出現衝突(同一機器上展現),只暴露了http端口,實際上還須要暴露多個tcp和udp端口.下節在k8s集羣中部署咱們將完整介紹整個部署方案.
docker run -d --name=node2 consul agent -server -join=172.17.0.2 -node=node2 -disable-host-node-id
啓動節點和節點3都是使用上面的命令,唯一要修改的是--name=node2
和-node=node2
兩處,節點3啓動的時候以上兩處都要改成node3
(固然也能夠是其它名字)
注意,你們不要混淆,--name是docker爲容器取的名字,-node是consul運行時給當前啓動節點取的名字
以上的-join裏的ip爲第一個啓動節點的ip,你們能夠經過docker inspect -f '{{.NetworkSettings.IPAddress}}' node1
或者進入到第一個啓動節點裏面執行ip a
獲取它的ip
咱們前面說過client和server的區別在於server啓動的時候指定-server選項,若是不指定則啓動的是client模式
docker run -d -p 8400:8500 --name=node4 consul agent -join=172.17.0.2 -node=node4 -disable-host-node-id -client=0.0.0.0 -ui
這裏對client進行端口映射,以方便經過client進行http操做.
咱們經過localhost:8400或者localhost:8500
就能夠看到整個集羣的節點信息了
注 8500是leader映射出來的端口,而8400是client映射出來的端口
咱們任意進入一個節點內部,這裏咱們以進入node4(也就是client)爲例
docker exec -it node4 /bin/sh
/ # consul members Node Address Status Type Build Protocol DC Segment node1 172.17.0.2:8301 alive server 1.4.4 2 dc1 <all> node2 172.17.0.3:8301 alive server 1.4.4 2 dc1 <all> node3 172.17.0.4:8301 alive server 1.4.4 2 dc1 <all> node4 172.17.0.5:8301 alive client 1.4.4 2 dc1 <default> / #
/ # consul info agent: check_monitors = 0 check_ttls = 0 checks = 0 services = 0 build: prerelease = revision = ea5210a3 version = 1.4.4 consul: acl = disabled known_servers = 3 server = false runtime: arch = amd64 cpu_count = 2 goroutines = 49 max_procs = 2 os = linux version = go1.11.4 serf_lan: coordinate_resets = 0 encrypted = false event_queue = 0 event_time = 2 failed = 0 health_score = 0 intent_queue = 0 left = 0 member_time = 4 members = 4 query_queue = 0 query_time = 1 / #
以上信息量不小,咱們比較關心的是consul
部分的,server=false代表當前節點不是server,known_servers=3代表集羣中共有3個server
若是當前執行命令的節點是server,還能夠看到server 主(leader)信息
... consul: acl = disabled bootstrap = false known_datacenters = 1 leader = false leader_addr = 172.17.0.2:8300 server = true ...
當前節點從集羣中離開
注,因爲docker在啓動容器時指定的要加入的ip,所以當前節點離開後經過
docker start
啓動後會從新自動加入到集羣.若是在實際生產中,不是以容器部署,當前節點掛掉後,須要再次執行前面咱們執行過的命令以加入節點
還有一點須要注意的是,主節點也可能會掛掉,這時候會產生新的節點,這時候就須要知道新的leader的ip,而後把
join
選項裏的ip改成新的leader的ip.下節咱們使用k8s部署的時候咱們將介紹一種新的思路來自動解決易主後節點從新加入集羣的問題.
關於命令的詳細信息,能夠查看官方文檔
建立鍵值存儲
consul除了能夠用於服務註冊外,還能夠用做鍵值存儲.下面咱們簡單介紹一下鍵值存儲用法
consul kv put user/config/connections 5
以上命令會在user目錄下的config目錄下存儲一個鍵名爲connections,值爲5的鍵值對
咱們能夠經過下圖查看其層次
咱們能夠經過如下命令獲取剛存儲的值
consul kv get -detailed user/config/connections
輸出信息爲
/ # consul kv get -detailed user/config/connections CreateIndex 407 Flags 0 Key user/config/connections LockIndex 0 ModifyIndex 407 Session - Value 5 / #
以上鍵值寫入和讀取能夠在任意節點上進行操做
consul提供了豐富的api接口,因爲本教程是偏管理部分的,所以僅對少數對管理有幫助的接口作簡單介紹
目前,使用的版本都是v1,所以全部請求地址的固定部分都是
localhost:8500/v1
agent/members
[ ... { "Name": "node2", "Addr": "172.17.0.3", "Port": 8301, "Tags": { "acls": "0", "build": "1.4.4:ea5210a3", "dc": "dc1", "id": "1866ce4f-e219-78f9-2bee-64f567a1bf74", "port": "8300", "raft_vsn": "3", "role": "consul", "segment": "", "vsn": "2", "vsn_max": "3", "vsn_min": "2", "wan_join_port": "8302" } ... ]
經過以上返回信息,咱們能夠看到節點的不少信息
/status/peers
[ "172.17.0.2:8300", "172.17.0.3:8300", "172.17.0.4:8300" ]
/status/leader
"172.17.0.2:8300"
經過執行命令查看主節點信息只能在server端執行,client沒法獲取到leader信息,而http api則能夠在任意節點執行,都能獲取到主節點信息
查詢注意的服務 catalog/services
查詢某一個服務 catalog/service/服務名
獲取鍵值 kv/key的路徑
好比咱們要獲取咱們剛纔添加的key,則請求路徑爲kv/user/config/connections
[ { "LockIndex": 0, "Key": "user/config/connections", "Flags": 0, "Value": "NQ==", "CreateIndex": 407, "ModifyIndex": 407 } ]
以上的值是base64編碼過的字符串
kv/?keys
原文出處:https://www.cnblogs.com/tylerzhou/p/11157165.html