轉載: Etcd 使用入門
etcd簡介
etcd是CoreOS團隊于2013年6月發起的開源項目,它的目標是構建一個高可用的分布式鍵值(key-value)數據庫。etcd內部采用raft
協議作為一致性算法,etcd基于Go語言實現。
etcd作為服務發現系統,有以下的特點:
- 簡單:安裝配置簡單,而且提供了HTTP API進行交互,使用也很簡單
- 安全:支持SSL證書驗證
- 快速:根據官方提供的benchmark數據,單實例支持每秒2k+讀操作
- 可靠:采用raft算法,實現分布式系統數據的可用性和一致性
etcd項目地址:https://github.com/coreos/etcd/
etcd應用場景
etcd比較多的應用場景是用于服務發現,服務發現(Service Discovery)要解決的是分布式系統中最常見的問題之一,即在同一個分布式集群中的進程或服務如何才能找到對方并建立連接。
從本質上說,服務發現就是要了解集群中是否有進程在監聽upd或者tcp端口,并且通過名字就可以進行查找和鏈接。
要解決服務發現的問題,需要下面三大支柱,缺一不可。
- 一個強一致性、高可用的服務存儲目錄。
基于Ralf算法的etcd天生就是這樣一個強一致性、高可用的服務存儲目錄。
- 一種注冊服務和健康服務健康狀況的機制。
用戶可以在etcd中注冊服務,并且對注冊的服務配置key TTL,定時保持服務的心跳以達到監控健康狀態的效果。
- 一種查找和連接服務的機制。
通過在etcd指定的主題下注冊的服務業能在對應的主題下查找到。為了確保連接,我們可以在每個服務機器上都部署一個proxy模式的etcd,這樣就可以確保訪問etcd集群的服務都能夠互相連接。
etcd安裝
etcd在生產環境中一般推薦集群方式部署。本文定位為入門,主要講講單節點安裝和基本使用。
etcd目前默認使用2379端口提供HTTP API服務,2380端口和peer通信(這兩個端口已經被IANA官方預留給etcd);在之前的版本中可能會分別使用4001和7001,在使用的過程中需要注意這個區別。
因為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
解壓后是一些文檔和兩個二進制文件etcd和etcdctl。etcd是server端,etcdctl是客戶端。
$ ls
Documentation etcd etcdctl README-etcdctl.md README.md READMEv2-etcdctl.md
如果在測試環境,啟動一個單節點的etcd服務,只需要運行etcd命令就行。
$ ./etcd
2017-04-10 11:46:44.772465 I | etcdmain: etcd Version: 3.1.5
2017-04-10 11:46:44.772512 I | etcdmain: Git SHA: 20490ca
2017-04-10 11:46:44.772607 I | etcdmain: Go Version: go1.7.5
2017-04-10 11:46:44.772756 I | etcdmain: Go OS/Arch: linux/amd64
2017-04-10 11:46:44.772817 I | etcdmain: setting maximum number of CPUs to 2, total number of available CPUs is 2
2017-04-10 11:46:44.772851 W | etcdmain: no data-dir provided, using default data-dir ./default.etcd
2017-04-10 11:46:44.773298 I | embed: listening for peers on http://localhost:2380
2017-04-10 11:46:44.773583 I | embed: listening for client requests on localhost:2379
2017-04-10 11:46:44.775967 I | etcdserver: name = default
2017-04-10 11:46:44.775993 I | etcdserver: data dir = default.etcd
2017-04-10 11:46:44.776167 I | etcdserver: member dir = default.etcd/member
2017-04-10 11:46:44.776253 I | etcdserver: heartbeat = 100ms
2017-04-10 11:46:44.776264 I | etcdserver: election = 1000ms
2017-04-10 11:46:44.776270 I | etcdserver: snapshot count = 10000
2017-04-10 11:46:44.776285 I | etcdserver: advertise client URLs = http://localhost:2379
2017-04-10 11:46:44.776293 I | etcdserver: initial advertise peer URLs = http://localhost:2380
2017-04-10 11:46:44.776306 I | etcdserver: initial cluster = default=http://localhost:2380
2017-04-10 11:46:44.781171 I | etcdserver: starting member 8e9e05c52164694d in cluster cdf818194e3a8c32
2017-04-10 11:46:44.781323 I | raft: 8e9e05c52164694d became follower at term 0
2017-04-10 11:46:44.781351 I | raft: newRaft 8e9e05c52164694d [peers: [], term: 0, commit: 0, applied: 0, lastindex: 0, lastterm: 0]
2017-04-10 11:46:44.781883 I | raft: 8e9e05c52164694d became follower at term 1
2017-04-10 11:46:44.795542 I | etcdserver: starting server... [version: 3.1.5, cluster version: to_be_decided]
2017-04-10 11:46:44.796453 I | etcdserver/membership: added member 8e9e05c52164694d [http://localhost:2380] to cluster cdf818194e3a8c32
2017-04-10 11:46:45.083350 I | raft: 8e9e05c52164694d is starting a new election at term 1
2017-04-10 11:46:45.083494 I | raft: 8e9e05c52164694d became candidate at term 2
2017-04-10 11:46:45.083520 I | raft: 8e9e05c52164694d received MsgVoteResp from 8e9e05c52164694d at term 2
2017-04-10 11:46:45.083598 I | raft: 8e9e05c52164694d became leader at term 2
2017-04-10 11:46:45.083654 I | raft: raft.node: 8e9e05c52164694d elected leader 8e9e05c52164694d at term 2
2017-04-10 11:46:45.084544 I | etcdserver: published {Name:default ClientURLs:[http://localhost:2379]} to cluster cdf818194e3a8c32
2017-04-10 11:46:45.084638 I | etcdserver: setting up the initial cluster version to 3.1
2017-04-10 11:46:45.084857 I | embed: ready to serve client requests
2017-04-10 11:46:45.085918 E | etcdmain: forgot to set Type=notify in systemd service file?
2017-04-10 11:46:45.086668 N | embed: serving insecure client requests on 127.0.0.1:2379, this is strongly discouraged!
2017-04-10 11:46:45.087004 N | etcdserver/membership: set the initial cluster version to 3.1
2017-04-10 11:46:45.087195 I | etcdserver/api: enabled capabilities for version 3.1
從上面的輸出中,我們可以看到很多信息。以下是幾個比較重要的信息:
- name表示節點名稱,默認為default。
- data-dir 保存日志和快照的目錄,默認為當前工作目錄default.etcd/目錄下。
- 在http://localhost:2380和集群中其他節點通信。
- 在http://localhost:2379提供HTTP API服務,供客戶端交互。
- heartbeat為100ms,該參數的作用是leader多久發送一次心跳到
- followers,默認值是100ms。
- election為1000ms,該參數的作用是重新投票的超時時間,如果follow在該+ 時間間隔沒有收到心跳包,會觸發重新投票,默認為1000ms。
- snapshot count為10000,該參數的作用是指定有多少事務被提交時,觸發+ 截取快照保存到磁盤。
- 集群和每個節點都會生成一個uuid。
- 啟動的時候會運行raft,選舉出leader。
- 上面的方法只是簡單的啟動一個etcd服務,但要長期運行的話,還是做成一個服務好一些。下面將以systemd為例,介紹如何建立一個etcd服務。
創建systemd服務
- 設定etcd配置文件
建立相關目錄
$ mkdir -p /var/lib/etcd/
$ mkdir -p /opt/etcd/config/
- 創建etcd配置文件
$ cat <<EOF | sudo tee /opt/etcd/config/etcd.conf
#節點名稱
ETCD_NAME=$(hostname -s)
#數據存放位置
ETCD_DATA_DIR=/var/lib/etcd
EOF
- 創建systemd配置文件
$ cat <<EOF | sudo tee /etc/systemd/system/etcd.service
[Unit]
Description=Etcd Server
Documentation=https://github.com/coreos/etcd
After=network.target
[Service]
User=root
Type=notify
EnvironmentFile=-/opt/etcd/config/etcd.conf
ExecStart=/opt/etcd/etcd
Restart=on-failure
RestartSec=10s
LimitNOFILE=40000
[Install]
WantedBy=multi-user.target
EOF
- 啟動etcd
$ systemctl daemon-reload && systemctl enable etcd && systemctl start etcd
etcd基本使用
etcdctl是一個命令行客戶端,它能提供一些簡潔的命令,供用戶直接跟etcd服務打交道,而無需基于 HTTP API方式。可以方便我們在對服務進行測試或者手動修改數據庫內容。建議剛剛接觸etcd時通過etdctl來熟悉相關操作。這些操作跟HTTP API基本上是對應的。
etcd項目二進制發行包中已經包含了etcdctl工具,etcdctl支持的命令大體上分為數據庫操作和非數據庫操作兩類。
$ etcd --version
etcd Version: 3.1.5
Git SHA: 20490ca
Go Version: go1.7.5
Go OS/Arch: linux/amd64
$ etcdctl -h
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
常用命令選項:
--debug 輸出CURL命令,顯示執行命令的時候發起的請求
--no-sync 發出請求之前不同步集群信息
--output, -o 'simple' 輸出內容的格式(simple 為原始信息,json 為進行json格式解碼,易讀性好一些)
--peers, -C 指定集群中的同伴信息,用逗號隔開(默認為: "127.0.0.1:4001")
--cert-file HTTPS下客戶端使用的SSL證書文件
--key-file HTTPS下客戶端使用的SSL密鑰文件
--ca-file 服務端使用HTTPS時,使用CA文件進行驗證
--help, -h 顯示幫助命令信息
--version, -v 打印版本信息
數據庫操作
數據庫操作圍繞對鍵值和目錄的CRUD完整生命周期的管理。
etcd在鍵的組織上采用了層次化的空間結構(類似于文件系統中目錄的概念),用戶指定的鍵可以為單獨的名字,如:testkey,此時實際上放在根目錄/下面,也可以為指定目錄結構,如/cluster1/node2/testkey,則將創建相應的目錄結構。
注:CRUD即Create,Read,Update,Delete是符合REST風格的一套API操作。
- set
指定某個鍵的值。例如:
$ etcdctl set /testdir/testkey "Hello world"
Hello world
支持的選項包括:
--ttl '0' 該鍵值的超時時間(單位為秒),不配置(默認為0)則永不超時
--swap-with-value value 若該鍵現在的值是value,則進行設置操作
--swap-with-index '0' 若該鍵現在的索引值是指定索引,則進行設置操作
- get
獲取指定鍵的值。例如:
$ etcdctl get /testdir/testkey
Hello world
當鍵不存在時,則會報錯。例如:
$ etcdctl get /testdir/testkey2
Error: 100: Key not found (/testdir/testkey2) [5]
支持的選項為:
--sort 對結果進行排序
--consistent 將請求發給主節點,保證獲取內容的一致性。
- update
當鍵存在時,更新值內容。例如:
$ etcdctl update /testdir/testkey "Hello"
Hello
當鍵不存在時,則會報錯。例如:
$ etcdctl update /testdir/testkey2 "Hello"
Error: 100: Key not found (/testdir/testkey2) [6]
支持的選項為:
--ttl '0' 超時時間(單位為秒),不配置(默認為 0)則永不超時。
- rm
刪除某個鍵值。例如:
$ etcdctl rm /testdir/testkey
PrevNode.Value: Hello
當鍵不存在時,則會報錯。例如:
$ etcdctl rm /testdir/testkey
Error: 100: Key not found (/testdir/testkey) [7]
支持的選項為:
--dir 如果鍵是個空目錄或者鍵值對則刪除
--recursive 刪除目錄和所有子鍵
--with-value 檢查現有的值是否匹配
--with-index '0'檢查現有的index是否匹配
- mk
如果給定的鍵不存在,則創建一個新的鍵值。例如:
$ etcdctl mk /testdir/testkey "Hello world"
Hello world
當鍵存在的時候,執行該命令會報錯,例如:
$ etcdctl mk /testdir/testkey "Hello world"
Error: 105: Key already exists (/testdir/testkey) [8]
支持的選項為:
--ttl '0' 超時時間(單位為秒),不配置(默認為 0)。則永不超時
- mkdir
如果給定的鍵目錄不存在,則創建一個新的鍵目錄。例如:
$ etcdctl mkdir testdir2
當鍵目錄存在的時候,執行該命令會報錯,例如:
$ etcdctl mkdir testdir2
Error: 105: Key already exists (/testdir2) [9]
支持的選項為:
--ttl '0' 超時時間(單位為秒),不配置(默認為0)則永不超時。
- setdir
創建一個鍵目錄。如果目錄不存在就創建,如果目錄存在更新目錄TTL。
$ etcdctl setdir testdir3
支持的選項為:
--ttl '0' 超時時間(單位為秒),不配置(默認為0)則永不超時。
- updatedir
更新一個已經存在的目錄。
$ etcdctl updatedir testdir2
支持的選項為:
--ttl '0' 超時時間(單位為秒),不配置(默認為0)則永不超時。
- rmdir
刪除一個空目錄,或者鍵值對。
$ etcdctl setdir dir1
$ etcdctl rmdir dir1
若目錄不空,會報錯:
$ etcdctl set /dir/testkey hi
hi
$ etcdctl rmdir /dir
Error: 108: Directory not empty (/dir) [17]
- ls
列出目錄(默認為根目錄)下的鍵或者子目錄,默認不顯示子目錄中內容。
例如:
$ etcdctl ls
/testdir
/testdir2
/dir
$ etcdctl ls dir
/dir/testkey
支持的選項包括:
--sort 將輸出結果排序
--recursive 如果目錄下有子目錄,則遞歸輸出其中的內容
-p 對于輸出為目錄,在最后添加/進行區分
非數據庫操作
- backup
備份etcd的數據。
$ etcdctl backup --data-dir /var/lib/etcd --backup-dir /home/etcd_backup
支持的選項包括:
--data-dir etcd的數據目錄
--backup-dir 備份到指定路徑
- watch
監測一個鍵值的變化,一旦鍵值發生更新,就會輸出最新的值并退出。
例如:用戶更新testkey鍵值為Hello watch。
$ etcdctl get /testdir/testkey
Hello world
$ etcdctl set /testdir/testkey "Hello watch"
Hello watch
$ etcdctl watch testdir/testkey
Hello watch
支持的選項包括:
--forever 一直監測直到用戶按CTRL+C退出
--after-index '0' 在指定index之前一直監測
--recursive 返回所有的鍵值和子鍵值
- exec-watch
監測一個鍵值的變化,一旦鍵值發生更新,就執行給定命令。
例如:用戶更新testkey鍵值。
$ etcdctl exec-watch testdir/testkey -- sh -c 'ls'
config Documentation etcd etcdctl README-etcdctl.md README.md READMEv2-etcdctl.md
支持的選項包括:
--after-index '0' 在指定 index 之前一直監測
--recursive 返回所有的鍵值和子鍵值
- member
通過list
、add
、remove
命令列出、添加、刪除etcd實例到etcd集群中。
查看集群中存在的節點
$ etcdctl member list
8e9e05c52164694d: name=dev-master-01 peerURLs=http://localhost:2380 clientURLs=http://localhost:2379 isLeader=true
刪除集群中存在的節點
$ etcdctl member remove 8e9e05c52164694d
Removed member 8e9e05c52164694d from cluster
向集群中新加節點
$ etcdctl member add etcd3 http://192.168.1.100:2380
Added member named etcd3 with ID 8e9e05c52164694d to cluster
參考文檔
http://www.google.com
http://t.cn/R5Fw20j
http://cizixs.com/2016/08/02/intro-to-etcd