徹底搞懂 etcd 系列文章(五):etcdctl 的使用

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)

image

推薦閱讀

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

參考

etcd docs

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容