1. 程式人生 > >k8s學習筆記之etcd

k8s學習筆記之etcd

etcd簡介

etcd是一個高可用的分散式鍵值(key-value)資料庫。etcd內部採用raft協議作為一致性演算法,etcd基於Go語言實現。
etcd是一個服務發現系統,具備以下的特點:
簡單:安裝配置簡單,而且提供了HTTP API進行互動,使用也很簡單
安全:支援SSL證書驗證
快速:根據官方提供的benchmark資料,單例項支援每秒2k+讀操作
可靠:採用raft演算法,實現分散式系統資料的可用性和一致性

etcd應用場景

用於服務發現,服務發現(ServiceDiscovery)要解決的是分散式系統中最常見的問題之一,即在同一個分散式叢集中的程序或服務如何才能找到對方並建立連線。

要解決服務發現的問題,需要具備下面三種必備屬性。
- 一個強一致性、高可用的服務儲存目錄。
基於Ralf演算法的etcd天生就是這樣一個強一致性、高可用的服務儲存目錄。
一種註冊服務和健康服務健康狀況的機制。

  • 使用者可以在etcd中註冊服務,並且對註冊的服務配置key TTL,定時保持服務的心跳以達到監控健康狀態的效果。
  • 一種查詢和連線服務的機制。
    通過在etcd指定的主題下注冊的服務業能在對應的主題下查詢到。為了確保連線,我們可以在每個服務機器上都部署一個proxy模式的etcd,這樣就可以確保訪問etcd叢集的服務都能夠互相連線。

etcd安裝

etcd在生產環境中一般推薦叢集方式部署。在這裡,主要講講單節點安裝和基本使用。
因為etcd是go語言編寫的,安裝只需要下載對應的二進位制檔案,並放到合適的路徑就行。

下載軟體包

$ wget https://github.com/coreos/etcd/releases/download/v3.1.5/etcd-v3.1.5-linux-amd64.tar.gz
$ tar xzvf etcd-v3.1.5-linux-amd64.tar.gz
$ mv etcd-v3.1.5-linux-amd64 /opt/etcd

解壓後的檔案如下所示:

root@rice:/opt/etcd# ls
Documentation  etcd  etcdctl  README-etcdctl.md  README.md  READMEv2-etcdctl.md

其中etcd是server端,etcdctl是客戶端,操作之後會生成一個default.etcd,主要用來儲存etct資料。
啟動一個單節點的etcd服務,只需要執行etcd命令就行。不過有可能會出現以下問題:

root@rice:/opt/etcd# ./etcd
bash: ./etcd: 許可權不夠

這個時候需要提高檔案的許可權,採用如下方法:

root@rice:/opt/etcd# chmod 777 etcd

再次啟動etcd,成功後可以看見以下提示:

[email protected]:/opt/etcd# ./etcd
2017-08-02 10:41:26.241044 I | etcdmain: etcd Version: 3.1.5
2017-08-02 10:41:26.241150 I | etcdmain: Git SHA: 20490ca
2017-08-02 10:41:26.241170 I | etcdmain: Go Version: go1.7.5
2017-08-02 10:41:26.241187 I | etcdmain: Go OS/Arch: linux/amd64
2017-08-02 10:41:26.241205 I | etcdmain: setting maximum number of CPUs to 4, total number of available CPUs is 4
2017-08-02 10:41:26.241230 W | etcdmain: no data-dir provided, using default data-dir ./default.etcd
2017-08-02 10:41:26.241730 I | embed: listening for peers on http://localhost:2380
2017-08-02 10:41:26.241883 I | embed: listening for client requests on localhost:2379
2017-08-02 10:41:26.246016 I | etcdserver: name = default
2017-08-02 10:41:26.246058 I | etcdserver: data dir = default.etcd
2017-08-02 10:41:26.246078 I | etcdserver: member dir = default.etcd/member
2017-08-02 10:41:26.246095 I | etcdserver: heartbeat = 100ms
2017-08-02 10:41:26.246110 I | etcdserver: election = 1000ms
2017-08-02 10:41:26.246127 I | etcdserver: snapshot count = 10000
2017-08-02 10:41:26.246153 I | etcdserver: advertise client URLs = http://localhost:2379
2017-08-02 10:41:26.246173 I | etcdserver: initial advertise peer URLs = http://localhost:2380
2017-08-02 10:41:26.246201 I | etcdserver: initial cluster = default=http://localhost:2380
2017-08-02 10:41:26.252215 I | etcdserver: starting member 8e9e05c52164694d in cluster cdf818194e3a8c32
2017-08-02 10:41:26.252400 I | raft: 8e9e05c52164694d became follower at term 0
2017-08-02 10:41:26.252455 I | raft: newRaft 8e9e05c52164694d [peers: [], term: 0, commit: 0, applied: 0, lastindex: 0, lastterm: 0]
2017-08-02 10:41:26.252492 I | raft: 8e9e05c52164694d became follower at term 1
2017-08-02 10:41:26.268040 I | etcdserver: starting server... [version: 3.1.5, cluster version: to_be_decided]
2017-08-02 10:41:26.268837 I | etcdserver/membership: added member 8e9e05c52164694d [http://localhost:2380] to cluster cdf818194e3a8c32
2017-08-02 10:41:26.553047 I | raft: 8e9e05c52164694d is starting a new election at term 1
2017-08-02 10:41:26.553127 I | raft: 8e9e05c52164694d became candidate at term 2
2017-08-02 10:41:26.553144 I | raft: 8e9e05c52164694d received MsgVoteResp from 8e9e05c52164694d at term 2
2017-08-02 10:41:26.553159 I | raft: 8e9e05c52164694d became leader at term 2
2017-08-02 10:41:26.553170 I | raft: raft.node: 8e9e05c52164694d elected leader 8e9e05c52164694d at term 2
2017-08-02 10:41:26.553336 I | etcdserver: setting up the initial cluster version to 3.1
2017-08-02 10:41:26.555447 N | etcdserver/membership: set the initial cluster version to 3.1
2017-08-02 10:41:26.555481 I | etcdserver/api: enabled capabilities for version 3.1
2017-08-02 10:41:26.555506 I | embed: ready to serve client requests
2017-08-02 10:41:26.555636 I | etcdserver: published {Name:default ClientURLs:[http://localhost:2379]} to cluster cdf818194e3a8c32
2017-08-02 10:41:26.555852 N | embed: serving insecure client requests on 127.0.0.1:2379, this is strongly discouraged!

從上面的輸出中,我們可以看到很多資訊。以下是幾個比較重要的資訊:

2017-08-02 10:41:26.246016 I | etcdserver: name = default

name表示節點名稱,預設為default。

2017-08-02 10:41:26.246058 I | etcdserver: data dir = default.etcd

data-dir 儲存日誌和快照的目錄,預設為當前工作目錄default.etcd/目錄下。

2017-08-02 10:41:26.246201 I | etcdserver: initial cluster = default=http://localhost:2380
2017-08-02 10:41:26.246153 I | etcdserver: advertise client URLs = http://localhost:2379
2017-08-02 10:41:26.246095 I | etcdserver: heartbeat = 100ms

heartbeat為100ms,該引數的作用是leader多久傳送一次心跳到followers,預設值是100ms。

2017-08-02 10:41:26.246110 I | etcdserver: election = 1000ms

election為1000ms,該引數的作用是重新投票的超時時間,如果follow在該時間間隔沒有收到心跳包,會觸發重新投票,預設為1000ms。

2017-08-02 10:41:26.246127 I | etcdserver: snapshot count = 10000

snapshot count為10000,該引數的作用是指定有多少事務被提交時,觸發擷取快照儲存到磁碟。
叢集和每個節點都會生成一個uuid。
啟動的時候會執行raft,選舉出leader。

採用這種方式啟動的etcd只是一個程式,如果啟動etcd的視窗被關閉的話則etcd便會被關閉
,所以如果要長期使用的話最好是為etcd開啟一個服務,此處便不提供開啟服務的方法,如果有需要讀者可以自行百度。

開啟另一個視窗輸入:

root@rice:/opt/etcd# ./etcd -version

可以看到etcd等的版本資訊

etcd Version: 3.1.5
Git SHA: 20490ca
Go Version: go1.7.5
Go OS/Arch: linux/amd64

那麼etcd如何使用呢?

etcd廠商為我們提供提供了一個命令列客戶端—etcdctl,供使用者直接跟etcd服務打交道,而無需基於 HTTP API方式。可以方便我們在對服務進行測試或者手動修改資料庫內容。
etcdctl支援的命令大體上分為資料庫操作和非資料庫操作兩類。
可以使用 ./etcdctl -h 檢視etcdctl的用法:

[email protected]:/opt/etcd# ./etcdctl -h 檢視etcdctl的用法:
NAME:
   etcdctl - A simple command line client for etcd.

USAGE:
   etcdctl [global options] command [command options] [arguments...]

VERSION:
   3.1.5

COMMANDS:
     backup          backup an etcd directory
     cluster-health  check the health of the etcd cluster
     mk              make a new key with a given value
     mkdir           make a new directory
     rm              remove a key or a directory
     rmdir           removes the key if it is an empty directory or a key-value pair
     get             retrieve the value of a key
     ls              retrieve a directory
     set             set the value of a key
     setdir          create a new directory or update an existing directory TTL
     update          update an existing key with a given value
     updatedir       update an existing directory
     watch           watch a key for changes
     exec-watch      watch a key for changes and exec an executable
     member          member add, remove and list subcommands
     user            user add, grant and revoke subcommands
     role            role add, grant and revoke subcommands
     auth            overall auth controls
     help, h         Shows a list of commands or help for one command

GLOBAL OPTIONS:
   --debug                          output cURL commands which can be used to reproduce the request
   --no-sync                        don't synchronize cluster information before sending request
   --output simple, -o simple       output response in the given format (simple, `extended` or `json`) (default: "simple")
   --discovery-srv value, -D value  domain name to query for SRV records describing cluster endpoints
   --insecure-discovery             accept insecure SRV records describing cluster endpoints
   --peers value, -C value          DEPRECATED - "--endpoints" should be used instead
   --endpoint value                 DEPRECATED - "--endpoints" should be used instead
   --endpoints value                a comma-delimited list of machine addresses in the cluster (default: "http://127.0.0.1:2379,http://127.0.0.1:4001")
   --cert-file value                identify HTTPS client using this SSL certificate file
   --key-file value                 identify HTTPS client using this SSL key file
   --ca-file value                  verify certificates of HTTPS-enabled servers using this CA bundle
   --username value, -u value       provide username[:password] and prompt if password is not supplied.
   --timeout value                  connection timeout per request (default: 2s)
   --total-timeout value            timeout for the command execution (except watch) (default: 5s)
   --help, -h                       show help
   --version, -v                    print the version

資料庫操作圍繞對鍵值和目錄的CRUD完整生命週期的管理。

etcd在鍵的組織上採用了層次化的空間結構(類似於檔案系統中目錄的概念),使用者指定的鍵可以為單獨的名字,如:testkey,此時實際上放在根目錄/下面,也可以為指定目錄結構,如/cluster1/node2/testkey,則將建立相應的目錄結構。

set
指定某個鍵的值。
-ttl ‘0’ 該鍵值的超時時間(單位為秒),不配置(預設為0)則永不超時
–swap-with-value value 若該鍵現在的值是value,則進行設定操作
–swap-with-index ‘0’ 若該鍵現在的索引值是指定索引,則進行設定操作

get
獲取指定鍵的值

例如:

[email protected]:/opt/etcd# ./etcdctl set --ttl '5' key "Hello world"
Hello world
[email protected]:/opt/etcd# ./etcdctl get key
Hello world
[email protected]:/opt/etcd# ./etcdctl get key
Error:  100: Key not found (/key) [14]

第一個get是5秒內的操作,第二get是5秒後的操作,此刻key的值已經消失了。

update
對指定鍵進行修改
–ttl ‘0’ 超時時間(單位為秒),不配置(預設為 0)則永不超時。

root@rice:/opt/etcd# ./etcdctl update key "Hello world2"
Hello world2
root@rice:/opt/etcd# ./etcdctl get key
Hello world2

rm
刪除某個鍵值。
–dir 如果鍵是個空目錄或者鍵值對則刪除
–recursive 刪除目錄和所有子鍵
–with-value 檢查現有的值是否匹配
–with-index ‘0’檢查現有的index是否匹配

例如

[email protected]:/opt/etcd# ./etcdctl rm key
PrevNode.Value: Hello world2
[email protected]:/opt/etcd# ./etcdctl get key
Error:  100: Key not found (/key) [17]

mk
如果給定的鍵不存在,則建立一個新的鍵值。
–ttl ‘0’ 超時時間(單位為秒),不配置(預設為 0)。則永不超時

例如:

root@rice:/opt/etcd# ./etcdctl mk /test/key "Hello world"
Hello world

當鍵存在的時候,執行該命令會報錯,例如:

root@rice:/opt/etcd#./etcdctl mk /testdir/testkey "Hello world"
Error:  105: Key already exists (/testdir/testkey) [8]

mkdir
–ttl ‘0’ 超時時間(單位為秒),不配置(預設為0)則永不超時。
如果給定的鍵目錄不存在,則建立一個新的鍵目錄。

例如:

root@rice:/opt/etcd#./etcdctl mkdir dir2

當鍵目錄存在的時候,執行該命令會報錯,例如:

root@rice:/opt/etcd#./etcdctl mkdir dir2
Error:  105: Key already exists (/dir2) [9]

setdir
建立一個鍵目錄。如果目錄不存在就建立,如果目錄存在更新目錄TTL。
–ttl ‘0’ 超時時間(單位為秒),不配置(預設為0)則永不超時。

例如:

root@rice:/opt/etcd#./etcdctl setdir dir3

updatedir
更新一個已經存在的目錄。
–ttl ‘0’ 超時時間(單位為秒),不配置(預設為0)則永不超時。

例如:

root@rice:/opt/etcd#./etcdctl updatedir dir2

rmdir
刪除一個空目錄,或者鍵值對。

例如:

root@rice:/opt/etcd#./etcdctl setdir dir2
root@rice:/opt/etcd#./etcdctl rmdir dir2

若目錄不空會報錯,例如:

root@rice:/opt/etcd#./etcdctl set /dir/key hi
hi
root@rice:/opt/etcd#./etcdctl rmdir /dir
Error:  108: Directory not empty (/dir) [17]

ls
列出目錄(預設為根目錄)下的鍵或者子目錄,預設不顯示子目錄中內容。
–sort 將輸出結果排序
–recursive 如果目錄下有子目錄,則遞迴輸出其中的內容
-p 對於輸出為目錄,在最後新增/進行區分

例如:

root@rice:/opt/etcd#./etcdctl ls
/dir
/dir2
/dir

例如:

root@rice:/opt/etcd#./etcdctl ls dir
/dir/key

非資料庫操作,非資料庫操作包括:備份、監測、節點管理等

backup
備份etcd的資料。
–data-dir etcd的資料目錄
–backup-dir 備份到指定路徑

例如:

root@rice:/opt/etcd#./etcdctl backup --data-dir default.etcd  --backup-dir /xx/xx

watch
監測一個鍵值的變化,一旦鍵值發生更新,就會輸出最新的值並退出。
–forever 一直監測直到使用者按CTRL+C退出
–after-index ‘0’ 在指定index之前一直監測
–recursive 返回所有的鍵值和子鍵值

例如:使用者更新key鍵值為test。

root@rice:/opt/etcd#./etcdctl set key "Hello world"
Hello world
root@rice:/opt/etcd#./etcdctl watch key

如圖,視窗一直在監控
圖片.png
當我開啟另一視窗,更新key的值後:

圖片.png
之前的監控介面便打印出test,然後退出,如圖:

圖片.png

exec-watch
監測一個鍵值的變化,一旦鍵值發生更新,就執行給定命令。
–after-index ‘0’ 在指定 index 之前一直監測
–recursive 返回所有的鍵值和子鍵值

例如:採用exec-watch設定如果key值被更新則啟動ls命令:

root@rice:/opt/etcd# ./etcdctl exec-watch key -- sh -c 'ls'

當我在另一個視窗update key的值之後,監控的視窗打印出以下資料,且監控不會退出:

[email protected]:/opt/etcd# ./etcdctl exec-watch key -- sh -c 'ls'
default.etcd   etcd README-etcdctl.md  READMEv2-etcdctl.md
Documentation  etcdctl  README.md
default.etcd   etcd README-etcdctl.md  READMEv2-etcdctl.md
Documentation  etcdctl  README.md

有興趣的可以試試,哈哈哈!

root@rice:/opt/etcd# ./etcdctl exec-watch key -- sh -c './etcdctl update key '5''

member
list 列出etcd例項
add 新增etcd例項
remove 刪除etcd例項

檢視叢集中存在的節點,例如:

root@rice:/opt/etcd# ./etcdctl member list
8e9e05c52164694d: name=default peerURLs=http://localhost:2380 clientURLs=http://localhost:2379 isLeader=true

刪除叢集中存在的節點,例如:

root@rice:/opt/etcd# ./etcdctl member remove 8e9e05c52164694d
Removed member 8e9e05c52164694d from cluster

向叢集中新加節點,例如:

root@rice:/opt/etcd# ./etcdctl member add etcd3 http://192.168.1.100:2380
Added member named etcd3 with ID 8e9e05c52164694d to cluster