一、簡介
etcd是一個高可用的分布式鍵值(key-value)數據庫。etcd內部采用raft協議作為一致性算法,etcd基於Go語言實現。
提供配置共享和服務發現的系統比較多,其中最為大家熟知的是[Zookeeper](后文簡稱ZK),而ETCD可以算得上是后起之秀了。在項目實現,一致性協議易理解性,運維,安全等多個維度上,ETCD相比Zookeeper都占據優勢。
etcd是一個服務發現系統,具備以下的特點:
- 簡單:安裝配置簡單,而且提供了HTTP API進行交互,使用也很簡單
- 安全:支持SSL證書驗證
- 快速:根據官方提供的benchmark數據,單實例支持每秒2k+讀操作
- 可靠:采用raft算法,實現分布式系統數據的可用性和一致性
二、ETCD vs ZK
本文選取ZK作為典型代表與ETCD進行比較,而不考慮[Consul]項目作為比較對象,原因為Consul的可靠性和穩定性還需要時間來驗證(項目發起方自身服務並未使用Consul, 自己都不用)。
- 一致性協議: ETCD使用[Raft]協議, ZK使用ZAB(類PAXOS協議),前者容易理解,方便工程實現;
- 運維方面:ETCD方便運維,ZK難以運維;
- 項目活躍度:ETCD社區與開發活躍,ZK已經快死了;
- API:ETCD提供HTTP+JSON, gRPC接口,跨平台跨語言,ZK需要使用其客戶端;
- 訪問安全方面:ETCD支持HTTPS訪問,ZK在這方面缺失;
三、應用場景
和ZK類似,ETCD有很多使用場景,包括:
- 配置管理
- 服務注冊於發現
- 選主
- 應用調度
- 分布式隊列
- 分布式鎖
四、讀寫性能
按照官網給出的[Benchmark], 在2CPU,1.8G內存,SSD磁盤這樣的配置下,單節點的寫性能可以達到16K QPS, 而先寫后讀也能達到12K QPS。這個性能還是相當可觀的。
五、工作原理
ETCD使用Raft協議來維護集群內各個節點狀態的一致性。簡單說,ETCD集群是一個分布式系統,由多個節點相互通信構成整體對外服務,每個節點都存儲了完整的數據,並且通過Raft協議保證每個節點維護的數據是一致的。
如圖所示,每個ETCD節點都維護了一個狀態機,並且,任意時刻至多存在一個有效的主節點。主節點處理所有來自客戶端寫操作,通過Raft協議保證寫操作對狀態機的改動會可靠的同步到其他節點。
ETCD工作原理核心部分在於Raft協議。本節接下來將簡要介紹Raft協議,具體細節請參考其[論文]。
Raft協議正如論文所述,確實方便理解。主要分為三個部分:選主,日志復制,安全性。
選主
Raft協議是用於維護一組服務節點數據一致性的協議。這一組服務節點構成一個集群,並且有一個主節點來對外提供服務。當集群初始化,或者主節點掛掉后,面臨一個選主問題。集群中每個節點,任意時刻處於Leader, Follower, Candidate這三個角色之一。選舉特點如下:
- 當集群初始化時候,每個節點都是Follower角色;
- 集群中存在至多1個有效的主節點,通過心跳與其他節點同步數據;
- 當Follower在一定時間內沒有收到來自主節點的心跳,會將自己角色改變為Candidate,並發起一次選主投票;當收到包括自己在內超過半數節點贊成后,選舉成功;當收到票數不足半數選舉失敗,或者選舉超時。若本輪未選出主節點,將進行下一輪選舉(出現這種情況,是由於多個節點同時選舉,所有節點均為獲得過半選票)。
-
Candidate節點收到來自主節點的信息后,會立即終止選舉過程,進入Follower角色。
為了避免陷入選主失敗循環,每個節點未收到心跳發起選舉的時間是一定范圍內的隨機值,這樣能夠避免2個節點同時發起選主。
日志復制

所謂日志復制,是指主節點將每次操作形成日志條目,並持久化到本地磁盤,然后通過網絡IO發送給其他節點。其他節點根據日志的邏輯時鍾(TERM)和日志編號(INDEX)來判斷是否將該日志記錄持久化到本地。當主節點收到包括自己在內超過半數節點成功返回,那么認為該日志是可提交的(committed),並將日志輸入到狀態機,將結果返回給客戶端。
這里需要注意的是,每次選主都會形成一個唯一的TERM編號,相當於邏輯時鍾。每一條日志都有全局唯一的編號。

主節點通過網絡IO向其他節點追加日志。若某節點收到日志追加的消息,首先判斷該日志的TERM是否過期,以及該日志條目的INDEX是否比當前以及提交的日志的INDEX跟早。若已過期,或者比提交的日志更早,那么就拒絕追加,並返回該節點當前的已提交的日志的編號。否則,將日志追加,並返回成功。
當主節點收到其他節點關於日志追加的回復后,若發現有拒絕,則根據該節點返回的已提交日志編號,發生其編號下一條日志。
主節點像其他節點同步日志,還作了擁塞控制。具體地說,主節點發現日志復制的目標節點拒絕了某次日志追加消息,將進入日志探測階段,一條一條發送日志,直到目標節點接受日志,然后進入快速復制階段,可進行批量日志追加。
按照日志復制的邏輯,我們可以看到,集群中慢節點不影響整個集群的性能。另外一個特點是,數據只從主節點復制到Follower節點,這樣大大簡化了邏輯流程。
安全性

截止此刻,選主以及日志復制並不能保證節點間數據一致。試想,當一個某個節點掛掉了,一段時間后再次重啟,並當選為主節點。而在其掛掉這段時間內,集群若有超過半數節點存活,集群會正常工作,那么會有日志提交。這些提交的日志無法傳遞給掛掉的節點。當掛掉的節點再次當選主節點,它將缺失部分已提交的日志。在這樣場景下,按Raft協議,它將自己日志復制給其他節點,會將集群已經提交的日志給覆蓋掉。
這顯然是不可接受的。
其他協議解決這個問題的辦法是,新當選的主節點會詢問其他節點,和自己數據對比,確定出集群已提交數據,然后將缺失的數據同步過來。這個方案有明顯缺陷,增加了集群恢復服務的時間(集群在選舉階段不可服務),並且增加了協議的復雜度。
Raft解決的辦法是,在選主邏輯中,對能夠成為主的節點加以限制,確保選出的節點已定包含了集群已經提交的所有日志。如果新選出的主節點已經包含了集群所有提交的日志,那就不需要從和其他節點比對數據了。簡化了流程,縮短了集群恢復服務的時間。
這里存在一個問題,加以這樣限制之后,還能否選出主呢?答案是:只要仍然有超過半數節點存活,這樣的主一定能夠選出。因為已經提交的日志必然被集群中超過半數節點持久化,顯然前一個主節點提交的最后一條日志也被集群中大部分節點持久化。當主節點掛掉后,集群中仍有大部分節點存活,那這存活的節點中一定存在一個節點包含了已經提交的日志了。
至此,關於Raft協議的簡介就全部結束了。
六、使用案例
據公開資料顯示,至少有CoreOS, Google Kubernetes, Cloud Foundry, 以及在Github上超過500個項目在使用ETCD。
七、接口
ETCD提供HTTP協議,在最新版本中支持Google gRPC方式訪問。具體支持接口情況如下:
- ETCD是一個高可靠的KV存儲系統,支持PUT/GET/DELETE接口;
- 為了支持服務注冊與發現,支持WATCH接口(通過http long poll實現);
- 支持KEY持有TTL屬性;
- CAS(compare and swap)操作;
- 支持多key的事務操作;
- 支持目錄操作
八、正式安裝(單節點)
etcd在生產環境中一般推薦集群方式部署。在這里,主要講講單節點安裝和基本使用。
因為etcd是go語言編寫的,安裝只需要下載對應的二進制文件,並放到合適的路徑就行。
下載軟件包
訪問下載鏈接:
https://github.com/etcd-io/etcd/releases
目前最新版本是3.3.10,所以完整的下載鏈接如下:
https://github.com/etcd-io/etcd/releases/download/v3.3.10/etcd-v3.3.10-linux-amd64.tar.gz
安裝
本文所使用的系統為: ubuntu-16.04.5-server-amd64
wget https://github.com/etcd-io/etcd/releases/download/v3.3.10/etcd-v3.3.10-linux-amd64.tar.gz tar zxvf etcd-v3.3.10-linux-amd64.tar.gz mv etcd-v3.3.10-linux-amd64 /opt/etcd-v3.3.10
解壓后的文件如下所示:
root@ubuntu:/opt/etcd-v3.3.10# ls default.etcd Documentation etcd etcdctl README-etcdctl.md README.md READMEv2-etcdctl.md
其中etcd是server端,etcdctl是客戶端,操作之后會生成一個default.etcd,主要用來存儲etct數據。
啟動一個單節點的etcd服務,只需要運行etcd命令就行。不過有可能會出現以下問題:
root@ubuntu:/opt/etcd-v3.3.10# ./etcd bash: ./etcd: 權限不夠
這個時候需要提高文件的權限,采用如下方法:
root@ubuntu:/opt/etcd-v3.3.10# chmod 755 etcd
再次啟動etcd
root@ubuntu:/opt/etcd-v3.3.10# ./etcd
成功后可以看見以下提示:

2018-11-11 15:46:43.134431 I | etcdmain: etcd Version: 3.3.10 2018-11-11 15:46:43.134941 I | etcdmain: Git SHA: 27fc7e2 2018-11-11 15:46:43.135324 I | etcdmain: Go Version: go1.10.4 2018-11-11 15:46:43.135572 I | etcdmain: Go OS/Arch: linux/amd64 2018-11-11 15:46:43.135781 I | etcdmain: setting maximum number of CPUs to 1, total number of available CPUs is1 2018-11-11 15:46:43.136055 W | etcdmain: no data-dir provided, using default data-dir ./default.etcd 2018-11-11 15:46:43.136331 N | etcdmain: the server is already initialized as member before, starting as etcd member... 2018-11-11 15:46:43.136847 I | embed: listening for peers on http://localhost:2380 2018-11-11 15:46:43.137159 I | embed: listening for client requests on localhost:2379 2018-11-11 15:46:43.138055 I | etcdserver: name = default 2018-11-11 15:46:43.138328 I | etcdserver: data dir = default.etcd 2018-11-11 15:46:43.138718 I | etcdserver: member dir = default.etcd/member 2018-11-11 15:46:43.139011 I | etcdserver: heartbeat = 100ms 2018-11-11 15:46:43.139280 I | etcdserver: election = 1000ms 2018-11-11 15:46:43.139545 I | etcdserver: snapshot count = 100000 2018-11-11 15:46:43.139839 I | etcdserver: advertise client URLs = http://localhost:2379 2018-11-11 15:46:43.141035 I | etcdserver: restarting member 8e9e05c52164694d in cluster cdf818194e3a8c32 at commit index 46 2018-11-11 15:46:43.141923 I | raft: 8e9e05c52164694d became follower at term 2 2018-11-11 15:46:43.142228 I | raft: newRaft 8e9e05c52164694d [peers: [], term: 2, commit: 46, applied: 0, lastindex: 46, lastterm: 2] 2018-11-11 15:46:43.143985 W | auth: simple token is not cryptographically signed 2018-11-11 15:46:43.145713 I | etcdserver: starting server... [version: 3.3.10, cluster version: to_be_decided] 2018-11-11 15:46:43.148015 I | etcdserver/membership: added member 8e9e05c52164694d [http://localhost:2380] to cluster cdf818194e3a8c32 2018-11-11 15:46:43.149041 N | etcdserver/membership: set the initial cluster version to 3.3 2018-11-11 15:46:43.149478 I | etcdserver/api: enabled capabilities for version 3.3 2018-11-11 15:46:45.043137 I | raft: 8e9e05c52164694d is starting a new election at term 2 2018-11-11 15:46:45.043461 I | raft: 8e9e05c52164694d became candidate at term 3 2018-11-11 15:46:45.043495 I | raft: 8e9e05c52164694d received MsgVoteResp from 8e9e05c52164694d at term 3 2018-11-11 15:46:45.043519 I | raft: 8e9e05c52164694d became leader at term 3 2018-11-11 15:46:45.043535 I | raft: raft.node: 8e9e05c52164694d elected leader 8e9e05c52164694d at term 3 2018-11-11 15:46:45.044348 I | etcdserver: published {Name:default ClientURLs:[http://localhost:2379]} to cluster cdf818194e3a8c32 2018-11-11 15:46:45.044593 E | etcdmain: forgot to set Type=notify in systemd service file? 2018-11-11 15:46:45.044737 I | embed: ready to serve client requests 2018-11-11 15:46:45.045232 N | embed: serving insecure client requests on 127.0.0.1:2379, this is strongly discouraged!
從上面的輸出中,我們可以看到很多信息。以下是幾個比較重要的信息:
2018-11-11 15:46:43.138055 I | etcdserver: name = default
name表示節點名稱,默認為default。
2018-11-11 15:46:43.138328 I | etcdserver: data dir = default.etcd
data-dir 保存日志和快照的目錄,默認為當前工作目錄default.etcd/目錄下。
2018-11-11 15:46:43.148015 I | etcdserver/membership: added member 8e9e05c52164694d [http://localhost:2380] to cluster cdf818194e3a8c32
在http://localhost:2380和集群中其他節點通信。
2018-11-11 15:46:43.139839 I | etcdserver: advertise client URLs = http://localhost:2379
在http://localhost:2379提供HTTP API服務,供客戶端交互。
2018-11-11 15:46:43.139011 I | etcdserver: heartbeat = 100ms
heartbeat為100ms,該參數的作用是leader多久發送一次心跳到followers,默認值是100ms。
2018-11-11 15:46:43.139280 I | etcdserver: election = 1000ms
election為1000ms,該參數的作用是重新投票的超時時間,如果follow在該時間間隔沒有收到心跳包,會觸發重新投票,默認為1000ms。
2018-11-11 15:46:43.139545 I | etcdserver: snapshot count = 100000
snapshot count為10000,該參數的作用是指定有多少事務被提交時,觸發截取快照保存到磁盤。
集群和每個節點都會生成一個uuid。
啟動的時候會運行raft,選舉出leader。
采用這種方式啟動的etcd只是一個程序,如果啟動etcd的窗口被關閉的話則etcd便會被關閉
,所以如果要長期使用的話最好是為etcd開啟一個服務,此處便不提供開啟服務的方法,如果有需要讀者可以自行百度。
打開另一個窗口輸入:
root@ubuntu:/opt/etcd-v3.3.10# ./etcd -version etcd Version: 3.3.10 Git SHA: 27fc7e2 Go Version: go1.10.4 Go OS/Arch: linux/amd64
九、使用etcd
etcdctl客戶端
etcd廠商為我們提供提供了一個命令行客戶端—etcdctl,供用戶直接跟etcd服務打交道,而無需基於 HTTP API方式。可以方便我們在對服務進行測試或者手動修改數據庫內容。
etcdctl支持的命令大體上分為數據庫操作和非數據庫操作兩類。
可以使用 ./etcdctl -h 查看etcdctl的用法:
root@ubuntu:/opt/etcd-v3.3.10# ./etcdctl -h
CRUD
注意:etcd的數據庫操作圍繞對鍵值和目錄的CRUD完整生命周期的管理。
etcd在鍵的組織上采用了層次化的空間結構(類似於文件系統中目錄的概念),用戶指定的鍵可以為單獨的名字,如:testkey,此時實際上放在根目錄/下面,也可以為指定目錄結構,如/cluster1/node2/testkey,則將創建相應的目錄結構。
set
指定某個鍵的值
語法:
-ttl '0' 該鍵值的超時時間(單位為秒),不配置(默認為0)則永不超時 –swap-with-value value 若該鍵現在的值是value,則進行設置操作 –swap-with-index '0' 若該鍵現在的索引值是指定索引,則進行設置操作
例如:
root@ubuntu:/opt/etcd-v3.3.10# ./etcdctl set --ttl '5' key "Hello world" Hello world root@ubuntu:/opt/etcd-v3.3.10# ./etcdctl get key Hello world # 等待幾秒,再執行 root@ubuntu:/opt/etcd-v3.3.10# ./etcdctl get key Error: 100: Key not found (/key) [8]
第一個get是5秒內的操作,第二get是5秒后的操作,此刻key的值已經消失了。
update
對指定鍵進行修改
語法:
–ttl '0' 超時時間(單位為秒),不配置(默認為 0)則永不超時。
舉例:
# 先設置一個5秒的值 root@ubuntu:/opt/etcd-v3.3.10# ./etcdctl set --ttl '5' key "Hello world" Hello world # 再修改值 root@ubuntu:/opt/etcd-v3.3.10# ./etcdctl update key "Hello world2" Hello world2 # 等待10秒,再次執行 root@ubuntu:/opt/etcd-v3.3.10# ./etcdctl get key Hello world2
可以發現,即使10秒,也可以get到。說明ttl和value同時更新了!
rm
刪除某個鍵值。
語法:
–dir 如果鍵是個空目錄或者鍵值對則刪除 –recursive 刪除目錄和所有子鍵 –with-value 檢查現有的值是否匹配 –with-index ‘0’檢查現有的index是否匹配
舉例:
# 刪除 root@ubuntu:/opt/etcd-v3.3.10# ./etcdctl rm key PrevNode.Value: Hello world2 # 再次獲取 root@ubuntu:/opt/etcd-v3.3.10# ./etcdctl rm key Error: 100: Key not found (/key) [11]
mk
如果給定的鍵不存在,則創建一個新的鍵值。
語法:
–ttl '0' 超時時間(單位為秒),不配置(默認為 0)。則永不超時
舉例:
root@ubuntu:/opt/etcd-v3.3.10# ./etcdctl mk /test/key "Hello world" Hello world
當鍵存在的時候,執行該命令會報錯,例如:
root@ubuntu:/opt/etcd-v3.3.10# ./etcdctl mk /test/key "Hello world" Error: 105: Key already exists (/test/key) [33]
mkdir
如果給定的鍵目錄不存在,則創建一個新的鍵目錄。
語法:
–ttl '0' 超時時間(單位為秒),不配置(默認為0)則永不超時。
舉例:
root@ubuntu:/opt/etcd-v3.3.10# ./etcdctl mkdir dir2
當鍵目錄存在的時候,執行該命令會報錯,例如:
root@ubuntu:/opt/etcd-v3.3.10# ./etcdctl mkdir dir2 Error: 105: Key already exists (/dir2) [13]
setdir
創建一個鍵目錄。如果目錄不存在就創建,如果目錄存在更新目錄TTL。
語法:
–ttl '0' 超時時間(單位為秒),不配置(默認為0)則永不超時。
舉例:
root@ubuntu:/opt/etcd-v3.3.10# ./etcdctl setdir dir3
如果重復執行,會報錯
root@ubuntu:/opt/etcd-v3.3.10# ./etcdctl setdir dir3 Error: 102: Not a file (/dir3) [34]
updatedir
更新一個已經存在的目錄。
語法:
–ttl '0' 超時時間(單位為秒),不配置(默認為0)則永不超時。
舉例:
root@ubuntu:/opt/etcd-v3.3.10# ./etcdctl updatedir dir2
如果重復執行,不會報錯!
rmdir
刪除一個空目錄,或者鍵值對
root@ubuntu:/opt/etcd-v3.3.10# ./etcdctl rmdir dir2
如果重復執行,會報錯
root@ubuntu:/opt/etcd-v3.3.10# ./etcdctl rmdir dir2 Error: 100: Key not found (/dir2) [36]
若目錄不空會報錯,例如:
root@ubuntu:/opt/etcd-v3.3.10# ./etcdctl set /dir/key hi hi root@ubuntu:/opt/etcd-v3.3.10# ./etcdctl rmdir /dir Error: 108: Directory not empty (/dir) [37]
ls
列出目錄(默認為根目錄)下的鍵或者子目錄,默認不顯示子目錄中內容。
語法:
–sort 將輸出結果排序 –recursive 如果目錄下有子目錄,則遞歸輸出其中的內容 -p 對於輸出為目錄,在最后添加/進行區分
例如:
root@ubuntu:/opt/etcd-v3.3.10# ./etcdctl ls /test /dir2 /dir3
如果有值,則輸出,否則不輸出!
root@ubuntu:/opt/etcd-v3.3.10# ./etcdctl ls test /test/key
非數據庫操作
非數據庫操作包括:備份、監測、節點管理等
backup
備份etcd的數據。
語法:
–data-dir etcd的數據目錄 –backup-dir 備份到指定路徑
例如:
root@ubuntu:/opt/etcd-v3.3.10# ./etcdctl backup --data-dir default.etcd --backup-dir /xx/xx 2018-11-11 16:43:34.119969 I | failed creating backup snapshot dir /xx/xx/member/snap: expected "/xx/xx/member/snap" to be empty, got ["db"]
提示 /xx/xx 目錄不存在!
那換一個存在的目錄,比如/opt/backup。注意:bakcup這個目錄可以不用創建,它會自動創建!
root@ubuntu:/opt/etcd-v3.3.10# ./etcdctl backup --data-dir default.etcd --backup-dir /opt/backup 2018-11-11 16:44:44.845409 I | ignoring EntryConfChange raft entry 2018-11-11 16:44:44.845901 I | ignoring member attribute update on /0/members/8e9e05c52164694d/attributes 2018-11-11 16:44:44.846307 I | ignoring member attribute update on /0/members/8e9e05c52164694d/attributes
查看備份目錄/opt/backup/
root@ubuntu:/opt/etcd-v3.3.10# ll /opt/backup/ total 12 drwx------ 3 root root 4096 Nov 11 16:44 ./ drwxr-xr-x 4 root root 4096 Nov 11 16:44 ../ drwx------ 4 root root 4096 Nov 11 16:44 member/
watch
監測一個鍵值的變化,一旦鍵值發生更新,就會輸出最新的值並退出。
exec-watch
監測一個鍵值的變化,一旦鍵值發生更新,就執行給定命令。
關於 watch 和 exec-watch,請參考鏈接:
https://blog.csdn.net/mnasd/article/details/79621155
我沒有做出來,主要是因為,開起新的窗口之后,get key無法獲取到值
設置一個新的值
./etcdctl set key "Hello world"
執行報錯:

Error: unknown command "set" for "etcdctl" Did you mean this? get put del user Run 'etcdctl --help' for usage. Error: unknown command "set" for "etcdctl" Did you mean this? get put del user
原來的窗口是可以執行的,但是新的窗口一直報錯,各種無賴ing...
member
list 列出etcd實例
add 添加etcd實例
remove 刪除etcd實例
查看集群中存在的節點,例如:
root@ubuntu:/opt/etcd-v3.3.10# ./etcdctl member list 1d64cbbe0759c8f8: name=ubuntu peerURLs=http://192.168.75.129:2380 clientURLs=http://192.168.75.129:2379 isLeader=true
刪除集群中存在的節點,例如:
root@ubuntu:/opt/etcd-v3.3.10# ./etcdctl member remove 1d64cbbe0759c8f8 Received an error trying to remove member 1d64cbbe0759c8f8: client: etcd cluster is unavailable or misconfigured; error #0: client: etcd member http://192.168.75.129:2379 has no leader
提示報錯,集群中沒有leader
向集群中新加節點,例如:
root@ubuntu:/opt/etcd-v3.3.10# ./etcdctl member add etcd3 http://192.168.75.129:2380 Added member named etcd3 with ID 6c40942fac2f358f to cluster ETCD_NAME="etcd3" ETCD_INITIAL_CLUSTER="etcd3=http://192.168.75.129:2380,default=http://localhost:2380" ETCD_INITIAL_CLUSTER_STATE="existing"
針對以上配置參數做些解釋:

ETCD_NAME :ETCD的節點名,在集群中應該保持唯一,可以使用 hostname。 ETCD_DATA_DIR:ETCD的數據存儲目錄,服務運行數據保存的路徑,默認為 ${name}.etcd。 ETCD_SNAPSHOT_COUNTER:多少次的事務提交將觸發一次快照,指定有多少事務(transaction)被提交時,觸發截取快照保存到磁盤。 ETCD_HEARTBEAT_INTERVAL:ETCD節點之間心跳傳輸的間隔,單位毫秒,leader 多久發送一次心跳到 followers。默認值是 100ms。 ETCD_ELECTION_TIMEOUT:該節點參與選舉的最大超時時間,單位毫秒,重新投票的超時時間,如果 follow 在該時間間隔沒有收到心跳包,會觸發重新投票,默認為 1000 ms。 ETCD_LISTEN_PEER_URLS:該節點與其他節點通信時所監聽的地址列表,多個地址使用逗號隔開,其格式可以划分為scheme://IP:PORT,這里的scheme可以是http、https。和同伴通信的地址,比如 http://ip:2380 ,如果有多個,使用逗號分隔。需要所有節點都能夠訪問,所以不要使用 localhost。 ETCD_LISTEN_CLIENT_URLS:該節點與客戶端通信時監聽的地址列表,對外提供服務的地址:比如 http://ip:2379 ,http://127.0.0.1:2379 ,客戶端會連接到這里和 etcd 交互 ETCD_INITIAL_ADVERTISE_PEER_URLS:該成員節點在整個集群中的通信地址列表,這個地址用來傳輸集群數據的地址。因此這個地址必須是可以連接集群中所有的成員的。該節點同伴監聽地址,這個值會告訴集群中其他節點。 ETCD_INITIAL_CLUSTER:配置集群內部所有成員地址,其格式為:ETCD_NAME=ETCD_INITIAL_ADVERTISE_PEER_URLS,如果有多個使用逗號隔開,集群中所有節點的信息,格式為 node1=http://ip1:2380 ,node2=http://ip2:2380 ,…。注意:這里的 node1 是節點的 –name 指定的名字;后面的 ip1:2380 是 –initial-advertise-peer-urls 指定的值 ETCD_ADVERTISE_CLIENT_URLS:廣播給集群中其他成員自己的客戶端地址列表 ETCD_INITIAL_CLUSTER_STATE:新建集群的時候,這個值為new;假如已經存在的集群,這個值為 existing。 ETCD_INITIAL_CLUSTER_TOKEN:初始化集群token,創建集群的token,這個值每個集群保持唯一。這樣的話,如果你要重新創建集群,即使配置和之前一樣,也會再次生成新的集群和節點 uuid;否則會導致多個集群之間的沖突,造成未知的錯誤。
注意:所有ETCD_MY_FLAG的配置參數也可以通過命令行參數進行設置,但是命令行指定的參數優先級更高,同時存在時會覆蓋環境變量對應的值。
api接口
關於etcd api接口,請參考鏈接:
https://www.cnblogs.com/doscho/p/6227351.html
以上內容,本文參考鏈接:
https://www.cnblogs.com/softidea/p/6517959.html
https://blog.csdn.net/mnasd/article/details/79621155
十、一鍵安裝腳本
說明:本腳本,只能在本地服務器安裝。請確保etcd-v3.3.10-linux-amd64.tar.gz文件和shell腳本在同一目錄下。
腳本附帶了使用systemctl命令啟動etcd服務
etcd_v3.3.10.sh
請仔細閱讀開頭部分的注意事項

#/bin/bash # 單擊版etcd安裝腳本 # 本腳本,只能在本地服務器安裝。 # 請確保etcd-v3.3.10-linux-amd64.tar.gz文件和當前腳本在同一目錄下。 # 務必使用root用戶執行此腳本! # 確保可以直接執行python3,因為倒數第4行,有一個json格式化輸出。如果不需要可以忽略 #set -e # 輸入本機ip while true do echo '請輸入本機ip' echo 'Example: 192.168.0.1' echo -e "etcd server ip=\c" read ETCD_Server if [ "$ETCD_Server" == "" ];then echo 'No input etcd server IP' else #echo 'No input etcd server IP' break fi done # etcd啟動服務 cat > /lib/systemd/system/etcd.service <<EOF [Unit] Description=etcd - highly-available key value store Documentation=https://github.com/coreos/etcd Documentation=man:etcd After=network.target Wants=network-online.target [Service] Environment=DAEMON_ARGS= Environment=ETCD_NAME=%H Environment=ETCD_DATA_DIR=/var/lib/etcd/default EnvironmentFile=-/etc/default/%p Type=notify User=etcd PermissionsStartOnly=true #ExecStart=/bin/sh -c "GOMAXPROCS=\$(nproc) /usr/bin/etcd \$DAEMON_ARGS" ExecStart=/usr/bin/etcd \$DAEMON_ARGS Restart=on-abnormal #RestartSec=10s #LimitNOFILE=65536 [Install] WantedBy=multi-user.target Alias=etcd3.service EOF # 主機名 name=`hostname` # etcd的http連接地址 initial_cluster="http://$ETCD_Server:2380" # 判斷進程是否啟動 A=`ps -ef|grep /usr/bin/etcd|grep -v grep|wc -l` if [ $A -ne 0 ];then # 殺掉進程 killall etcd fi # 刪除etcd相關文件 rm -rf /var/lib/etcd/* rm -rf /etc/default/etcd # 設置時區 ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime # 判斷壓縮文件 if [ ! -f "etcd-v3.3.10-linux-amd64.tar.gz" ];then echo "當前目錄etcd-v3.3.10-linux-amd64.tar.gz文件不存在" exit fi # 安裝etcd tar zxf etcd-v3.3.10-linux-amd64.tar.gz -C /tmp/ cp -f /tmp/etcd-v3.3.10-linux-amd64/etcd /usr/bin/ cp -f /tmp/etcd-v3.3.10-linux-amd64/etcdctl /usr/bin/ # etcd配置文件 cat > /etc/default/etcd <<EOF ETCD_NAME=$name ETCD_DATA_DIR="/var/lib/etcd/" ETCD_LISTEN_PEER_URLS="http://$ETCD_Server:2380" ETCD_LISTEN_CLIENT_URLS="http://$ETCD_Server:2379,http://127.0.0.1:4001" ETCD_INITIAL_ADVERTISE_PEER_URLS="http://$ETCD_Server:2380" ETCD_INITIAL_CLUSTER="$ETCD_Servernitial_cluster" ETCD_INITIAL_CLUSTER_STATE="new" ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster-sdn" ETCD_ADVERTISE_CLIENT_URLS="http://$ETCD_Server:2379" EOF # 臨時腳本,添加用戶和組 cat > /tmp/foruser <<EOF #!/bin/bash if [ \`cat /etc/group|grep etcd|wc -l\` -eq 0 ];then groupadd -g 217 etcd;fi if [ \`cat /etc/passwd|grep etcd|wc -l\` -eq 0 ];then mkdir -p /var/lib/etcd && useradd -g 217 -u 111 etcd -d /var/lib/etcd/ -s /bin/false;fi if [ \`cat /etc/profile|grep ETCDCTL_API|wc -l\` -eq 0 ];then bash -c "echo 'export ETCDCTL_API=3' >> /etc/profile" && bash -c "source /etc/profile";fi EOF # 執行腳本 bash /tmp/foruser # 啟動服務 systemctl daemon-reload systemctl enable etcd.service chown -R etcd:etcd /var/lib/etcd systemctl restart etcd.service #netstat -anpt | grep 2379 # 查看版本 etcdctl -v # 訪問API, -s 去掉curl的統計信息. python3 -m json.tool 表示json格式化 curl $initial_cluster/version -s | python3 -m json.tool # 刪除臨時文件 rm -rf /tmp/foruser /tmp/etcd-v3.3.10-linux-amd64
執行腳本,輸出:
請輸入本機ip Example: 192.168.0.1 etcd server ip=192.168.75.129 etcdctl version: 3.3.10 API version: 2 { "etcdserver": "3.3.10", "etcdcluster": "3.3.0" }
如果需要清空etcd的值,使用以下命令
rm -rf /var/lib/etcd/member/*
重啟etcd
service etcd restart
查看etcd的所有的值,其中 --endpoints 用來指定etcd服務器地址
etcdctl get / --prefix --keys-only --endpoints=192.168.0.88:2379