【ETCD】ETCD常用命令

ETCD常用命令

文章目录

资源列表

操作系统 配置 主机名 IP
openEuler 2C4G etcd1 192.168.93.101
openEuler 2C4G etcd2 192.168.93.102
openEuler 2C4G etcd3 192.168.93.103

基础环境

  • 关闭防火墙
bash 复制代码
systemctl stop firewalld
systemctl disable firewalld
  • 关闭内核安全机制
bash 复制代码
setenforce 0
sed -i "s/^SELINUX=.*/SELINUX=disabled/g" /etc/selinux/config
  • 修改主机名
bash 复制代码
hostnamectl set-hostname etcd1
hostnamectl set-hostname etcd2
hostnamectl set-hostname etcd3

一、集群管理命令

  • etcd是一个命令行的客户端,它提供了一些命令,可以方便我们在对服务进行测试或者手动修改数据库内容。etcd命令基本用法如下所示:
bash 复制代码
etcdctl [global options] command [command options] [args...]
  • 具体的命令选项可以通过etcd command --help 来获取相关帮助

二、环境变量

  • 如果遇到使用了TLS加密的集群,通常每条指令都需要指定证书路径和etcd节点地址,可以把相关命令行参数添加在环境变量中,在.bashrc添加以下内容。
  • 本次实验不采用TLS
bash 复制代码
[root@etcd1 ~]# cat ~/.bashrc 
HOST_1=https://192.168.93.101:2379
HOST_2=https://192.168.93.102:2379
HOST_3=https://192.168.93.103:2379
ENDPOINTS=${HOST_1},${HOST_2},${HOST_3}
# 如果需要使用原生命令,在命令开头加一个\ 例如:\etcdctl command
alias etcdctl="etcdctl --endpoints=${ENDPOINTS} --cacert=/root/cfssl/etcd/ca.pem --cert=/root/cfssl/etcd/client.pem --key=/root/cfssl/etcd/client-key.pem"
alias etcdctljson="etcdctl --endpoints=${ENDPOINTS} --cacert=/root/cfssl/etcd/ca.pem --cert=/root/cfssl/etcd/client.pem --key=/root/cfssl/etcd/client-key.pem --write-out=json"
alias etcdctltable="etcdctl --endpoints=${ENDPOINTS} --cacert=/root/cfssl/etcd/ca.pem --cert=/root/cfssl/etcd/client.pem --key=/root/cfssl/etcd/client-key.pem --write-out=table"

三、ETCD常用命令

  • etcd的常用命令有很多,但不限于获取、删除、查看。

3.1、查看etcd版本

bash 复制代码
[root@etcd1 ~]# etcdctl version
etcdctl version: 3.4.23
API version: 3.4

3.2、查看etcd结群节点信息

bash 复制代码
[root@etcd1 ~]# etcdctl member list -w table
+------------------+---------+-------+----------------------------+----------------------------+------------+
|        ID        | STATUS  | NAME  |         PEER ADDRS         |        CLIENT ADDRS        | IS LEARNER |
+------------------+---------+-------+----------------------------+----------------------------+------------+
| 3d33f92152eaee46 | started | etcd3 | http://192.168.93.103:2380 | http://192.168.93.103:2379 |      false |
| 5abc4e842d3ab1d6 | started | etcd2 | http://192.168.93.102:2380 | http://192.168.93.102:2379 |      false |
| f416c4d7e7853c3a | started | etcd1 | http://192.168.93.101:2380 | http://192.168.93.101:2379 |      false |
+------------------+---------+-------+----------------------------+----------------------------+------------+

3.3、查看集群健康状态

bash 复制代码
[root@etcd1 ~]# cat ~/.bashrc 
HOST_1=http://192.168.93.101:2379
HOST_2=http://192.168.93.102:2379
HOST_3=http://192.168.93.103:2379
ENDPOINTS=${HOST_1},${HOST_2},${HOST_3}
# 如果需要使用原生命令,在命令开头加一个\ 例如:\etcdctl command
alias etcdctl="etcdctl --endpoints=${ENDPOINTS}"
bash 复制代码
[root@etcd1 ~]# etcdctl endpoint status -w table
+----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
|          ENDPOINT          |        ID        | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS |
+----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| http://192.168.93.101:2379 | f416c4d7e7853c3a |  3.4.23 |   20 kB |      true |      false |         2 |          8 |                  8 |        |
| http://192.168.93.102:2379 | 5abc4e842d3ab1d6 |  3.4.23 |   20 kB |     false |      false |         2 |          8 |                  8 |        |
| http://192.168.93.103:2379 | 3d33f92152eaee46 |  3.4.23 |   20 kB |     false |      false |         2 |          8 |                  8 |        |
+----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
bash 复制代码
[root@etcd1 ~]# etcdctl endpoint health -w table
+----------------------------+--------+------------+-------+
|          ENDPOINT          | HEALTH |    TOOK    | ERROR |
+----------------------------+--------+------------+-------+
| http://192.168.93.101:2379 |   true | 1.591124ms |       |
| http://192.168.93.103:2379 |   true | 1.987456ms |       |
| http://192.168.93.102:2379 |   true | 8.935062ms |       |
+----------------------------+--------+------------+-------+

3.4、查看告警事件

  • 如果内部出现了问题,会触发告警,可以通过命令查看告警引起的原因,命令如下所示:
bash 复制代码
etcdctl alarm <subcommand> [flags]
  • 常用的子命令主要有两个:
bash 复制代码
# 查看所有告警
etcdctl alarm list
# 解除所有告警
etcdctl alarm disarm

3.5、添加成员

  • 当集群部署完成后,后续可能需要进行节点扩缩容,就可以使用member命令管理节点。先查看当前集群信息。
bash 复制代码
[root@etcd1 ~]# etcdctl endpoint status --cluster -w table
+----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
|          ENDPOINT          |        ID        | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS |
+----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| http://192.168.93.103:2379 | 3d33f92152eaee46 |  3.4.23 |   20 kB |     false |      false |         2 |          8 |                  8 |        |
| http://192.168.93.102:2379 | 5abc4e842d3ab1d6 |  3.4.23 |   20 kB |     false |      false |         2 |          8 |                  8 |        |
| http://192.168.93.101:2379 | f416c4d7e7853c3a |  3.4.23 |   20 kB |      true |      false |         2 |          8 |                  8 |        |
+----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
  • 在启动新的etcd节点前,先向etcd集群声明添加节点的peer-urls和节点名称
bash 复制代码
[root@etcd1 ~]# etcdctl member add etcd4 --peer-urls=http://192.168.93.104:2380
Member  dd2947c31edb0d2 added to cluster b59d820ff8caf3f4

ETCD_NAME="etcd4"
ETCD_INITIAL_CLUSTER="etcd4=http://192.168.93.104:2380,etcd3=http://192.168.93.103:2380,etcd2=http://192.168.93.102:2380,etcd1=http://192.168.93.101:2380"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.168.93.104:2380"
ETCD_INITIAL_CLUSTER_STATE="existing"
  • 接下来新开启一台etcd服务器,IP地址为192.168.93.104,节点名称是etcd4.
bash 复制代码
# 以下是 etcd4 的配置文件
# 注意此时 etcd4 要加入的集群是一个已经存在的集群, 所以initial-cluster-state 字段需要设置为 existing 表示加入现有集群
[root@etcd5 ~]# cat /etc/etcd/etcd.conf
# 节点名称
name: "etcd4"
# 数据存储目录
data-dir: "/data/etcd"
# 对外公告的该节点客户端监听地址,这个值会告诉集群中其他节点
advertise-client-urls: "http://192.168.93.104:2379"
# 监听客户端请求的地址列表
listen-client-urls: "http://192.168.93.104:2379,http://127.0.0.1:2379"
# 监听URL,用于节点之间通信监听地址
listen-peer-urls: "http://192.168.93.104:2380"
# 服务端之间通讯使用的地址列表,该节点同伴监听地址,这个值会告诉集群中其他节点
initial-advertise-peer-urls: "http://192.168.93.104:2380"
# etcd启动时,etcd集群的节点地址列表
initial-cluster: "etcd1=http://192.168.93.101:2380,etcd2=http://192.168.93.102:2380,etcd3=http://192.168.93.103:2380,etcd4=http://192.168.93.104:2380"
# etcd集群的初始集群令牌
initial-cluster-token: 'etcd-cluster'
# etcd集群初始化的状态,new代表新建集群,existing表示加入现有集群
initial-cluster-state: 'existing'
bash 复制代码
# 启动 etcd4
[root@etcd4 ~]# systemctl start etcd


# etcd4 启动后, 查看集群节点信息
[root@etcd1 ~]# etcdctl endpoint status --cluster -w table
+----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
|          ENDPOINT          |        ID        | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS |
+----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| http://192.168.93.104:2379 |  dd2947c31edb0d2 |  3.4.23 |   20 kB |     false |      false |         2 |         12 |                 12 |        |
| http://192.168.93.103:2379 | 3d33f92152eaee46 |  3.4.23 |   20 kB |     false |      false |         2 |         12 |                 12 |        |
| http://192.168.93.102:2379 | 5abc4e842d3ab1d6 |  3.4.23 |   20 kB |     false |      false |         2 |         12 |                 12 |        |
| http://192.168.93.101:2379 | f416c4d7e7853c3a |  3.4.23 |   20 kB |      true |      false |         2 |         12 |                 12 |        |
+----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+

3.6、更新成员

  • 当 etcd 节点故障,启动 etcd 时报错member count is unqueal。如果有保留的数据目录吓下得文件时,可以通过使用member update命令,在保留 etcd 数据得情况下初始化集群数据,重新构建一个新的 etcd 集群节点。
  • 模拟192.168.93.101:2380节点故障,但数据目录文件有备份,启动一个新得节点,地址为:192.168.93.105:2380。
bash 复制代码
# 停用旧节点
[root@etcd4 ~]# systemctl stop etcd.service


# 把 etcd4 得数据 scp 到 etcd5 节点
[root@etcd4 ~]# scp -r /data/ root@192.168.93.105:/
bash 复制代码
# 更新节点地址
[root@etcd5 ~]# cat /etc/etcd/etcd.conf 
# 节点名称
name: "etcd4"
# 数据存储目录
data-dir: "/data/etcd"
# 对外公告的该节点客户端监听地址,这个值会告诉集群中其他节点
advertise-client-urls: "http://192.168.93.105:2379"
# 监听客户端请求的地址列表
listen-client-urls: "http://192.168.93.105:2379,http://127.0.0.1:2379"
# 监听URL,用于节点之间通信监听地址
listen-peer-urls: "http://192.168.93.105:2380"
# 服务端之间通讯使用的地址列表,该节点同伴监听地址,这个值会告诉集群中其他节点
initial-advertise-peer-urls: "http://192.168.93.105:2380"
# etcd启动时,etcd集群的节点地址列表
initial-cluster: "etcd1=http://192.168.93.101:2380,etcd2=http://192.168.93.102:2380,etcd3=http://192.168.93.103:2380,etcd4=http://192.168.93.105:2380"
# etcd集群的初始集群令牌
initial-cluster-token: 'etcd-cluster'
# etcd集群初始化的状态,new代表新建集群,existing表示加入现有集群
initial-cluster-state: 'existing'
bash 复制代码
# 启动新节点
[root@etcd5 ~]# systemctl daemon-reload 
[root@etcd5 ~]# systemctl start etcd.service
  • 执行更新member操作,指定新的节点地址
bash 复制代码
# ID 为 104 
[root@etcd1 ~]# etcdctl member update dd2947c31edb0d2 --peer-urls=http://192.168.93.105:2380
Member  dd2947c31edb0d2 updated in cluster b59d820ff8caf3f4
  • 查看集群节点信息,节点信息更新完成。
bash 复制代码
[root@etcd1 ~]# etcdctl endpoint status --cluster -w table
+----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
|          ENDPOINT          |        ID        | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS |
+----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| http://192.168.93.105:2379 |  dd2947c31edb0d2 |  3.4.23 |   20 kB |     false |      false |         2 |         14 |                 14 |        |
| http://192.168.93.103:2379 | 3d33f92152eaee46 |  3.4.23 |   20 kB |     false |      false |         2 |         14 |                 14 |        |
| http://192.168.93.102:2379 | 5abc4e842d3ab1d6 |  3.4.23 |   20 kB |     false |      false |         2 |         14 |                 14 |        |
| http://192.168.93.101:2379 | f416c4d7e7853c3a |  3.4.23 |   20 kB |      true |      false |         2 |         14 |                 14 |        |
+----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+

3.7、删除成员

  • 主要用法如下所示:
bash 复制代码
etcdctl member remove <memberID> [flags]
  • 模拟192.168.93.105:2380节点下线操作
bash 复制代码
# 停止 etcd 5的节点
[root@etcd5 ~]# systemctl stop etcd.service
  • 执行删除操作
bash 复制代码
# dd2947c31edb0d2 为 etcd5 的 ID
[root@etcd1 ~]# etcdctl member remove dd2947c31edb0d2
Member  dd2947c31edb0d2 removed from cluster b59d820ff8caf3f4
[root@etcd1 ~]# etcdctl endpoint status --cluster -w table
+----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
|          ENDPOINT          |        ID        | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS |
+----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| http://192.168.93.103:2379 | 3d33f92152eaee46 |  3.4.23 |   20 kB |     false |      false |         4 |         21 |                 21 |        |
| http://192.168.93.102:2379 | 5abc4e842d3ab1d6 |  3.4.23 |   20 kB |     false |      false |         4 |         21 |                 21 |        |
| http://192.168.93.101:2379 | f416c4d7e7853c3a |  3.4.23 |   20 kB |      true |      false |         4 |         21 |                 21 |        |
+----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+

四、数据库操作命令

4.1、增加(put)

  • 添加一个键值对,基本用法如下所示
bash 复制代码
etcdctl put [options] <key> <value> [flags]
  • 常用参数如下所示:
参数 功能描述
--perv-kv 输出修改前的键值
  • 注意事项:
    • 其中value接受从stdin的输入内容
    • 如果value是以横线-开始,将会被视为flag,如果不希望出现这种情况,可以使用两个横线代替--
    • 若键已经存在,则进行更新并覆盖原有值,若不存在,则进行添加
bash 复制代码
[root@etcd1 ~]# etcdctl put name wzh
OK
[root@etcd1 ~]# etcdctl put location -- -shanghai
OK
[root@etcd1 ~]# etcdctl put foo1 bar1
OK
[root@etcd1 ~]# etcdctl put foo2 bar2
OK
[root@etcd1 ~]# etcdctl put foo3 bar3
OK

4.2、查询(get)

  • 查询键值对,基本用法如下所示
bash 复制代码
etcdctl get [options] <key> [range_end] [flags]
  • 常用参数如下所示
参数 功能描述
--hex 以十六进制形式输出
--limit number 设置是输出结果的最大值
--prefix 根据prefix进行匹配key
--order 对输出结果进行排序,ASCEND或DESCEND
--sort-by 按给定字段排序,CREATE,KEYMODIFY,VALUE,VERSION
--print-value-only 仅输出value值
--from-key 按byte进行比较,获取大于等于指定key的结果
--keys-only 仅获取keys
  • 示例
bash 复制代码
# 获取键值
[root@etcd1 ~]# etcdctl get name
name
wzh


# 只获取值
[root@etcd1 ~]# etcdctl get location --print-value-only
-shanghai


# 批量取从 foo1-foo3 的值, 不包括 foo3
[root@etcd1 ~]# etcdctl get foo1 foo3 --print-value-only
bar1
bar2


# 批量获取前缀为 foo 的值
[root@etcd1 ~]# etcdctl get --prefix foo --print-value-only
bar1
bar2
bar3


# 批量获取符合前缀的两个值
[root@etcd1 ~]# etcdctl get --prefix --limit=2 foo --print-value-only
bar1
bar2


# 批量获取前缀为 foo 的值, 并排序
[root@etcd1 ~]# etcdctl get --prefix foo --print-value-only --order DESCEND
bar3
bar2
bar1

4.3、删除(del)

  • 删除键值,基本用法如下所示
bash 复制代码
etcdctl del [options] <key> [range_end] [flags]
  • 常用参数如下所示
参数 功能描述
--prefix 根据prefix进行匹配删除
--prev-kv 输出删除的键值
--form-key 按byte进行比较,删除大于指定key的结果
  • 示例
bash 复制代码
# 删除name的键值
[root@etcd1 ~]# etcdctl del name
1


# 删除从foo1到foo3且不包含foo3的键值
[root@etcd1 ~]# etcdctl del foo1 foo3
2


# 删除前缀为foo的所有键值
[root@etcd1 ~]# etcdctl del --prefix foo
1

4.4、更新(put覆盖)

  • 若键值已经存在,则进行更新并覆盖原有值,若不存在,则进行添加

4.5、查询键历史记录查询

  • etcd在每次键值变更时,都会记录变更信息,便于我们查看键变更记录

4.6、监听命令

  • watch是监听或前缀发生改变的事件流,只要用法如下所示:
bash 复制代码
etcdctl watch [options] [key or prefix] [range_end] [--] [exec-command arg1 arg2 ...] [flags]
  • 示例如下所示:
bash 复制代码
# 对某个 key 监听操作, 当 key1 发生改变时, 会返回最新值
[root@etcd1 ~]# etcdctl watch name


# 监听 key 前缀
[root@etcd1 ~]# etcdctl watch name --prefix


# 监听到改变后执行相关操作
[root@etcd1 ~]# etcdctl watch name -- etcdctl get age

4.6、监听单个建

bash 复制代码
# 启动监听命令
[root@etcd1 ~]# etcdctl watch foo

# 另一个控制台执行新增命令
[root@etcd1 ~]# etcdctl put foo bar
OK

# 观察控制台监听输出
[root@etcd1 ~]# etcdctl watch foo
PUT
foo
bar

# 另一个控制台执行删除命令
[root@etcd1 ~]# etcdctl del foo
1

# 观察控制台监听输出
[root@etcd1 ~]# etcdctl watch foo
PUT
foo
bar
DELETE
foo

4.7、同时监听多个建

bash 复制代码
# 监听前缀为 foo 的建
[root@etcd1 ~]# etcdctl watch --prefix foo

# 另一个控制台执行操作
[root@etcd1 ~]# etcdctl put foo1 bar1
OK
[root@etcd1 ~]# etcdctl put foo2 bar2
OK
[root@etcd1 ~]# etcdctl del foo1
1

# 观察控制台输出
[root@etcd1 ~]# etcdctl watch --prefix foo
PUT
foo1
bar1
PUT
foo2
bar2
DELETE
foo1

# 监听指定的多个建
[root@etcd1 ~]# etcdctl watch -i 
watch name
watch location

# 另一个控制台执行操作
[root@etcd1 ~]# etcdctl put name wzh
OK
[root@etcd1 ~]# etcdctl del name
1
[root@etcd1 ~]# etcdctl put location shanghai
OK

# 观察控制台输出
[root@etcd1 ~]# etcdctl watch -i 
watch name
watch location
PUT
name
wzh
DELETE
name

PUT
location
shanghai

五、租约命令

  • 租约具有生命周期,需要为租约授予一个TTL(生命周期),将租约绑定到key上,则key的生命周期与租约一直,可续约,可撤销租约,类似于redis为建设置过期时间。其主要用法如下所示:
bash 复制代码
etcdctl lease <subcommand> [flags]

5.1、添加租约

  • 主要用法如下所示:
bash 复制代码
etcdctl lease grant <ttl> [flags]
  • 示例
bash 复制代码
# 设置 60 秒后过期时间
[root@etcd1 ~]# etcdctl lease grant 60
lease 3c3a9a4cb7661512 granted with TTL(60s)

# 把 foo 和租约绑定, 设置为60秒后过期
[root@etcd1 ~]# etcdctl put --lease=3c3a9a4cb7661512 foo bar
OK

# 租约期内查询键值
[root@etcd1 ~]# etcdctl get foo
foo
bar

# 租约期外查询键值(没有任何回显)
[root@etcd1 ~]# etcdctl get foo

5.2、查看租约

  • 查看租约信息,以便租约或查看租约是否仍然存在或者已过期。
  • 查看租约详情主要用法如下所示:
bash 复制代码
etcdctl lease timetolive <leaseID> [options] [flags]
  • 示例
bash 复制代码
# 添加一个 50 秒的租约
[root@etcd1 ~]# etcdctl lease grant 50
lease 3c3a9a4cb7661518 granted with TTL(50s)

# 将 name 键绑定到 3c3a9a4cb7661518 租约上
[root@etcd1 ~]# etcdctl put --lease=3c3a9a4cb7661518 name wzh
OK

# 查看所有租约列表
[root@etcd1 ~]# etcdctl lease list
found 1 leases
3c3a9a4cb7661518

# 查看租约详情, remaining: 剩余时间 keys: 获取租约绑定的 key
[root@etcd1 ~]# etcdctl lease timetolive --keys 3c3a9a4cb7661518
lease 3c3a9a4cb7661518 granted with TTL(50s), remaining(16s), attached keys([name])

5.3、租约续约

  • 通过刷新TTL值来保持续约的有效,使其不会过期。
  • 示例如下所示:
bash 复制代码
etcdctl lease keep-alive [options] <leaseID> [flags]
  • 示例如下所示
bash 复制代码
# 设置 60 秒后过期租约
[root@etcd1 ~]# etcdctl lease grant 60
lease 3c3a9a4cb766151c granted with TTL(60s)

# 把 name 和租约绑定, 设置成功后 60 秒后过期
[root@etcd1 ~]# etcdctl put --lease=3c3a9a4cb766151c name wzh
OK

# 自动定时执行续约, 续约成功后每次租约为 60 秒
[root@etcd1 ~]# etcdctl lease keep-alive 3c3a9a4cb766151c
lease 3c3a9a4cb766151c keepalived with TTL(60)
lease 3c3a9a4cb766151c keepalived with TTL(60)
......

5.4、删除租约

  • 通过租约ID撤销租约,撤销租约将删除其所有绑定的key。

  • 主要用法如下所示:

bash 复制代码
etcdctl lease revoke <leaseID> [flags]
  • 示例如下所示
bash 复制代码
# 设置 600 秒后过期租约
[root@etcd1 ~]# etcdctl lease grant 600
lease 3c3a9a4cb766151f granted with TTL(600s)

# 把 foo 和租约绑定, 600 秒后过期
[root@etcd1 ~]# etcdctl put --lease=3c3a9a4cb766151f foo bar
OK

# 查看租约详情
[root@etcd1 ~]# etcdctl lease timetolive --keys 3c3a9a4cb766151f
lease 3c3a9a4cb766151f granted with TTL(600s), remaining(574s), attached keys([foo])

# 删除租约
[root@etcd1 ~]# etcdctl lease revoke 3c3a9a4cb766151f
lease 3c3a9a4cb766151f revoked

# 查案续约详情
[root@etcd1 ~]# etcdctl lease timetolive --keys 3c3a9a4cb766151f
lease 3c3a9a4cb766151f already expired

# 获取键值(无任何返回)
[root@etcd1 ~]# etcdctl get foo

5.5、多key同一租约

  • 一个租约支持绑定多个key
bash 复制代码
[root@etcd1 ~]# etcdctl lease grant 60
lease 3c3a9a4cb7661525 granted with TTL(60s)
[root@etcd1 ~]# etcdctl put --lease=3c3a9a4cb7661525 foo1 bar1
OK
[root@etcd1 ~]# etcdctl put --lease=3c3a9a4cb7661525 foo2 bar2
OK
[root@etcd1 ~]# etcdctl lease timetolive --keys 3c3a9a4cb7661525
lease 3c3a9a4cb7661525 granted with TTL(60s), remaining(29s), attached keys([foo1 foo2])
  • 租约过期后,所有key值都会被删除,因此:

    • 当租约只绑定一个key时,想删除这个key,最好的办法是撤销它的租约,而不是直接删除这个key。
    • 当租约没有绑定key时,应主动把它撤销掉,单纯删除key后,续约操作持续进行,会造成内存泄漏。
  • 直接删除key的演示:

bash 复制代码
# 设置租约并绑定 zoo1
[root@etcd1 ~]# etcdctl lease grant 60
lease 3c3a9a4cb766152a granted with TTL(60s)
[root@etcd1 ~]# etcdctl --lease=3c3a9a4cb766152a put zoo1 val1
OK
[root@etcd1 ~]# etcdctl del zoo1
1

# 单纯删除 key 后, 续约操作持续进行, 会造成内存泄漏
[root@etcd1 ~]# etcdctl lease keep-alive 3c3a9a4cb766152a
lease 3c3a9a4cb766152a keepalived with TTL(60)
lease 3c3a9a4cb766152a keepalived with TTL(60)
......
  • 撤销key的续约演示
bash 复制代码
# 设置租约并绑定 zoo1
[root@etcd1 ~]# etcdctl lease grant 60
lease 3c3a9a4cb766152e granted with TTL(60s)
[root@etcd1 ~]# etcdctl --lease=3c3a9a4cb766152e put zoo1 val1
OK

# 续约
[root@etcd1 ~]# etcdctl lease keep-alive 3c3a9a4cb766152e
lease 3c3a9a4cb766152e keepalived with TTL(60)
lease 3c3a9a4cb766152e expired or revoked.

# 另一个控制台执行
[root@etcd1 ~]# etcdctl lease revoke 3c3a9a4cb766152e
lease 3c3a9a4cb766152e revoked

# 续约撤销并退出
[root@etcd1 ~]# etcdctl lease keep-alive 3c3a9a4cb766152e
lease 3c3a9a4cb766152e keepalived with TTL(60)
lease 3c3a9a4cb766152e expired or revoked.

# 返回为空
[root@etcd1 ~]# etcdctl get zoo1

六、备份恢复命令

  • 主要用于管理节点的快照,其主要用法如下所示:
bash 复制代码
etcdctl snapshot <subcommand> [flags]

6.1、生成快照

  • 其主要用法如下所示:
bash 复制代码
etcdctl snapshot save <filename> [flags]
  • 示例如下所示:
bash 复制代码
etcdctl snapshot save etcd-snapshot.db

6.2、查看快照

  • 其主要用法如下所示:
bash 复制代码
etcdctl snapshot status <filename> [flags]
  • 示例如下所示:
bash 复制代码
etcdctl snapshot status etcd-snapshot.db -w table

6.3、恢复快照

  • 其主要用法如下所示:
bash 复制代码
etcdctl snapshot restore <filename> [options] [flags]

6.4、备份恢复演示

  • 新建一个名为name 的key
bash 复制代码
[root@etcd1 ~]# etcdctl put name wzh
OK
[root@etcd1 ~]# etcdctl get name
name
wzh
[root@etcd1 ~]# etcdctl endpoint status -w table
+----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
|          ENDPOINT          |        ID        | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS |
+----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| http://192.168.93.101:2379 | f416c4d7e7853c3a |  3.4.23 |   33 kB |      true |      false |         2 |         45 |                 45 |        |
| http://192.168.93.102:2379 | 5abc4e842d3ab1d6 |  3.4.23 |   25 kB |     false |      false |         2 |         45 |                 45 |        |
| http://192.168.93.103:2379 | 3d33f92152eaee46 |  3.4.23 |   29 kB |     false |      false |         2 |         45 |                 45 |        |
+----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
  • 生成快照,创建名为snap.db的备份文件
bash 复制代码
[root@etcd1 ~]# etcdctl snapshot save snap.db --endpoints=http://192.168.93.101:2379
{"level":"info","ts":1762233834.5750756,"caller":"snapshot/v3_snapshot.go:119","msg":"created temporary db file","path":"snap.db.part"}
{"level":"info","ts":"2025-11-04T13:23:54.575+0800","caller":"clientv3/maintenance.go:200","msg":"opened snapshot stream; downloading"}
{"level":"info","ts":1762233834.5759904,"caller":"snapshot/v3_snapshot.go:127","msg":"fetching snapshot","endpoint":"http://192.168.93.101:2379"}
{"level":"info","ts":"2025-11-04T13:23:54.576+0800","caller":"clientv3/maintenance.go:208","msg":"completed snapshot read; closing"}
{"level":"info","ts":1762233834.5780404,"caller":"snapshot/v3_snapshot.go:142","msg":"fetched snapshot","endpoint":"http://192.168.93.101:2379","size":"33 kB","took":0.002909912}
{"level":"info","ts":1762233834.57811,"caller":"snapshot/v3_snapshot.go:152","msg":"saved","path":"snap.db"}
  • 查看备份文件详情
bash 复制代码
[root@etcd1 ~]# ls -lh snap.db 
-rw------- 1 root root 33K 11月  4 13:23 snap.db

[root@etcd1 ~]# etcdctl snapshot status snap.db -w table
+--------+----------+------------+------------+
|  HASH  | REVISION | TOTAL KEYS | TOTAL SIZE |
+--------+----------+------------+------------+
| 28ac4c |       30 |         36 |      33 kB |
+--------+----------+------------+------------+
  • 把快照文件传到其他节点
bash 复制代码
[root@etcd1 ~]# scp snap.db root@192.168.93.102:/root
[root@etcd1 ~]# scp snap.db root@192.168.93.103:/root
  • 停止所有节点的etcd服务,并删除数据目录
bash 复制代码
# 所有节点都要执行
systemctl stop etcd

# 删除数据
rm -rf /data/etcd/
  • 在所有节点上开始恢复数据
bash 复制代码
# etcd1
[root@etcd1 ~]# etcdctl snapshot restore snap.db --name=etcd1 --data-dir=/data/etcd --initial-cluster=etcd1=http://192.168.93.101:2380,etcd2=http://192.168.93.102:2380,etcd3=http://192.168.93.103:2380 --initial-advertise-peer-urls=http://192.168.93.101:2380
{"level":"info","ts":1762234209.7733314,"caller":"snapshot/v3_snapshot.go:296","msg":"restoring snapshot","path":"snap.db","wal-dir":"/data/etcd/member/wal","data-dir":"/data/etcd","snap-dir":"/data/etcd/member/snap"}
{"level":"info","ts":1762234209.7786083,"caller":"membership/cluster.go:392","msg":"added member","cluster-id":"b59d820ff8caf3f4","local-member-id":"0","added-peer-id":"3d33f92152eaee46","added-peer-peer-urls":["http://192.168.93.103:2380"]}
{"level":"info","ts":1762234209.778708,"caller":"membership/cluster.go:392","msg":"added member","cluster-id":"b59d820ff8caf3f4","local-member-id":"0","added-peer-id":"5abc4e842d3ab1d6","added-peer-peer-urls":["http://192.168.93.102:2380"]}
{"level":"info","ts":1762234209.7787428,"caller":"membership/cluster.go:392","msg":"added member","cluster-id":"b59d820ff8caf3f4","local-member-id":"0","added-peer-id":"f416c4d7e7853c3a","added-peer-peer-urls":["http://192.168.93.101:2380"]}
{"level":"info","ts":1762234209.7882888,"caller":"snapshot/v3_snapshot.go:309","msg":"restored snapshot","path":"snap.db","wal-dir":"/data/etcd/member/wal","data-dir":"/data/etcd","snap-dir":"/data/etcd/member/snap"}
bash 复制代码
# etcd2
[root@etcd2 ~]# etcdctl snapshot restore snap.db --name=etcd2 --data-dir=/data/etcd --initial-cluster=etcd1=http://192.168.93.101:2380,etcd2=http://192.168.93.102:2380,etcd3=http://192.168.93.103:2380 --initial-advertise-peer-urls=http://192.168.93.102:2380
{"level":"info","ts":1762234209.7753522,"caller":"snapshot/v3_snapshot.go:296","msg":"restoring snapshot","path":"snap.db","wal-dir":"/data/etcd/member/wal","data-dir":"/data/etcd","snap-dir":"/data/etcd/member/snap"}
{"level":"info","ts":1762234209.7921374,"caller":"membership/cluster.go:392","msg":"added member","cluster-id":"b59d820ff8caf3f4","local-member-id":"0","added-peer-id":"3d33f92152eaee46","added-peer-peer-urls":["http://192.168.93.103:2380"]}
{"level":"info","ts":1762234209.7922328,"caller":"membership/cluster.go:392","msg":"added member","cluster-id":"b59d820ff8caf3f4","local-member-id":"0","added-peer-id":"5abc4e842d3ab1d6","added-peer-peer-urls":["http://192.168.93.102:2380"]}
{"level":"info","ts":1762234209.7922487,"caller":"membership/cluster.go:392","msg":"added member","cluster-id":"b59d820ff8caf3f4","local-member-id":"0","added-peer-id":"f416c4d7e7853c3a","added-peer-peer-urls":["http://192.168.93.101:2380"]}
{"level":"info","ts":1762234209.7970464,"caller":"snapshot/v3_snapshot.go:309","msg":"restored snapshot","path":"snap.db","wal-dir":"/data/etcd/member/wal","data-dir":"/data/etcd","snap-dir":"/data/etcd/member/snap"}
bash 复制代码
# etcd3
[root@etcd3 ~]# etcdctl snapshot restore snap.db --name=etcd3 --data-dir=/data/etcd --initial-cluster=etcd1=http://192.168.93.101:2380,etcd2=http://192.168.93.102:2380,etcd3=http://192.168.93.103:2380 --initial-advertise-peer-urls=http://192.168.93.103:2380
{"level":"info","ts":1762234209.7737963,"caller":"snapshot/v3_snapshot.go:296","msg":"restoring snapshot","path":"snap.db","wal-dir":"/data/etcd/member/wal","data-dir":"/data/etcd","snap-dir":"/data/etcd/member/snap"}
{"level":"info","ts":1762234209.7843802,"caller":"membership/cluster.go:392","msg":"added member","cluster-id":"b59d820ff8caf3f4","local-member-id":"0","added-peer-id":"3d33f92152eaee46","added-peer-peer-urls":["http://192.168.93.103:2380"]}
{"level":"info","ts":1762234209.7845335,"caller":"membership/cluster.go:392","msg":"added member","cluster-id":"b59d820ff8caf3f4","local-member-id":"0","added-peer-id":"5abc4e842d3ab1d6","added-peer-peer-urls":["http://192.168.93.102:2380"]}
{"level":"info","ts":1762234209.7845669,"caller":"membership/cluster.go:392","msg":"added member","cluster-id":"b59d820ff8caf3f4","local-member-id":"0","added-peer-id":"f416c4d7e7853c3a","added-peer-peer-urls":["http://192.168.93.101:2380"]}
{"level":"info","ts":1762234209.7922416,"caller":"snapshot/v3_snapshot.go:309","msg":"restored snapshot","path":"snap.db","wal-dir":"/data/etcd/member/wal","data-dir":"/data/etcd","snap-dir":"/data/etcd/member/snap"}
  • 所有节点重启etcd服务
bash 复制代码
systemctl restart etcd
  • 查看验证
bash 复制代码
[root@etcd1 ~]# etcdctl endpoint status -w table --endpoints=http://192.168.93.101:2379,http://192.168.93.102:2379,http://192.168.93.103:2379
+----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
|          ENDPOINT          |        ID        | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS |
+----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| http://192.168.93.101:2379 | f416c4d7e7853c3a |  3.4.23 |   33 kB |      true |      false |         2 |          8 |                  8 |        |
| http://192.168.93.102:2379 | 5abc4e842d3ab1d6 |  3.4.23 |   33 kB |     false |      false |         2 |          8 |                  8 |        |
| http://192.168.93.103:2379 | 3d33f92152eaee46 |  3.4.23 |   33 kB |     false |      false |         2 |          8 |                  8 |        |
+----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
  • 重启etcd后,仍能正常获取name的值,并且节点ID未发生改变

七、用户管理命令

  • etcd默认是没有开启访问控制的,如果开启外网访问etcd的话就需要考虑访问控制的问题,etcd提供了两种访问控制的方式:
    • 基于身份验证的访问控制
    • 基于证书的访问控制
  • 从v3.2版本开始,如果使用参数-- client-cert-auth=true启动etcdu武器,则客户端的TLS证书红的"通用名称(CN)"字段将用作etcd用户。在这种情况下,公用名将对用户进行身份验证,并且客户端不需要密码。如果同时传递了--client-cert-auth=true且客户端提供了CN,并且客户端提供了用户名和密码,则将优先考虑基于用户名和密码的身份验证。
  • etcd有一个特殊用户root和一个特殊角色root:
    • root用户:root用户是etcd角色的超级管理员,拥有etcd的所有权限,在开启角色认证之前必须要先建立好root用户
    • root角色:具有该root角色的用户既具有全局读写访问权限,具有更新集群的身份验证配置和权限。此外,该root角色还授予常规集群维护的特权,包括修改集群成员资格,对存储进行碎片整理以及拍摄快照。
  • etcd的权限资源:
    • Users:user用来设置身份认证(user:passwd),一个用户可以拥有多个角色,每个角色被分配一定的权限(只读、只写、可读写),用户分为root用户和非root用户。
    • Roles:角色用来关联权限,角色主要三类:
      • root角色:默认创建root用户时即创建了root角色,该角色拥有所有权限;
      • guest角色:默认自动创建,主要用于非认证使用。普通角色,由root用户创建角色,并分配指定权限。
      • Permissions:权限分为只读、只写、可读写三种权限,权限即对指定目录或key的读写权限。
  • 如果没有指定任何验证方式,即未显示指定以什么用户进行访问,那么会默认会设置为guest角色。默认情况下guest也是具有全局访问权限的。

7.1、用户管理

  • 其主要用法如下所示:
bash 复制代码
etcdctl user <subcommand> [flags]
  • 其主要子命令主要如下所示:
子命令 常用用法 功能描述
add etcdctl user add < user name or user:password > [options] [flags] 添加新用户
delete etcdctl user delete < user name > [flags] 删除用户
list etcdctl user list [flags] 列出所有用户
get etcdctl user get < user name [options] [flags] 获取用户详细信息
passwd etcdctl user passwd < user name > [options] [flags] 修改密码
grant-role etcdctl user grant-role < user name > < role name > [flags] 赋予用户角色
revoke-role etcdctl user revoke-role < user name > < role name > [flags]

7.2、角色管理

  • 其主要用法如下所示:
bash 复制代码
etcdctl role <subcommand> [flags]
  • 其主要子命令主要如下所示:
子命令 常用用法 功能描述
add etcdctl role add < role name [flags] 添加角色
delete etcdctl role delete [flags] 删除角色
list etcdctl role list [flags] 列出所有角色
get etcdctl role get [flags] 获取角色详情
grant-permission etcdctl role grant-permission [options] < role name > < permission tye > < < key > > [endkey] [flags] 把key操作权限授予一个角色
revoke-permission etcdctl role revoke-permission < role name > < key > [endkey] [flags]

7.3、开启root身份验证

  • 在开启身份验证后,注意事项如下所示:
    • 开启身份验证:所有etcdctl命令操作都需要指定用户参数--user,参数值为用户名:密码
    • 开启证书验证:所有etcdctl命令操作都需要添加证书参数--cacert
  • 开启root身份验证的步骤如下所示:
bash 复制代码
# 添加 root 用户, 密码为 123456
[root@etcd1 ~]# etcdctl user add root:123456
User root created


# 开启身份验证, 开启为 enable, 取消为 disable
[root@etcd1 ~]# etcdctl auth enable --user=root:123456
{"level":"warn","ts":"2025-11-04T15:45:30.570+0800","caller":"clientv3/retry_interceptor.go:62","msg":"retrying of unary invoker failed","target":"endpoint://client-a1a91c15-df9d-4e6f-80d3-7f388e9188f4/127.0.0.1:2379","attempt":0,"error":"rpc error: code = FailedPrecondition desc = etcdserver: authentication is not enabled"}
{"level":"warn","ts":"2025-11-04T15:45:30.575+0800","caller":"clientv3/retry_interceptor.go:62","msg":"retrying of unary invoker failed","target":"endpoint://client-a1a91c15-df9d-4e6f-80d3-7f388e9188f4/127.0.0.1:2379","attempt":0,"error":"rpc error: code = FailedPrecondition desc = etcdserver: root user does not have root role"}
Authentication Enabled

# 开启身份验证后, 直接获取键值报错
[root@etcd1 ~]# etcdctl get name
{"level":"warn","ts":"2025-11-04T15:47:25.710+0800","caller":"clientv3/retry_interceptor.go:62","msg":"retrying of unary invoker failed","target":"endpoint://client-09b2c5c3-3be4-45f9-8465-cb85c80dfc80/127.0.0.1:2379","attempt":0,"error":"rpc error: code = InvalidArgument desc = etcdserver: user name is empty"}
Error: etcdserver: user name is empty

# 添加用户信息访问
[root@etcd1 ~]# etcdctl get name --user=root:123456
name
wzh

7.4、角色授权

  • 在开启了root身份验证后,就可以对普通用户和角色操作了
7.4.1、用户增删改查
bash 复制代码
# 添加普通
[root@etcd1 ~]# etcdctl user add test:123 --user=root:123456
User test created

# 用户用户信息
[root@etcd1 ~]# etcdctl user get test --user=root:123456
User: test
Roles:

# 查看所有用户
[root@etcd1 ~]# etcdctl user list --user=root:123456
root
test

# 修改用户密码
[root@etcd1 ~]# etcdctl user passwd test --user=root:123456
Password of test: 
Type password of test again for confirmation: 
Password updated

# 删除用户
[root@etcd1 ~]# etcdctl user delete test --user=root:123456
User test deleted
7.4.2、用户角色绑定
bash 复制代码
# 增加普通用户
[root@etcd1 ~]# etcdctl user add test:123 --user=root:123456
User test created

# 添加角色
[root@etcd1 ~]# etcdctl role add test-role --user=root:123456
Role test-role created

# 将角色绑定给指定用户
[root@etcd1 ~]# etcdctl user grant-role test test-role --user=root:123456
Role test-role is granted to user test

# 查看用户信息
[root@etcd1 ~]# etcdctl user get test --user=root:123456
User: test
Roles: test-role
7.4.3、角色授权
  • 权限分为:只读(read),只写(write)和读写(readwrite)权限
bash 复制代码
# 使用 test 用户获取 name 值会报错, 权限拒绝
[root@etcd1 ~]# etcdctl get name --user=test:123
{"level":"warn","ts":"2025-11-04T16:00:59.605+0800","caller":"clientv3/retry_interceptor.go:62","msg":"retrying of unary invoker failed","target":"endpoint://client-af949a12-8f25-4070-8fef-b7bad516d71b/127.0.0.1:2379","attempt":0,"error":"rpc error: code = PermissionDenied desc = etcdserver: permission denied"}
Error: etcdserver: permission denied

# 按 key 进行授权, test-role 角色可以读写 name
[root@etcd1 ~]# etcdctl role grant-permission test-role readwrite name --user=root:123456
Role test-role updated

# 查看角色权限详情
[root@etcd1 ~]# etcdctl role get test-role --user=root:123456
Role test-role
KV Read:
	name
KV Write:
	name

# 撤销角色权限
[root@etcd1 ~]# etcdctl role revoke-permission test-role name --user=root:123456
Permission of key name is revoked from role test-role


# 查看角色权限详情
[root@etcd1 ~]# etcdctl role get test-role --user=root:123456
Role test-role
KV Read:
KV Write:
相关推荐
独行soc3 小时前
2025年渗透测试面试题总结-234(题目+回答)
网络·python·安全·web安全·渗透测试·1024程序员节·安全狮
刘一说3 小时前
深入理解 Spring Boot 中的数据库迁移:Flyway 与 Liquibase 实战指南
数据库·spring boot·oracle
August_._3 小时前
【MySQL】SQL语法详细总结
java·数据库·后端·sql·mysql·oracle
上海云盾安全满满3 小时前
APP应用怎么选择游戏盾
网络·游戏
打不了嗝 ᥬ᭄3 小时前
数据链路层
linux·网络·网络协议·http
升鲜宝供应链及收银系统源代码服务4 小时前
升鲜宝生鲜配送供应链管理系统---PMS--商品品牌多语言存储与 Redis 缓存同步实现
java·开发语言·数据库·redis·缓存·开源·供应链系统
Fanmeang4 小时前
无线交换机(AC)核心技术详解:构建集中式Wi-Fi网络的基石
网络
苦学编程的谢5 小时前
Redis_8_List
数据库·redis·缓存
曹天骄5 小时前
阿里云 DCDN → CDN 无缝切换教程(以 example.com 为例)
数据库·阿里云·云计算