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

0 專輯概述

etcd 是雲原生架構中重要的基礎組件,由 CNCF 孵化託管。etcd 在微服務和 Kubernates 集羣中不僅可以作爲服務註冊與發現,還可以作爲 key-value 存儲的中間件。

《徹底搞懂 etcd 系列文章》將會從 etcd 的基本功能實踐、API 接口、實現原理、源碼分析,以及實現中的踩坑經驗等幾方面具體展開介紹 etcd。預計會有 20 篇左右的文章,筆者將會每週持續更新,歡迎關注。

1 etcdctl 的實踐應用

在前面的文章介紹了 etcd 的相關概念,單機和集羣的多種安裝方式,以及etcd 安全通信相關的內容。本篇主要基於 etcdctl 介紹 etcd 的常用命令和操作。

etcdctl 是一個命令行客戶端,它能提供一些簡潔的命令,供用戶直接跟etcd服務打交道,而無需基於 HTTP API 方式。可以方便我們在對服務進行測試或者手動修改數據庫內容。我們剛開始可以通過 etdctl 來熟悉相關操作。這些操作跟 HTTP API 基本上是對應的。etcdctl 在兩個不同的 etcd 版本下的行爲方式也完全不同。

export ETCDCTL_API=2
export ETCDCTL_API=3

這裏主要以講解 API 3 爲主。

etcd 項目二進制發行包中已經包含了 etcdctl 工具,etcdctl 支持的命令大體上分爲數據庫操作和非數據庫操作兩類。

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 支持的命令很多,常用的命令選項:

--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 打印版本信息

下面我們將介紹其中常用的數據庫命令。

3 數據庫操作

數據庫操作圍繞對鍵值和目錄的 CRUD (即增刪改查,符合 REST 風格的一套API操作)完整生命週期的管理。

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

3.1 鍵操作

  • set 指定某個鍵的值。例如:

    $ etcdctl put /testdir/testkey "Hello world"
    $ etcdctl put /testdir/testkey2 "Hello world2"
    $ etcdctl put /testdir/testkey3 "Hello world3"
    

    成功寫入三對鍵值,/testdir/testkey、/testdir/testkey2 和 /testdir/testkey3。

  • get 獲取指定鍵的值。例如:

    $ etcdctl get /testdir/testkey
    Hello world
    
  • get 十六進制讀指定的值:

    $ 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 可以讀取對應的值。

  • get 範圍內的值

     $ etcdctl get /testdir/testkey /testdir/testkey3
    
    /testdir/testkey
    Hello world
    /testdir/testkey2
    Hello world2
    

    可以看到,獲取了大於等於 /testdir/testkey,且小於 /testdir/testkey3 的鍵值對。testkey3 不在範圍之內,因爲範圍是半開區間 [testkey, testkey3), 不包含 testkey3。

  • 獲取某個前綴的所有鍵值對,通過 --prefix 可以指定前綴:

    $ etcdctl get --prefix /testdir/testkey
    /testdir/testkey
    Hello world
    /testdir/testkey2
    Hello world2
    /testdir/testkey3
    Hello world3
    

    這樣既可獲取所有以 /testdir/testkey 開頭的鍵值對。當前綴獲取的結果過多時,還可以通過 --limit=2 限制獲取的數量:

    etcdctl get --prefix --limit=2 /testdir/testkey
    
  • 讀取鍵過往版本的值
    應用可能想讀取鍵的被替代的值。例如,應用可能想通過訪問鍵的過往版本來回滾到舊的配置。或者,應用可能想通過多個請求來得到一個覆蓋多個鍵的統一視圖,而這些請求可以通過訪問鍵歷史記錄而來。因爲 etcd 集羣上鍵值存儲的每個修改都會增加 etcd 集羣的全局修訂版本,應用可以通過提供舊有的 etcd 修改版本來讀取被替代的鍵。現有如下這些鍵值對:

    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個版本的key
    foo
    bar_new
    foo1
    bar1
    
    $ etcdctl get --prefix --rev=3 foo #  訪問第3個版本的key
    foo
    bar
    foo1
    bar1
    
    $ etcdctl get --prefix --rev=2 foo #  訪問第3個版本的key
    foo
    bar
    
    $ etcdctl get --prefix --rev=1 foo #  訪問第1個版本的key
    
  • 讀取大於等於指定鍵的 byte 值的鍵
    應用可能想讀取大於等於指定鍵 的 byte 值的鍵。假設 etcd 集羣已經有下列鍵:

    a = 123
    b = 456
    z = 789
    

    讀取大於等於鍵 b 的 byte 值的鍵的命令:

    $ etcdctl get --from-key b
    b
    456
    z
    789
    
  • 刪除鍵。應用可以從 etcd 集羣中刪除一個鍵或者特定範圍的鍵。
    假設 etcd 集羣已經有下列鍵:

    foo = bar
    foo1 = bar1
    foo3 = bar3
    zoo = val
    zoo1 = val1
    zoo2 = val2
    a = 123
    b = 456
    z = 789
    

    刪除鍵 foo 的命令:

    $ etcdctl del foo
    1 # 刪除了一個鍵
    

    刪除從 foo to foo9 範圍的鍵的命令:

    $ etcdctl del foo foo9
    2 # 刪除了兩個鍵
    

    刪除鍵 zoo 並返回被刪除的鍵值對的命令:

    $ etcdctl del --prev-kv zoo
    1   # 一個鍵被刪除
    zoo # 被刪除的鍵
    val # 被刪除的鍵的值
    

    刪除前綴爲 zoo 的鍵的命令:

    $ etcdctl del --prefix zoo
    2 # 刪除了兩個鍵
    

    刪除大於等於鍵 b 的 byte 值的鍵的命令:

    $ etcdctl del --from-key b
    2 # 刪除了兩個鍵
    

3.2 watch 歷史改動

  • watch 監測一個鍵值的變化,一旦鍵值發生更新,就會輸出最新的值並退出。例如:用戶更新 testkey 鍵值爲 Hello watch。

    $ etcdctl watch  testkey
    # 在另外一個終端: etcdctl put  testkey Hello watch
    testkey
    Hello watch
    

    從 foo to foo9 範圍內鍵的命令:

    $ etcdctl watch foo foo9
    # 在另外一個終端: etcdctl put foo bar
    PUT
    foo
    bar
    # 在另外一個終端: etcdctl put foo1 bar1
    PUT
    foo1
    bar1
    

    以16進制格式在鍵 foo 上進行觀察的命令:

    $ etcdctl watch foo --hex
    # 在另外一個終端: etcdctl put foo bar
    PUT
    \x66\x6f\x6f          # 鍵
    \x62\x61\x72          # 值
    

    觀察多個鍵 foo 和 zoo 的命令:

    $ etcdctl watch -i
    $ watch foo
    $ watch zoo
    # 在另外一個終端: etcdctl put foo bar
    PUT
    foo
    bar
    # 在另外一個終端: etcdctl put zoo val
    PUT
    zoo
    val
    
  • 查看 key 的歷史改動,應用可能想觀察 etcd 中鍵的歷史改動。例如,應用想接收到某個鍵的所有修改。如果應用一直連接到 etcd,那麼 watch 就足夠好了。但是,如果應用或者 etcd 出錯,改動可能發生在出錯期間,這樣應用就沒能實時接收到這個更新。爲了保證更新被交付,應用必須能夠觀察到鍵的歷史變動。爲了做到這點,應用可以在觀察時指定一個歷史修訂版本,就像讀取鍵的過往版本一樣。
    假設我們完成了下列操作序列:

    $ 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
    

    觀察歷史改動:

    # 從修訂版本 2 開始觀察鍵 `foo` 的改動
    $ etcdctl watch --rev=2 foo
    PUT
    foo
    bar
    PUT
    foo
    bar_new
    

    從上一次歷史修改開始觀察:

    # 在鍵 `foo` 上觀察變更並返回被修改的值和上個修訂版本的值
    $ etcdctl watch --prev-kv foo
    # 在另外一個終端: etcdctl put foo bar_latest
    PUT
    foo         # 鍵
    bar_new     # 在修改前鍵foo的上一個值
    foo         # 鍵
    bar_latest  # 修改後鍵foo的值
    
  • 壓縮修訂版本。如我們提到的,etcd 保存修訂版本以便應用可以讀取鍵的過往版本。但是,爲了避免積累無限數量的歷史數據,壓縮過往的修訂版本就變得很重要。壓縮之後,etcd 刪除歷史修訂版本,釋放資源來提供未來使用。所有修訂版本在壓縮修訂版本之前的被替代的數據將不可訪問。這是壓縮修訂版本的命令:

    $ 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 租約

  • 授予租約
    應用可以爲 etcd 集羣裏面的鍵授予租約。當鍵被附加到租約時,它的存活時間被綁定到租約的存活時間,而租約的存活時間相應的被 time-to-live (TTL)管理。在租約授予時每個租約的最小TTL值由應用指定。租約的實際 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
    

    建議時間設置久一點,否則來不及操作會出現如下的錯誤:

  • 撤銷租約
    應用通過租約 id 可以撤銷租約。撤銷租約將刪除所有它附帶的 key。
    假設我們完成了下列的操作:

    $ etcdctl lease revoke 694d71ddacfda227
    lease 694d71ddacfda227 revoked
    
    $ etcdctl get foo10
    
  • 刷新租期
    應用程序可以通過刷新其TTL來保持租約活着,因此不會過期。

    $ etcdctl lease keep-alive 694d71ddacfda227
    lease 694d71ddacfda227 keepalived with TTL(100)
    lease 694d71ddacfda227 keepalived with TTL(100)
    ...
    
  • 查詢租期
    應用程序可能想要了解租賃信息,以便它們可以續訂或檢查租賃是否仍然存在或已過期。應用程序也可能想知道特定租約所附的 key。

    假設我們完成了以下一系列操作:

    $ etcdctl lease grant 300
    lease 694d71ddacfda22c granted with TTL(300s)
    
    $ etcdctl put --lease=694d71ddacfda22c foo10 bar
    OK
    

    獲取有關租賃信息以及哪些 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 小結

本篇主要基於 etcdctl 介紹 etcd 的常用命令和操作,包括鍵值對的操作、租期、Watch 監測鍵值等。通過這些命令實現我們在前面文章介紹的 etcd 多種使用場景。下面的文章將開始介紹 etcd v3 的 API 定義和使用,深入瞭解 etcd 的內幕。

訂閱最新文章,歡迎關注我的公衆號

推薦閱讀

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

參考

etcd docs

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章