etcdctl 是一个 etcd 命令行工具,通过它可以与 etcd 集群进行交互。这篇文章总结下 etcdctl 的使用方法。
 
  通用说明 
当前 etcdctl 默认使用 v3 API 和 etcd 通信。如果想要使用 v2 API,可以设置环境变量:ETCDCTL_API=2。 
所有的命令都可以通过 -w 或 --write-out 选项设置输出格式。支持的输出格式有 simple、json、Protobuf、Fields 
所有命令默认都是 simple 输出。如果一个命令有对应的 RPC,那么它可以接受所有输出格式 
如果命令执行失败,返回非 0 退出码,同时会输出错误字符串信息,此时输出格式不生效 
 
  Key-value 命令 
  设置 key 
命令语法:
1 PUT [options] <key> <value> 
 
为指定 key 设置 value 
对应的 RPC: Put 
 
通用选项:
--lease <lease ID>:设置 key 所使用的租约 ID 
--prev-kv:返回该 key 修改之前的值 
ignore-value:使用当前值更新 key 
ignore-lease:使用当前 lease 更新 key 
 
示例:
1 2 3 4 5 $ etcdctl put foo bar OK $ etcdctl get foo foo bar 
 
1 2 3 4 5 6 7 $ etcdctl put foo bar1 --prev-kv OK foo bar $ etcdctl get foo foo bar1 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 $etcdctl  put foo --ignore-valueOK $ etcdctl get foo foo bar1 $ etcdctl get foo -w fields "ClusterID"  : 10316109323310759371"MemberID"  : 12530464223947363063"Revision"  : 4"RaftTerm"  : 2"Key"  : "foo" "CreateRevision"  : 2"ModRevision"  : 4"Version"  : 3"Value"  : "bar1" "Lease"  : 0"More"  : false "Count"  : 1$ etcdctl put foo --ignore-value OK // 可以看到,虽然值没有变,但是其 ModRevision 发生了改变 $ etcdctl get foo -w fields "ClusterID"  : 10316109323310759371"MemberID"  : 12530464223947363063"Revision"  : 5"RaftTerm"  : 2"Key"  : "foo" "CreateRevision"  : 2"ModRevision"  : 5"Version"  : 4"Value"  : "bar1" "Lease"  : 0"More"  : false "Count"  : 1
 
注意事项:
如果想在 value 中包含换行符,需要在输入时使用 "" 引用输入的内容。 
如果输入 value 中包含 -,可以通过如下形式解决,否则 -value 会被当成命令 flag 
 
1 2 ./etcdctl put <key> -- <value> ./etcdctl put -- <key> <value> 
 
例如:
1 2 3 4 5 $ etcdctl put foo3 -- -test  OK $ etcdctl get foo3 foo3 -test  
 
  获取 key 
命令语法:
1 GET [options] <key> [range_end] 
 
用于获取某个 key 或某个 key 范围 [key, range_end) 
对应的 RPC:Range 
 
常用选项:
--hex:以十六进制输出 key/value 
--limit <number>:限制输出结果的个数 
--prefix:通过前缀匹配获取 key 
--order:对结果排序,ASCEND 或 DESCEND 
sort-by:设置排序依据,可以是 CREATE、KEY、MODIFY、VALUE 或 VERSION 
--rev <revision>:指定 KV 版本 
--print-value-only:只输出值 
--consistency:一致性,可以是 Linearizable 或 Serializable 
from-key:获取大于等于指定 key 的所有 key(通过字节比较排序) 
keys-only:只输出 key 
 
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 $ etcdctl get foo foo bar1 $ etcdctl get foo foo2 foo bar1 foo1 bar1 $ etcdctl get foo foo2 --limit  1 foo bar1 $ etcdctl get foo --prefix foo bar1 foo1 bar1 foo2 barnew foo3 -test4 $ etcdctl get foo foo2 --order DESCEND --sort-by MODIFY foo1 bar1 foo bar1 $ etcdctl get foo foo2 --print-value-only bar1 bar1 $ etcdctl get foo --from-key foo bar1 foo1 bar1 foo2 barnew foo3 -test4 $ etcdctl get foo --from-key --keys-only foo foo1 foo2 foo3 
 
注意事项:
可以通过 etcdctl get --from-key '' 获取所有的 key 
当 key 或 value 中有不可打印字符或者控制字符,此时输出可能会引入混淆,为了解决该问题,可以使用 --hex 进行输出 
 
  删除 key 
命令语法:
1 DEL [options] <key> [range_end] 
 
移除指定的 key 或 key 范围 
对应的 RPC 方法:DeleteRange 
如果删除成功,返回删除的元素个数 
 
常用选项:
--prefix:通过前缀匹配指定 key 
--prev-kv:返回删除的 key-value 对 
--from-key:删除大于等于指定 key 的所有 key(通过字节比较排序) 
 
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 $ etcdctl del foo 1 $ etcdctl del foo foo1 0 $ etcdctl del foo foo2 1 $ etcdctl del foo2 --prev-kv 1 foo2 barnew $ etcdctl del foo2 --from-key 1 $ etcdctl del foo2 --prefix 0 
 
  事务 
命令语法:
 
TXN 从标准输入中读取多个请求,并将它们应用到单个原子的事务操作中。一个事务包含 一系列的条件、所有条件都满足时要执行的一系列请求、任意条件不满足时要执行的一系列请求 
对应的 RPC:Txn 
 
TXN 的语法为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <Txn> ::= <CMP>* "\n"  <THEN> "\n"  <ELSE> "\n"  <CMP> ::= (<CMPCREATE>|<CMPMOD>|<CMPVAL>|<CMPVER>|<CMPLEASE>) "\n"  <CMPOP> ::= "<"  | "="  | ">"  <CMPCREATE> := ("c" |"create" )"(" <KEY>")"  <CMPOP> <REVISION> <CMPMOD> ::= ("m" |"mod" )"(" <KEY>")"  <CMPOP> <REVISION> <CMPVAL> ::= ("val" |"value" )"(" <KEY>")"  <CMPOP> <VALUE> <CMPVER> ::= ("ver" |"version" )"(" <KEY>")"  <CMPOP> <VERSION> <CMPLEASE> ::= "lease(" <KEY>")"  <CMPOP> <LEASE> <THEN> ::= <OP>* <ELSE> ::= <OP>* <OP> ::= ((see put, get, del etcdctl command  syntax)) "\n"  <KEY> ::= (%q formatted string) <VALUE> ::= (%q formatted string) <REVISION> ::= "\"" [0-9]+"\""  <VERSION> ::= "\"" [0-9]+"\""  <LEASE> ::= "\"" [0-9]+\""  
 
如果执行的是事务成功条件下的命令列表,输出 SUCCESS,否则输出 FAILURE。同时会输出命令列表中的每个命令的结果,以空行分隔。
常用选项:
--hex:以十六进制输出 key 和 value 
--interactive:以交互模式执行 input transaction 
 
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 $ etcdctl txn -i compares: mod("key1" ) > "0"  success requests (get, put, del): put key1 "overwrote-key1"  failure requests (get, put, del): put key1 "created-key1"  put key2 "some extra key"  FAILURE OK OK $ etcdctl get key1 key1 created-key1 $ etcdctl get key2 key2 some extra key 
 
注意事项:
由于在 TXN 中通过换行符来分隔事务命令,因此如果 TXN 命令中如果本身需要输入换行符,则必须使用 \n。 
 
  压缩 
命令语法:
1 COMPACTION [options] <revision> 
 
compaction 命令用于丢弃给定 revision 之前的所有 etcd 事件历史。由于 etcd 使用多版本并发控制模型,它会以事件历史的形式保存所有的 key 更新记录。当给定 revision 之前的事件历史不再需要时候,此时可以对 key 进行压缩以释放 etcd 后端数据存储空间 
对应的 RPC 方法:Compact 
 
常用选项:
--physical:等待 compaction 操作物理移除所有旧的 revisions 
 
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 $ etcdctl put key value1 -w fields "ClusterID"  : 10316109323310759371"MemberID"  : 12530464223947363063"Revision"  : 21"RaftTerm"  : 2$ etcdctl put key value2 -w fields "ClusterID"  : 10316109323310759371"MemberID"  : 12530464223947363063"Revision"  : 22"RaftTerm"  : 2$ etcdctl compact 22 compacted revision 22 I have no name!@9008eb121933:/opt/bitnami/etcd$ etcdctl get key key value2 $ etcdctl get key --rev 22 key value2 $ etcdctl get key --rev 21 {"level" :"warn" ,"ts" :"2022-02-23T11:34:26.239Z" ,"logger" :"etcd-client" ,"caller" :"v3/retry_interceptor.go:62" ,"msg" :"retrying of unary invoker failed" ,"target" :"etcd-endpoints://0xc00023e000/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 
 
  WATCH 
命令语法:
1 WATCH [options] [key or prefix] [range_end] [--] [exec-command arg1 arg2 ...] 
 
通过 Watch 命令可以监控指定 key、前缀、key 范围的事件流。watch 命令会持续运行,直到出现错误或终端用户手动终止 
对应的 RPC 方法:Watch 
输出的格式为: 
 
1 <event>[\n<old_key>\n<old_value>]\n<key>\n<value>\n<event>\n<next_key>\n<next_value>\n... 
 
常用选项:
--hex:以十六进制输出 key 和 value 
--interactive:开始交互式的 watch 
--prefix:按前缀进行 watch 
--prev-kv:输出之前的 key-value 值 
--rev:从指定的 revision 开始 watch,这可以使得我们获得之间的事件 
 
示例:
1 2 3 4 5 6 7 8 9 $ etcdctl watch foo $ etcdctl put foo bar OK $ etcdctl watch foo PUT foo bar 
 
1 2 3 4 5 6 7 8 $ etcdctl put foo bar2 $ etcdctl watch foo --prev-kv PUT foo bar foo bar2 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 $ etcdctl put foo bar3 OK $ etcdctl put foo3 bar3 OK $ etcdctl put foo1 bar1 OK $ etcdctl watch foo foo2 PUT foo bar3 PUT foo1 bar1 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 $ etcdctl put foo bar4 -w fields "ClusterID"  : 10316109323310759371"MemberID"  : 15168875803774599630"Revision"  : 33"RaftTerm"  : 2$ etcdctl put foo bar5 -w fields "ClusterID"  : 10316109323310759371"MemberID"  : 15168875803774599630"Revision"  : 34"RaftTerm"  : 2$ etcdctl put foo bar6 -w fields "ClusterID"  : 10316109323310759371"MemberID"  : 15168875803774599630"Revision"  : 35"RaftTerm"  : 2$ etcdctl watch foo --rev 34 PUT foo bar5 PUT foo bar6 $ etcdctl watch foo --rev 35 PUT foo bar6 
 
如果想在收到事件后执行命令,可以通过 [--] [exec-command arg1 arg2 ...] 的方式指定,例如在收到事件后,执行 echo watch event received:
1 2 3 4 5 6 7 8 9 10 $ etcdctl watch foo -- echo  watch event received $ etcdctl put foo bar OK $ etcdctl watch foo -- echo  watch event received PUT foo bar watch event received 
 
watch 的响应会通过环境变量 ETCD_WATCH_* 设置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 $ etcdctl put foo bar $ etcdctl watch foo -- sh -c "env | grep ETCD_WATCH_"  PUT foo bar ETCD_WATCH_REVISION=25 ETCD_WATCH_KEY="foo"  ETCD_WATCH_EVENT_TYPE="PUT"  ETCD_WATCH_VALUE="bar"  DELETE foo $ etcdctl del foo ETCD_WATCH_REVISION=26 ETCD_WATCH_KEY="foo"  ETCD_WATCH_EVENT_TYPE="DELETE"  ETCD_WATCH_VALUE=""  
 
  租约 
  创建租约 
命令语法:
 
新建一个租约,租约的到期时间为 ttl 秒 
对应的 RPC:LeaseGrant 
输出创建的租约 ID 
 
示例:
1 2 3 4 5 6 7 8 $ etcdctl lease grant 20 lease 12f77f2076d86f50 granted with TTL(20s) $ etcdctl put foo bar --lease 12f77f2076d86f50 OK $ etcdctl get foo foo bar $ etcdctl get foo 
 
  释放租约 
命令语法:
 
释放一个指定的租约,并删除该租约关联的所有 keys 
对应的 RPC:LeaseRevoke 
 
示例:
1 2 3 4 5 6 7 8 9 10 $ etcdctl lease grant 600 lease 12f77f2076d86f60 granted with TTL(600s) $ etcdctl put foo bar --lease 12f77f2076d86f60 OK $ etcdctl get foo foo bar $ etcdctl lease revoke 12f77f2076d86f60 lease 12f77f2076d86f60 revoked $ etcdctl get foo 
 
  获取租约 
命令语法:
1 LEASE TIMETOLIVE <leaseID> [options] 
 
获取指定租约的信息 
对应的 RPC 方法:LeaseTimeToLive 
 
常用选项:
示例:
1 2 3 4 5 6 7 8 9 10 11 $ etcdctl lease grant 600 lease 12f77f2076d86f66 granted with TTL(600s) $ etcdctl put foo bar --lease 12f77f2076d86f66 OK $ etcdctl lease timetolive 12f77f2076d86f66 lease 12f77f2076d86f66 granted with TTL(600s), remaining(572s) $ etcdctl lease timetolive 12f77f2076d86f66 --keys lease 12f77f2076d86f66 granted with TTL(600s), remaining(566s), attached keys([foo]) $ etcdctl put foo1 bar1 --lease 12f77f2076d86f66 $ etcdctl lease timetolive 12f77f2076d86f66 --keys lease 12f77f2076d86f66 granted with TTL(600s), remaining(462s), attached keys([foo foo1]) 
 
  获取租约列表 
命令语法:
 
列出所有的 lease 
对应的 RPC 方法:LeaseLeases 
 
示例:
1 2 3 $ etcdctl lease list found 1 leases 12f77f2076d86f66 
 
  续约 
命令语法:
1 LEASE KEEP-ALIVE <leaseID> 
 
LEASE KEEP-ALIVE 周期性地对指定租约进行续约,因此该 lease 不会过期 
 
示例:
1 2 3 4 5 6 7 8 $ etcdctl lease timetolive 12f77f2076d86f66 lease 12f77f2076d86f66 granted with TTL(600s), remaining(234s) $ etcdctl lease keep-alive 12f77f2076d86f66 lease 12f77f2076d86f66 keepalived with TTL(600) $ etcdctl lease timetolive 12f77f2076d86f66 lease 12f77f2076d86f66 granted with TTL(600s), remaining(556s) 
 
  集群维护命令 
  成员管理 
成员管理命令用于管理 etcd 集群中的成员关系。
  添加成员 
命令语法:
1 MEMBER ADD <memberName> [options] 
 
在 etcd 集群中新添加一个成员 
输出新成员的成员 ID 以及其所在的 cluster ID 
对应的 RPC 方法:MemberAdd 
 
常用选项:
peer-urls:新成员所关联的 peer-urls,如果包含多个 URL,需要用逗号分隔 
 
示例:
1 2 3 4 5 6 7 $ etcdctl member add newMember --peer-urls=https://etcd4:2380 Member 2833744901904773 added to cluster 8f2a2ec5c0087dcb ETCD_NAME="newMember"  ETCD_INITIAL_CLUSTER="newMember=https://etcd4:2380,etcd1=http://etcd1:2380,etcd3=http://etcd3:2380,etcd2=http://etcd2:2380"  ETCD_INITIAL_ADVERTISE_PEER_URLS="https://etcd4:2380"  ETCD_INITIAL_CLUSTER_STATE="existing"  
 
  更新成员 
命令语法:
1 MEMBER UPDATE <memberID> [options] 
 
对 etcd 集群中的 member 进行更新,只能更新 peer URLs 
输出更新的成员 ID 以及其所在的 cluster ID 
对应的 RPC 方法:MemberUpdate 
 
常用选项:
--peer-urls:成员所关联的 peer-urls,如果包含多个 URL,需要用逗号分隔 
 
示例:
1 2 $ etcdctl member update 2833744901904773 --peer-urls=https://etcd4:2380 Member 2833744901904773 updated in  cluster 8f2a2ec5c0087dcb 
 
  移除成员 
命令语法:
1 MEMBER REMOVE <memberID> 
 
从 etcd 集群中移除成员 
输出删除的成员 ID 以及其所在的 cluster ID。 
对应的 RPC 方法:MEMBER REMOVE  
 
示例:
1 2 $ etcdctl member remove 2833744901904773 Member 2833744901904773 removed from cluster 8f2a2ec5c0087dcb 
 
  列出成员 
命令语法:
 
示例:
1 2 3 4 $ etcdctl member list ade526d28b1f92f7, started, etcd1, http://etcd1:2380, http://etcd1:2379, false  bd388e7810915853, started, etcd3, http://etcd3:2380, http://etcd3:2379, false  d282ac2ce600c1ce, started, etcd2, http://etcd2:2380, http://etcd2:2379, false  
 
  ENDPOINT 命令 
ENDPOINT 命令用于查询独立的 endpoints。
  节点健康信息 
命令语法:
 
用于检查 cluster 集群中 endpoint 列表的健康情况。如果某个 endpoint 无法与集群的其他节点达成一致,就认为该节点是不健康的 
 
常用选项:
--cluster:使用 etcd 集群中的所有成员 
 
示例:
1 2 3 $ etcdctl endpoint health 127.0.0.1:2379 is healthy: successfully committed proposal: took = 8.8908ms 
 
1 2 3 4 5 $ etcdctl endpoint --cluster health http://etcd2:2379 is healthy: successfully committed proposal: took = 9.1295ms http://etcd3:2379 is healthy: successfully committed proposal: took = 8.031ms http://etcd1:2379 is healthy: successfully committed proposal: took = 25.7359ms 
 
  节点状态 
命令语法:
 
ENDPOINT STATUS 用来查询给定 endpoint 列表中每个 endpoint 的状态。 
 
示例:
1 2 3 4 5 6 7 $ etcdctl endpoint status 127.0.0.1:2379, ade526d28b1f92f7, 3.5.2, 25 kB, false , false , 2, 85, 85, $ etcdctl endpoint status --cluster http://etcd1:2379, ade526d28b1f92f7, 3.5.2, 25 kB, false , false , 2, 85, 85, http://etcd3:2379, bd388e7810915853, 3.5.2, 25 kB, true , false , 2, 85, 85, http://etcd2:2379, d282ac2ce600c1ce, 3.5.2, 25 kB, false , false , 2, 85, 85, 
 
  节点 HASHKV 
命令语法:
 
ENDPOINT HASHKV 用于获取某个 endpoint KV 存储的 hash 值 
 
示例:
1 2 3 4 5 6 7 $ etcdctl endpoint hashkv 127.0.0.1:2379, 2755762864 $ etcdctl endpoint hashkv --cluster http://etcd1:2379, 2755762864 http://etcd3:2379, 2755762864 http://etcd2:2379, 2755762864 
 
  ALARM 命令 
提供告警相关的命令。
  解除警告 
命令语法:
 
解除所有的告警 
对应的 RPC 方法: Alarm 
 
示例:
 
  列出警告 
 
列出所有的告警 
对应的 RPC 方法为 Alarm 
 
示例:
 
  碎片整理 
DEFRAG 命令可以在 etcd 运行时为一系列 endpoint 整理后端数据库文件的碎片。当 etcd member 删除或压缩 keys 时,这些 keys 占用的空间仍然会被占用。通过对数据库进行碎片整理,etcd 成员可以把这些空间归还给文件系统。
需要注意,在某个成员上进行在线的碎片整理会阻塞系统的读写。碎片整理操作默认不会在集群中传播,它只会应用于 local node。可以通过 --endpoints 指定集群成员,或者使用 --cluster 标志来指定所有集群成员。
如果想使用离线碎片整理(–data-dir flag),可以使用 etcutl defrag。
示例:
1 2 3 4 etcdctl --endpoints=localhost:2379,badendpoint:2379 defrag Finished defragmenting etcd member[localhost:2379] {"level" :"warn" ,"ts" :"2022-02-24T12:05:08.985Z" ,"logger" :"etcd-client" ,"caller" :"v3/retry_interceptor.go:62" ,"msg" :"retrying of unary invoker failed" ,"target" :"etcd-endpoints://0xc00020e000/localhost:2379" ,"attempt" :0,"error" :"rpc error: code = DeadlineExceeded desc = latest balancer error: last connection error: connection error: desc = \"transport: Error while dialing dial tcp: lookup badendpoint on 127.0.0.11:53: no such host\"" } Failed to defragment etcd member[badendpoint:2379] (context deadline exceeded) 
 
1 2 3 4 $ etcdctl defrag --cluster Finished defragmenting etcd member[http://etcd1:2379] Finished defragmenting etcd member[http://etcd3:2379] Finished defragmenting etcd member[http://etcd2:2379] 
 
如果想直接压缩某个数据目录,可以使用 etcdutl 并指定 --data-dir(该标志马上将被删除)。
  快照命令 
SNAPSHOT 命令可以用于实现快照。
  保存快照 
命令语法:
1 SNAPSHOT SAVE <filename> 
 
示例:
1 2 3 4 5 6 7 8 etcdctl snapshot save test.db {"level" :"info" ,"ts" :1645705033.3974695,"caller" :"snapshot/v3_snapshot.go:68" ,"msg" :"created temporary db file" ,"path" :"test.db.part" } {"level" :"info" ,"ts" :1645705033.4031475,"logger" :"client" ,"caller" :"v3/maintenance.go:211" ,"msg" :"opened snapshot stream; downloading" } {"level" :"info" ,"ts" :1645705033.403688,"caller" :"snapshot/v3_snapshot.go:76" ,"msg" :"fetching snapshot" ,"endpoint" :"127.0.0.1:2379" } {"level" :"info" ,"ts" :1645705033.4247742,"logger" :"client" ,"caller" :"v3/maintenance.go:219" ,"msg" :"completed snapshot read; closing" } {"level" :"info" ,"ts" :1645705033.428916,"caller" :"snapshot/v3_snapshot.go:91" ,"msg" :"fetched snapshot" ,"endpoint" :"127.0.0.1:2379" ,"size" :"25 kB" ,"took" :"now" } {"level" :"info" ,"ts" :1645705033.4335535,"caller" :"snapshot/v3_snapshot.go:100" ,"msg" :"saved" ,"path" :"test.db" } Snapshot saved at test.db 
 
  恢复快照 
命令语法:
1 SNAPSHOT RESTORE [options] <filename> 
 
它根据后端数据库快照以及新的集群配置,为 etcd 集群成员创建一个 etcd 数据目录。为新集群中的每个 member 恢复 snapshot,这样新的 etcd 集群就预先加载了快照数据 
该命令即将被遗弃,应该使用 etcdutl snapshot restore 
 
该命令支持的选项基本类似于 etcd 集群命令:
--data-dir <dir>:数据目录的路径,如果没有指定的话默认使用 <name>.etcd 
--wal-dir <dir>:WAL 目录路径,如果没有指定的话则使用数据目录 
--initial-cluster <configuration>:初始集群配置 
initial-cluster-token:初始 token 
initial-advertise-peer-urls:初始通告的成员 peer URLS 
name:集群成员名称 
skip-hash-check:忽略快照的 hash value 
 
示例:
1 2 3 4 5 6 7 8 9 $ etcdctl snapshot restore test.db --initial-cluster-token etcd-cluster-1 --initial-advertise-peer-urls http://127.0.0.1:12380  --name sshot1 --initial-cluster 'sshot1=http://127.0.0.1:12380,sshot2=http://127.0.0.1:22380,sshot3=http://127.0.0.1:32380'  Deprecated: Use `etcdutl snapshot restore` instead. 2022-02-24T13:03:33Z    info    snapshot/v3_snapshot.go:251     restoring snapshot      {"path" : "test.db" , "wal-dir" : "sshot1.etcd/member/wal" , "data-dir" : "sshot1.etcd" , "snap-dir" : "sshot1.etcd/member/snap" , "stack" : "go.etcd.io/etcd/etcdutl/v3/snapshot.(*v3Manager).Restore\n\t/tmp/etcd-release-3.5.2/etcd/release/etcd/etcdutl/snapshot/v3_snapshot.go:257\ngo.etcd.io/etcd/etcdutl/v3/etcdutl.SnapshotRestoreCommandFunc\n\t/tmp/etcd-release-3.5.2/etcd/release/etcd/etcdutl/etcdutl/snapshot_command.go:147\ngo.etcd.io/etcd/etcdctl/v3/ctlv3/command.snapshotRestoreCommandFunc\n\t/tmp/etcd-release-3.5.2/etcd/release/etcd/etcdctl/ctlv3/command/snapshot_command.go:128\ngithub.com/spf13/cobra.(*Command).execute\n\t/usr/local/google/home/siarkowicz/.gvm/pkgsets/go1.16.3/global/pkg/mod/github.com/spf13/cobra@v1.1.3/command.go:856\ngithub.com/spf13/cobra.(*Command).ExecuteC\n\t/usr/local/google/home/siarkowicz/.gvm/pkgsets/go1.16.3/global/pkg/mod/github.com/spf13/cobra@v1.1.3/command.go:960\ngithub.com/spf13/cobra.(*Command).Execute\n\t/usr/local/google/home/siarkowicz/.gvm/pkgsets/go1.16.3/global/pkg/mod/github.com/spf13/cobra@v1.1.3/command.go:897\ngo.etcd.io/etcd/etcdctl/v3/ctlv3.Start\n\t/tmp/etcd-release-3.5.2/etcd/release/etcd/etcdctl/ctlv3/ctl.go:107\ngo.etcd.io/etcd/etcdctl/v3/ctlv3.MustStart\n\t/tmp/etcd-release-3.5.2/etcd/release/etcd/etcdctl/ctlv3/ctl.go:111\nmain.main\n\t/tmp/etcd-release-3.5.2/etcd/release/etcd/etcdctl/main.go:59\nruntime.main\n\t/usr/local/google/home/siarkowicz/.gvm/gos/go1.16.3/src/runtime/proc.go:225" } 2022-02-24T13:03:33Z    info    membership/store.go:141 Trimming membership information from the backend... 2022-02-24T13:03:33Z    info    membership/cluster.go:421       added member    {"cluster-id" : "ef37ad9dc622a7c4" , "local-member-id" : "0" , "added-peer-id" : "8211f1d0f64f3269" , "added-peer-peer-urls" : ["http://127.0.0.1:12380" ]} 2022-02-24T13:03:33Z    info    membership/cluster.go:421       added member    {"cluster-id" : "ef37ad9dc622a7c4" , "local-member-id" : "0" , "added-peer-id" : "91bc3c398fb3c146" , "added-peer-peer-urls" : ["http://127.0.0.1:22380" ]} 2022-02-24T13:03:33Z    info    membership/cluster.go:421       added member    {"cluster-id" : "ef37ad9dc622a7c4" , "local-member-id" : "0" , "added-peer-id" : "fd422379fda50e48" , "added-peer-peer-urls" : ["http://127.0.0.1:32380" ]} 2022-02-24T13:03:33Z    info    snapshot/v3_snapshot.go:272     restored snapshot       {"path" : "test.db" , "wal-dir" : "sshot1.etcd/member/wal" , "data-dir" : "sshot1.etcd" , "snap-dir" : "sshot1.etcd/member/snap" } 
 
1 etcd --name sshot1 --listen-client-urls http://127.0.0.1:2379 --advertise-client-urls http://127.0.0.1:2379 --listen-peer-urls http://127.0.0.1:12380 & 
 
  查快快照 
命令语法:
1 SNAPSHOT STATUS <filename> 
 
示例:
1 2 3 4 $ etcdctl snapshot status test.db Deprecated: Use `etcdutl snapshot status` instead. dc4be536, 48, 43, 25 kB 
 
1 2 3 4 5 6 7 8 etcdctl snapshot status test.db -w table Deprecated: Use `etcdutl snapshot status` instead. +----------+----------+------------+------------+ |   HASH   | REVISION | TOTAL KEYS | TOTAL SIZE | +----------+----------+------------+------------+ | dc4be536 |       48 |         43 |      25 kB | +----------+----------+------------+------------+ 
 
  MOVE-LEADER 
命令语法:
 
示例:
1 2 3 4 5 6 7 8 9 10 11 12 $ etcdctl endpoint status --cluster http://etcd1:2379, ade526d28b1f92f7, 3.5.2, 25 kB, false , false , 2, 89, 89, http://etcd3:2379, bd388e7810915853, 3.5.2, 25 kB, true , false , 2, 89, 89, http://etcd2:2379, d282ac2ce600c1ce, 3.5.2, 25 kB, false , false , 2, 89, 89, $ etcdctl endpoint status --cluster | grep -m 1 "false"  | awk -F', '  '{print $2}'  ade526d28b1f92f7 $ etcdctl move-leader ade526d28b1f92f7 Error: no leader endpoint given at [127.0.0.1:2379] $ etcdctl --endpoints bd388e7810915853 move-leader ade526d28b1f92f7 
 
  降级命令 
降级在 v3.6 中是实验性质的特性,并不推荐在生产环境中使用。降级命令用于对集群进行降级。通常来说,由于集群版本机制的问题,etcd 成员是不能降级的。
在初始启动后,集群成员对集群版本达成一致。每隔 5 s,leader 会检查所有成员的版本并选择最小的版本。如果新加入的成员,其版本低于当前的集群版本,该成员无法加入集群,这样可以防止集群被降级。而降级命令则允许集群管理员强制对集群进行降级。
降级应该分阶段执行:
执行 etcdctl downgrade validate <TARGET_VERSION> 验证当前集群是否准备好进行降级 
etcdctl downgrade enable <TARGET_VERSION> 开始集群降级 
对于每个成员
通过检查其 log 中是否包含 The server is ready to downgrade 来确认成员准备好执行降级 
替换成员的二进制版本 
确认每个成员都正确启动并加入集群 
 
 
通过检查 leader log 中是否包含 The server is ready to downgrade 来确认降级是否成功 
 
  降级校验 
命令语法:
1 DOWNGRADE VALIDATE <TARGET_VERSION> 
 
  启动降级 
命令语法:
1 DOWNGRADE ENABLE <TARGET_VERSION> 
 
  取消降级 
命令语法:
1 DOWNGRADE CANCEL <TARGET_VERSION> 
 
  并发命令 
  LOCK 命令 
命令语法:
1 LOCK [options] <lockname> [command  arg1 arg2 ...] 
 
获取一个分布式锁,该锁的名称由 lockname 指定。一旦 lock 获取到后,该锁一直会被持有,直到 etcdctl 命令终止 
如果 lock 获取到,同时没有指定要执行的命令,那么会输出则会输出该 lock 的 KEY 
如果 lock 获取到,同时指定了要执行的命令,那么换将变量 ETCD_LOCK_KEY 和 ETCD_LOCK_KEY 会输出成 lock 的 key 和 revision 
 
常用选项:
示例:
1 2 3 4 5 $ etcdctl lock mylock mylock/12f77f2076d86fa0 $ etcdctl lock mylock etcdctl put foo bar OK 
 
注意事项:
只有当 LOCK 命令是通过信号终止,并释放 lock 之后,LOCK 命令的退出码才是 0 
如果 LOCK 命令是异常终止,或者无法让集群释放锁时,该 lock 会一直被占有,直到租约过期(60s) 
 
  ELECT 命令 
命令语法:
1 ELECT [options] <election-name> [proposal] 
 
ELECT 命令用于参加一个命名选举。通过在 ELECT 命令中提供一个 prososal 值,来表明本节点参与本选举 
如果只是想观察选举,不用提供 prososal 值,但是需要使用 listen 选项 
无论何时 leader 被选举后,它的 prososal 值都会被打印出来 
对于候选人,如果该节点赢得了选举,会输出对应的 key 信息。如果是观察选举,ELECT 命令会持续输出选举的结果 
 
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 $ etcdctl elect myelection etcd1 myelection/12f77f2076d86fb4 etcd1 $ etcdctl elect myelection etcd2 $ etcdctl elect myelection -l myelection/12f77f2076d86fb4 etcd1 $ etcdctl elect myelection etcd2 myelection/41ce7f2076d86923 etcd2 $ etcdctl elect myelection -l myelection/12f77f2076d86fb4 etcd1 myelection/41ce7f2076d86923 etcd2 
 
注意事项:
只有当 ELECT 命令是通过信号终止,并释放其候选人/领导者身份的时候,ELECT 命令的退出码才是 0 
如果候选人是异常终止,那么该选举过程会一直持续,直到默认租约过期(60s) 
 
  认证命令 
  开启/关闭认证 
命令语法:
1 AUTH <enable  or disable > 
 
用于开启或关闭 etcd 集群的认证机制。当开启 etcd 的认证机制的时候,etcd 会对所有请求进行认证检查 
对应的 RPC:AuthEnable/AuthDisable 
 
  添加角色 
命令语法:
 
创建一个角色 
对应的 RPC 方法:RoleAdd 
 
示例:
1 2 $ etcdctl role add test  Role test  created 
 
  获取角色 
命令语法:
 
获取详细的角色信息 
对应的 RPC 方法 RoleGet 
 
示例:
1 2 3 4 $ etcdctl role get test  Role test  KV Read: KV Write: 
 
  删除角色 
命令语法:
 
删除指定角色 
对应的 RPC 方法: RoleDelete 
 
示例:
1 2 $ etcdctl role delete test  Role test  deleted 
 
  列出角色 
命令语法:
 
列出 etcd 中所有的角色 
对应的 RPC 方法:RoleList 
 
示例:
1 2 $ etcdctl role list test 
 
  角色授权 
命令语法:
1 ROLE GRANT-PERMISSION [options] <role name> <permission type > <key> [endkey] 
 
针对某个 key 或 key 范围,为 role 设置权限 
对应的 RPC 方法为 RoleGrantPermission 
 
常用选项:
--from-key:为大于等于指定 key 的所有 key(通过字节比较排序)进行授权 
--preifx:使用前缀匹配 
 
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 $ etcdctl role grant-permission test  readwrite test_key Role test  updated $ etcdctl role get test  Role test  KV Read:         test_key KV Write:         test_key $ etcdctl role grant-permission test  read  foo/ --prefix Role test  updated $ etcdctl role get test  Role test  KV Read:         [foo/, foo0) (prefix foo/)         test_key KV Write:         test_key 
 
  取消授权 
命令语法:
1 ROLE REVOKE-PERMISSION <role name> <permission type > <key> [endkey] 
 
针对某个 key 或者 key 范围,为 role 撤销权限 
对应的 RPC 方法为 RoleRevokePermission 
 
常用选项:
--from-key:为大于等于指定 key 的所有 key(通过字节比较排序)取消授权 
--preifx:使用前缀匹配 
 
示例:
1 2 3 4 5 6 7 8 9 10 $ etcdctl role revoke-permission test  test_key Permission of key test_key is revoked from role test  $ etcdctl role revoke-permission test  --prefix foo/ Permission of range [foo/, foo0) is revoked from role test  $ etcdctl role get test  Role test  KV Read: KV Write: 
 
  添加用户 
命令语法:
1 USER ADD <user name or user:password> [options] 
 
添加一个用户 
对应的 RPC 方法为:UserAdd 
 
常用选项:
--interactive:交互模式,从标准输入中读取密码 
 
示例:
1 2 3 4 etcdctl user add test_user Password of test_user: Type password of test_user again for  confirmation: User test_user created 
 
  获取用户 
命令语法:
1 USER GET <user name> [options] 
 
获取指定用户的信息 
对应的RPC 方法 UserGet 
 
常用选项:
示例:
1 2 etcdctl user get test_user --detail User: test_user 
 
  删除用户 
命令语法:
 
删除指定的用户 
对应的 RPC 方法为 UserDelete 
 
示例:
1 2 $ etcdctl user delete test_user User test_user deleted 
 
  列出用户 
命令语法:
 
示例:
1 2 $ etcdctl user list test_user 
 
  设置密码 
命令语法:
1 USER PASSWD <user name> [options] 
 
修改用户的密码 
对应的 RPC 方法:UserChangePassword 
 
常用选项:
--interactive:交互模式,从标准输入中读取密码 
 
示例:
1 2 3 4 $ etcdctl user passwd test_user Password of test_user: Type password of test_user again for  confirmation: Password updated 
 
  设置用户角色 
命令语法:
1 USER GRANT-ROLE <user name> <role name> 
 
为 user 指定角色 
对应的 RPC 方法:UserGrantRole 
 
示例:
1 2 $ etcdctl user grant-role test_user test  Role test  is granted to user test_user 
 
  取消用户角色 
命令语法:
1 USER REVOKE-ROLE <user name> <role name> 
 
撤销用户的角色 
对应的 RPC 方法:UserRevokeRole 
 
示例:
1 2 $ etcdctl user revoke-role test_user test  Role test  is revoked from user test_user 
 
  工具命令 
  make-mirror 
命令语法:
1 MAKE-MIRROR [options] <destination> 
 
将 etcd 集群中的某些 key 映射到另一个 etcd 集群中 
 
常用选项
--dest-cacert <cacert>:目的集群的 TLS cacert 文件 
--dest-cacert <cert>:目的集群的 TLS cert 文件 
--dest-key <key>:目的集群的 TLS key 文件 
--prefix:按前缀匹配 
dest-prefix:指定在目标集群中的前缀 
no-dest-prefix:在目标集群的 root 下进行 mirror 
dest-insecure-transport:关闭传输层安全 
 
  版本 
命令语法:
 
示例:
1 2 3 $ etcdctl version etcdctl version: 3.5.2 API version: 3.5 
 
  CHECK 
用于检查 etcd 集群中的各个信息。
  性能检查 
命令语法:
 
用于检查 etcd 集群的性能信息。 
对应的 RPC 方法:CheckPerf 
 
常用选项:
--load:性能检查的负载模型,支持有:s(small), m(medium)、l(large)、xl(xlarge) 
--prefix:性能测试使用的 key 前缀 
--auto-compact:性能测试后,自动进行 compact 
auto-defrag:性能测试后自动进行 defragment 
 
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 $ etcdctl check perf --load="s"   60 / 60 Booooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo! 100.00% 1m0s PASS: Throughput is 149 writes/s PASS: Slowest request took 0.261242s PASS: Stddev is 0.013076s PASS $ etcdctl check perf --load="l"  FAIL: too many errors FAIL: ERROR(etcdserver: request timed out) -> 287 FAIL: Throughput too low: 297 writes/s Slowest request took too long: 8.325122s Stddev too high: 1.062989s FAIL 
 
  数据规模检查 
命令语法:
1 CHECK DATASCALE [options] 
 
检查在一个指定的 endpoint server 上,不同负载情况下保存数据所需要使用的内存 
对应的 RPC 方法 CheckDatascale 
 
常用选项:
--load:所使用的负载模型,支持有:s(small), m(medium)、l(large)、xl(xlarge) 
--prefix:所使用的 key 前缀 
--auto-compact:性能测试后,自动进行 compact 
auto-defrag:性能测试后自动进行 defragment 
 
示例:
1 2 3 4 $ etcdctl check datascale --load="s"  Start data scale check for  work load [10000 key-value pairs, 1024 bytes per key-value, 50 concurrent clients].  10000 / 10000 Boooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo! 100.00% 14s PASS: Approximate system memory used : 91.16 MB. 
 
  Reference