kubernetes實戰之consul簡單測試環境搭建及填坑


這一節內容有點長,我們將介紹如何基於docker搭建一client一server的consul測試環境,以及如何搭建多server consul測試集群.在基於docker搭建多server的consul集群時出碰到了一些坑,這對我們是很有益的提醒,很多時候我們不能僅僅滿足於最小化的環境搭建及簡單使用,而是要朝着接近生產環境的方向努力.同時,我們這里基於docker搭建集群其實和在宿主機上直接搭建並沒有太大區別,也就是我們僅僅把docker當作類似虛擬機來使用,本系列我們多次強調新瓶裝老酒,我們要真正思考新的技術方案到底能為我們的項目帶來什么,如何充分利用新技術新方案來更好的服務於我們的項目.后面我們會基於k8s來搭建一個接近生產環境的集群,實現節點節點自動組成集群,某個節點掛掉后新增補的節點如何自動加入原有集群.后來我們還會探索如何使用k8s的服務發現功能,實現consul節點的自動擴容.相比傳統的方法手動啟動宕掉的節點或者使用腳本來實現自動化,我們完全基於kubernetes的能力來實現自動化.閑言少敘.我們進入正題,開始講如何使用docker來搭建consul測試集群.后面的具體章節我們再詳細介紹這里討論的內容.

使用docker鏡像部署一個client和一個server

前面我們介紹了在windows下部署dev環境的consul,我們僅部署了一個節點,其實這個節點是一個client節點,不對數據做持久化存儲,僅保存在內存中.生產環境需要持久化存儲數據,因此需要server模式,本篇介紹如何使用consul docker鏡像部署一個server和一個client

拉取consul鏡像

使用docker pull consul命令來拉取consul的docker鏡像.

啟動server 端

通過以下命令啟動server端

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返回容器id

d107a4eda2f84bee09c0ae9044a22aa99249d144a1751e270ef6641fead79884

注意這個數字是隨機的,讀者要看自己的docker實際返回的id

然后我們執行docker ps查看以上容器是否在運行

λ 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

可以看到它已經在運行了.

此節點是server端,client需要加入它組成集群,client加入需要知道server的ip.我們有兩種方式獲取server的ip,實際上就是server所在容器的ip

  • 通過docker inspect -f '{{.NetworkSettings.IPAddress}}' node1來查看查看server端的ip.

  • 通過docker exec -it node1 /bin/sh進入到容器內部的交互shell,通過ip a命令獲取容器ip

我獲取到的ip為172.17.0.2.

啟動client端

通過以下命令

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 consul集群部署及常用命令講解

前面我們使用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的.

以上問題請參看

github issue1
github issue2

解決方案有兩種第一種是啟動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命令都是在執行命令的時候生成的,也就是在宿主機生成的,而不是在容器生成后執行的,因此需要容器宿主機支持uuidgenawk命令,在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集群中部署我們將完整介紹整個部署方案.

啟動節點2和3

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節點

我們前面說過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映射出來的端口

img

常用命令

我們任意進入一個節點內部,這里我們以進入node4(也就是client)為例

docker exec -it node4 /bin/sh
  • consul members
    此命令可以查看當前節點所在集群中所有節點信息
/ # 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
    查看集群中的信息
/ # 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
...
  • consul leave

當前節點從集群中離開

注,由於docker在啟動容器時指定的要加入的ip,因此當前節點離開后通過docker start啟動后會重新自動加入到集群.如果在實際生產中,不是以容器部署,當前節點掛掉后,需要再次執行前面我們執行過的命令以加入節點

還有一點需要注意的是,主節點也可能會掛掉,這時候會產生新的節點,這時候就需要知道新的leader的ip,然后把join選項里的ip改為新的leader的ip.下節我們使用k8s部署的時候我們將介紹一種新的思路來自動解決易主后節點重新加入集群的問題.

關於命令的詳細信息,可以查看官方文檔

創建鍵值存儲

consul除了可以用於服務注冊外,還可以用作鍵值存儲.下面我們簡單介紹一下鍵值存儲用法

consul kv put user/config/connections 5

以上命令會在user目錄下的config目錄下存儲一個鍵名為connections,值為5的鍵值對

我們可以通過下圖查看其層次

img

我們可以通過以下命令獲取剛存儲的值

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
/ #

以上鍵值寫入和讀取可以在任意節點上進行操作

http api接口

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"
		}
        ...
]

通過以上返回信息,我們可以看到節點的很多信息

  • 獲取集群中server列表 /status/peers
[

    "172.17.0.2:8300",
    "172.17.0.3:8300",
    "172.17.0.4:8300"

]
  • 查看集群中的leader /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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM