0 專輯概述
etcd 是云原生架構(gòu)中重要的基礎(chǔ)組件,由 CNCF 孵化托管。etcd 在微服務(wù)和 Kubernates 集群中不僅可以作為服務(wù)注冊(cè)與發(fā)現(xiàn),還可以作為 key-value 存儲(chǔ)的中間件。
《徹底搞懂 etcd 系列文章》將會(huì)從 etcd 的基本功能實(shí)踐、API 接口、實(shí)現(xiàn)原理、源碼分析,以及實(shí)現(xiàn)中的踩坑經(jīng)驗(yàn)等幾方面具體展開介紹 etcd。預(yù)計(jì)會(huì)有 20 篇左右的文章,筆者將會(huì)每周持續(xù)更新,歡迎關(guān)注。
1 etcdctl 的實(shí)踐應(yīng)用
在前面的文章介紹了 etcd 的相關(guān)概念,單機(jī)和集群的多種安裝方式,以及etcd 安全通信相關(guān)的內(nèi)容。本篇主要基于 etcdctl 介紹 etcd 的常用命令和操作。
etcdctl 是一個(gè)命令行客戶端,它能提供一些簡潔的命令,供用戶直接跟etcd服務(wù)打交道,而無需基于 HTTP API 方式??梢苑奖阄覀?cè)趯?duì)服務(wù)進(jìn)行測試或者手動(dòng)修改數(shù)據(jù)庫內(nèi)容。我們剛開始可以通過 etdctl 來熟悉相關(guān)操作。這些操作跟 HTTP API 基本上是對(duì)應(yīng)的。etcdctl 在兩個(gè)不同的 etcd 版本下的行為方式也完全不同。
export ETCDCTL_API=2
export ETCDCTL_API=3
這里主要以講解 API 3 為主。
etcd 項(xiàng)目二進(jìn)制發(fā)行包中已經(jīng)包含了 etcdctl 工具,etcdctl 支持的命令大體上分為數(shù)據(jù)庫操作和非數(shù)據(jù)庫操作兩類。
2 常用命令介紹
首先查看一下 etcd 的版本:
$ etcd --version
etcd Version: 3.4.7
Git SHA: e784ba73c
Go Version: go1.12.12
Go OS/Arch: linux/amd64
我們的版本是 etcd 3.4.7 ,下面介紹下 etcdctl 常用的命令。
$ etcdctl -h
NAME:
etcdctl - A simple command line client for etcd3.
USAGE:
etcdctl [flags]
VERSION:
3.4.7
API VERSION:
3.4
COMMANDS:
alarm disarm Disarms all alarms
alarm list Lists all alarms
auth disable Disables authentication
auth enable Enables authentication
check datascale Check the memory usage of holding data for different workloads on a given server endpoint.
check perf Check the performance of the etcd cluster
compaction Compacts the event history in etcd
defrag Defragments the storage of the etcd members with given endpoints
del Removes the specified key or range of keys [key, range_end)
elect Observes and participates in leader election
endpoint hashkv Prints the KV history hash for each endpoint in --endpoints
endpoint health Checks the healthiness of endpoints specified in `--endpoints` flag
endpoint status Prints out the status of endpoints specified in `--endpoints` flag
get Gets the key or a range of keys
help Help about any command
lease grant Creates leases
lease keep-alive Keeps leases alive (renew)
lease list List all active leases
lease revoke Revokes leases
lease timetolive Get lease information
lock Acquires a named lock
make-mirror Makes a mirror at the destination etcd cluster
member add Adds a member into the cluster
member list Lists all members in the cluster
member promote Promotes a non-voting member in the cluster
member remove Removes a member from the cluster
member update Updates a member in the cluster
migrate Migrates keys in a v2 store to a mvcc store
move-leader Transfers leadership to another etcd cluster member.
put Puts the given key into the store
role add Adds a new role
role delete Deletes a role
role get Gets detailed information of a role
role grant-permission Grants a key to a role
role list Lists all roles
role revoke-permission Revokes a key from a role
snapshot restore Restores an etcd member snapshot to an etcd directory
snapshot save Stores an etcd node backend snapshot to a given file
snapshot status Gets backend snapshot status of a given file
txn Txn processes all the requests in one transaction
user add Adds a new user
user delete Deletes a user
user get Gets detailed information of a user
user grant-role Grants a role to a user
user list Lists all users
user passwd Changes password of user
user revoke-role Revokes a role from a user
version Prints the version of etcdctl
watch Watches events stream on keys or prefixes
OPTIONS:
--cacert="" verify certificates of TLS-enabled secure servers using this CA bundle
--cert="" identify secure client using this TLS certificate file
--command-timeout=5s timeout for short running command (excluding dial timeout)
--debug[=false] enable client-side debug logging
--dial-timeout=2s dial timeout for client connections
-d, --discovery-srv="" domain name to query for SRV records describing cluster endpoints
--discovery-srv-name="" service name to query when using DNS discovery
--endpoints=[127.0.0.1:2379] gRPC endpoints
-h, --help[=false] help for etcdctl
--hex[=false] print byte strings as hex encoded strings
--insecure-discovery[=true] accept insecure SRV records describing cluster endpoints
--insecure-skip-tls-verify[=false] skip server certificate verification
--insecure-transport[=true] disable transport security for client connections
--keepalive-time=2s keepalive time for client connections
--keepalive-timeout=6s keepalive timeout for client connections
--key="" identify secure client using this TLS key file
--password="" password for authentication (if this option is used, --user option shouldn't include password)
--user="" username[:password] for authentication (prompt if password is not supplied)
-w, --write-out="simple" set the output format (fields, json, protobuf, simple, table)
可以看到,etcdctl 支持的命令很多,常用的命令選項(xiàng):
--debug 輸出CURL命令,顯示執(zhí)行命令的時(shí)候發(fā)起的請(qǐng)求
--no-sync 發(fā)出請(qǐng)求之前不同步集群信息
--output, -o 'simple' 輸出內(nèi)容的格式(simple 為原始信息,json 為進(jìn)行json格式解碼,易讀性好一些)
--peers, -C 指定集群中的同伴信息,用逗號(hào)隔開(默認(rèn)為: "127.0.0.1:4001")
--cert-file HTTPS下客戶端使用的SSL證書文件
--key-file HTTPS下客戶端使用的SSL密鑰文件
--ca-file 服務(wù)端使用HTTPS時(shí),使用CA文件進(jìn)行驗(yàn)證
--help, -h 顯示幫助命令信息
--version, -v 打印版本信息
下面我們將介紹其中常用的數(shù)據(jù)庫命令。
3 數(shù)據(jù)庫操作
數(shù)據(jù)庫操作圍繞對(duì)鍵值和目錄的 CRUD (即增刪改查,符合 REST 風(fēng)格的一套API操作)完整生命周期的管理。
etcd在鍵的組織上采用了層次化的空間結(jié)構(gòu)(類似于文件系統(tǒng)中目錄的概念),用戶指定的鍵可以為單獨(dú)的名字,如:testkey,此時(shí)實(shí)際上放在根目錄/下面,也可以為指定目錄結(jié)構(gòu),如/cluster1/node2/testkey,則將創(chuàng)建相應(yīng)的目錄結(jié)構(gòu)。
3.1 鍵操作
-
set 指定某個(gè)鍵的值。例如:
$ etcdctl put /testdir/testkey "Hello world" $ etcdctl put /testdir/testkey2 "Hello world2" $ etcdctl put /testdir/testkey3 "Hello world3"成功寫入三對(duì)鍵值,/testdir/testkey、/testdir/testkey2 和 /testdir/testkey3。
-
get 獲取指定鍵的值。例如:
$ etcdctl get /testdir/testkey Hello world -
get 十六進(jìn)制讀指定的值:
$ etcdctl get /testdir/testkey --hex \x2f\x74\x65\x73\x74\x64\x69\x72\x2f\x74\x65\x73\x74\x6b\x65\x79 #鍵 \x48\x65\x6c\x6c\x6f\x20\x77\x6f\x72\x6c\x64 #值加上
--print-value-only可以讀取對(duì)應(yīng)的值。 -
get 范圍內(nèi)的值
$ etcdctl get /testdir/testkey /testdir/testkey3 /testdir/testkey Hello world /testdir/testkey2 Hello world2可以看到,獲取了大于等于 /testdir/testkey,且小于 /testdir/testkey3 的鍵值對(duì)。testkey3 不在范圍之內(nèi),因?yàn)榉秶前腴_區(qū)間 [testkey, testkey3), 不包含 testkey3。
-
獲取某個(gè)前綴的所有鍵值對(duì),通過 --prefix 可以指定前綴:
$ etcdctl get --prefix /testdir/testkey /testdir/testkey Hello world /testdir/testkey2 Hello world2 /testdir/testkey3 Hello world3這樣既可獲取所有以 /testdir/testkey 開頭的鍵值對(duì)。當(dāng)前綴獲取的結(jié)果過多時(shí),還可以通過 --limit=2 限制獲取的數(shù)量:
etcdctl get --prefix --limit=2 /testdir/testkey -
讀取鍵過往版本的值
應(yīng)用可能想讀取鍵的被替代的值。例如,應(yīng)用可能想通過訪問鍵的過往版本來回滾到舊的配置。或者,應(yīng)用可能想通過多個(gè)請(qǐng)求來得到一個(gè)覆蓋多個(gè)鍵的統(tǒng)一視圖,而這些請(qǐng)求可以通過訪問鍵歷史記錄而來。因?yàn)?etcd 集群上鍵值存儲(chǔ)的每個(gè)修改都會(huì)增加 etcd 集群的全局修訂版本,應(yīng)用可以通過提供舊有的 etcd 修改版本來讀取被替代的鍵?,F(xiàn)有如下這些鍵值對(duì):foo = bar # revision = 2 foo1 = bar2 # revision = 3 foo = bar_new # revision = 4 foo1 = bar1_new # revision = 5以下是訪問以前版本 key 的示例:
$ etcdctl get --prefix foo # 訪問最新版本的key foo bar_new foo1 bar1_new $ etcdctl get --prefix --rev=4 foo # 訪問第4個(gè)版本的key foo bar_new foo1 bar1 $ etcdctl get --prefix --rev=3 foo # 訪問第3個(gè)版本的key foo bar foo1 bar1 $ etcdctl get --prefix --rev=2 foo # 訪問第3個(gè)版本的key foo bar $ etcdctl get --prefix --rev=1 foo # 訪問第1個(gè)版本的key -
讀取大于等于指定鍵的 byte 值的鍵
應(yīng)用可能想讀取大于等于指定鍵 的 byte 值的鍵。假設(shè) etcd 集群已經(jīng)有下列鍵:a = 123 b = 456 z = 789讀取大于等于鍵 b 的 byte 值的鍵的命令:
$ etcdctl get --from-key b b 456 z 789 -
刪除鍵。應(yīng)用可以從 etcd 集群中刪除一個(gè)鍵或者特定范圍的鍵。
假設(shè) etcd 集群已經(jīng)有下列鍵:foo = bar foo1 = bar1 foo3 = bar3 zoo = val zoo1 = val1 zoo2 = val2 a = 123 b = 456 z = 789刪除鍵 foo 的命令:
$ etcdctl del foo 1 # 刪除了一個(gè)鍵刪除從 foo to foo9 范圍的鍵的命令:
$ etcdctl del foo foo9 2 # 刪除了兩個(gè)鍵刪除鍵 zoo 并返回被刪除的鍵值對(duì)的命令:
$ etcdctl del --prev-kv zoo 1 # 一個(gè)鍵被刪除 zoo # 被刪除的鍵 val # 被刪除的鍵的值刪除前綴為 zoo 的鍵的命令:
$ etcdctl del --prefix zoo 2 # 刪除了兩個(gè)鍵刪除大于等于鍵 b 的 byte 值的鍵的命令:
$ etcdctl del --from-key b 2 # 刪除了兩個(gè)鍵
3.2 watch 歷史改動(dòng)
-
watch 監(jiān)測一個(gè)鍵值的變化,一旦鍵值發(fā)生更新,就會(huì)輸出最新的值并退出。例如:用戶更新 testkey 鍵值為 Hello watch。
$ etcdctl watch testkey # 在另外一個(gè)終端: etcdctl put testkey Hello watch testkey Hello watch從 foo to foo9 范圍內(nèi)鍵的命令:
$ etcdctl watch foo foo9 # 在另外一個(gè)終端: etcdctl put foo bar PUT foo bar # 在另外一個(gè)終端: etcdctl put foo1 bar1 PUT foo1 bar1以16進(jìn)制格式在鍵 foo 上進(jìn)行觀察的命令:
$ etcdctl watch foo --hex # 在另外一個(gè)終端: etcdctl put foo bar PUT \x66\x6f\x6f # 鍵 \x62\x61\x72 # 值觀察多個(gè)鍵 foo 和 zoo 的命令:
$ etcdctl watch -i $ watch foo $ watch zoo # 在另外一個(gè)終端: etcdctl put foo bar PUT foo bar # 在另外一個(gè)終端: etcdctl put zoo val PUT zoo val -
查看 key 的歷史改動(dòng),應(yīng)用可能想觀察 etcd 中鍵的歷史改動(dòng)。例如,應(yīng)用想接收到某個(gè)鍵的所有修改。如果應(yīng)用一直連接到 etcd,那么 watch 就足夠好了。但是,如果應(yīng)用或者 etcd 出錯(cuò),改動(dòng)可能發(fā)生在出錯(cuò)期間,這樣應(yīng)用就沒能實(shí)時(shí)接收到這個(gè)更新。為了保證更新被交付,應(yīng)用必須能夠觀察到鍵的歷史變動(dòng)。為了做到這點(diǎn),應(yīng)用可以在觀察時(shí)指定一個(gè)歷史修訂版本,就像讀取鍵的過往版本一樣。
假設(shè)我們完成了下列操作序列:$ etcdctl put foo bar # revision = 2 OK $ etcdctl put foo1 bar1 # revision = 3 OK $ etcdctl put foo bar_new # revision = 4 OK $ etcdctl put foo1 bar1_new # revision = 5 OK觀察歷史改動(dòng):
# 從修訂版本 2 開始觀察鍵 `foo` 的改動(dòng) $ etcdctl watch --rev=2 foo PUT foo bar PUT foo bar_new從上一次歷史修改開始觀察:
# 在鍵 `foo` 上觀察變更并返回被修改的值和上個(gè)修訂版本的值 $ etcdctl watch --prev-kv foo # 在另外一個(gè)終端: etcdctl put foo bar_latest PUT foo # 鍵 bar_new # 在修改前鍵foo的上一個(gè)值 foo # 鍵 bar_latest # 修改后鍵foo的值 -
壓縮修訂版本。如我們提到的,etcd 保存修訂版本以便應(yīng)用可以讀取鍵的過往版本。但是,為了避免積累無限數(shù)量的歷史數(shù)據(jù),壓縮過往的修訂版本就變得很重要。壓縮之后,etcd 刪除歷史修訂版本,釋放資源來提供未來使用。所有修訂版本在壓縮修訂版本之前的被替代的數(shù)據(jù)將不可訪問。這是壓縮修訂版本的命令:
$ etcdctl compact 5 compacted revision 5 #在壓縮修訂版本之前的任何修訂版本都不可訪問 $ etcdctl get --rev=4 foo {"level":"warn","ts":"2020-05-04T16:37:38.020+0800","caller":"clientv3/retry_interceptor.go:62","msg":"retrying of unary invoker failed","target":"endpoint://client-c0d35565-0584-4c07-bfeb-034773278656/127.0.0.1:2379","attempt":0,"error":"rpc error: code = OutOfRange desc = etcdserver: mvcc: required revision has been compacted"} Error: etcdserver: mvcc: required revision has been compacted
3.3 租約
-
授予租約
應(yīng)用可以為 etcd 集群里面的鍵授予租約。當(dāng)鍵被附加到租約時(shí),它的存活時(shí)間被綁定到租約的存活時(shí)間,而租約的存活時(shí)間相應(yīng)的被 time-to-live (TTL)管理。在租約授予時(shí)每個(gè)租約的最小TTL值由應(yīng)用指定。租約的實(shí)際 TTL 值是不低于最小 TTL,由 etcd 集群選擇。一旦租約的 TTL 到期,租約就過期并且所有附帶的鍵都將被刪除。# 授予租約,TTL為100秒 $ etcdctl lease grant 100 lease 694d71ddacfda227 granted with TTL(10s) # 附加鍵 foo 到租約694d71ddacfda227 $ etcdctl put --lease=694d71ddacfda227 foo10 bar OK建議時(shí)間設(shè)置久一點(diǎn),否則來不及操作會(huì)出現(xiàn)如下的錯(cuò)誤:
-
撤銷租約
應(yīng)用通過租約 id 可以撤銷租約。撤銷租約將刪除所有它附帶的 key。
假設(shè)我們完成了下列的操作:$ etcdctl lease revoke 694d71ddacfda227 lease 694d71ddacfda227 revoked $ etcdctl get foo10 -
刷新租期
應(yīng)用程序可以通過刷新其TTL來保持租約活著,因此不會(huì)過期。$ etcdctl lease keep-alive 694d71ddacfda227 lease 694d71ddacfda227 keepalived with TTL(100) lease 694d71ddacfda227 keepalived with TTL(100) ... -
查詢租期
應(yīng)用程序可能想要了解租賃信息,以便它們可以續(xù)訂或檢查租賃是否仍然存在或已過期。應(yīng)用程序也可能想知道特定租約所附的 key。假設(shè)我們完成了以下一系列操作:
$ etcdctl lease grant 300 lease 694d71ddacfda22c granted with TTL(300s) $ etcdctl put --lease=694d71ddacfda22c foo10 bar OK獲取有關(guān)租賃信息以及哪些 key 使用了租賃信息:
$ etcdctl lease timetolive 694d71ddacfda22c lease 694d71ddacfda22c granted with TTL(300s), remaining(282s) $ etcdctl lease timetolive --keys 694d71ddacfda22c lease 694d71ddacfda22c granted with TTL(300s), remaining(220s), attached keys([foo10])
4 小結(jié)
本篇主要基于 etcdctl 介紹 etcd 的常用命令和操作,包括鍵值對(duì)的操作、租期、Watch 監(jiān)測鍵值等。通過這些命令實(shí)現(xiàn)我們?cè)谇懊嫖恼陆榻B的 etcd 多種使用場景。下面的文章將開始介紹 etcd v3 的 API 定義和使用,深入了解 etcd 的內(nèi)幕。
訂閱最新文章,歡迎關(guān)注我的公眾號(hào)

推薦閱讀
- etcd 與 Zookeeper、Consul 等其它 k-v 組件的對(duì)比
- 徹底搞懂 etcd 系列文章(一):初識(shí) etcd
- 徹底搞懂 etcd 系列文章(二):etcd 的多種安裝姿勢
- 徹底搞懂 etcd 系列文章(三):etcd 集群運(yùn)維部署
- 徹底搞懂 etcd 系列文章(四):etcd 安全