etcd 入门


入门一下 etcd。

etcd 是一个分布式的数据库,但是本文几乎没有涉及分布式内容,主要在介绍 etcd 是什么,etcd 有哪些基本功能,etcd 有哪些配置项,如何使用 etcdcli(客户端)。


名词解释

下表列了一些名词和概念,它们可能跟 etcd 有关,也可能跟分布式概念有关,如果你在阅读后文时遇到障碍,可以来这里找找看。

概念 解释
etcd 一种基于 raft 协议的分布式 kv 数据库,特点是数据强一致性
常用于保存配置文件,如作为 Kubernetes 的默认数据库(etcd 即 etc distributed,/etc 是操作系统的配置目录)
etcdctl etcd 客户端命令行工具,可以输入命令与 etcd 服务端交互(如同 redis-cli)
server 服务端
client 客户端(用户侧)
cluster 集群,etcd 是一个分布式数据库,由多个节点构成一个集群,作为一个整体提供数据库能力
member 集群成员,其实就是一个 server 节点,更侧重 raft 集群下各节点相互通信保证数据一致性的角度
peer 在同一个集群中,一个 member 将其他 member 视为 peer
endpoint 服务节点,其实就是一个 server 节点,更侧重向 client 提供 API 调用的角度
leader 主节点,etcd 集群中只有一个主节点,所有写请求都会先到主节点,由主节点同步数据给从节点
follower 从节点,etcd 集群中可以有若干个
revision etcd 全局版本号,从 1 开始,每次操作数据都会增加
snapshot 快照,保存某一时刻下的系统状态数据,以便可以让 etcd 恢复到该时刻(在此之前的 log 都可以删掉了)
wal 预写日志(Write Ahead Log),类似 MySQL 的 redo log,用于保证集群的一致性、可恢复性
lease 租约,是客户端与服务端之间的约定,约定内容是某段时间内数据必须保留,过了这段时间数据可以删掉,起到过期时间的作用
checkpoints 一种保障 lease 的技术手段,leader 定期做 checkpoints,同步给其他 member,目前还处于实验阶段

快速入门

etcd 是一种数据库,它的特点是分布式、强一致性。

怎么理解分布式、强一致性:

etcd 由多个节点组成一个集群,只要成功向集群写入数据,立刻可以读到刚刚写入的数据,即使发生节点异常、网络分区故障。强一致性,不是指集群内的所有节点在任意时刻状态一致,而是指整个集群看起来像是只有一个数据副本,读写操作都是原子的,不用关心数据同步的。

etcd 内部通过 Raft 协议实现,由该协议保证分布式、强一致性,这种协议的原理可以参考:

粗略写一下 etcd 如何保证数据强一致性(Raft 实现):

etcd 由多个节点组成一个集群,其中一个主节点,剩余的都是从节点。

写操作:只能由主节点操作,主节点将数据同步给从节点,大多数从节点返回成功,主节点认为成功。

读操作:所有节点均可操作,从节点先获取主节点的版本号,如果版本落后就等,一直等到版本追上,返回数据。


介绍一点历史。

etcd 于 2013 年由 CoreOS 团队发起,2015 年发布第一个正式稳定版本 2.0,2017 年发布 3.0,这两个版本内部实现不同,v2 写入的数据 v3 查不到。本文采用的版本是 3.5。

etcd 最初的目标是构建一种高可用、分布式、强一致性的 key-value 数据库,用来保存重要的数据,etcd 即 etc distributed 的缩写,/etc 是操作系统存储配置数据的地方。

目前 etcd 是 Kubernetes 的默认数据库。


etcd 分服务端(Server)和客户端(Client),在本地起一个 etcd 服务端后,就可以使用客户端命令行工具 etcdctl 发送命令,读写数据:

1
2
3
4
5
6
# etcd 服务端启动后
etcdctl put foo bar
# OK
etcdctl get foo
# foo
# bar

etcd 保存的数据有版本号,你可以读到所有历史版本的数据(如果不压缩清除历史版本的数据):

1
2
3
4
5
6
7
8
9
10
11
12
13
# 写数据
etcdctl put foo bar1 -w json
# {"header":{"cluster_id":14841639068965178418,"member_id":10276657743932975437,"revision":2,"raft_term":3}}
etcdctl put foo bar2 -w json
# {"header":{"cluster_id":14841639068965178418,"member_id":10276657743932975437,"revision":3,"raft_term":3}}

# 读数据
etcdctl get foo
# foo
# bar2
etcdctl get foo --rev=2
# foo
# bar1

etcd Server

简单起见,本文只启动一个 etcd 节点,是一个单节点集群。

安装命令

参考文档:

1
2
3
4
5
docker run -d --name Etcd \
--publish 2379:2379 \
--publish 2380:2380 \
--env ALLOW_NONE_AUTHENTICATION=yes \
bitnami/etcd:latest

安装成功,测试一下:

1
2
3
4
5
6
etcdctl put foo bar
# OK

etcdctl get foo
# foo
# bar

配置参数

etcd 服务端在启动时,可以配置名称、存储文件目录、Raft 选举间隔等参数。官方文档:《Configuration flags》。

有三种配置方式:

  • Configuration file

    通过 YAML 文件配置,官方 demo:etcd.conf.yml.sample

    需要在启动命令里通过 --config-file 指定配置文件。

  • Command-line flags

    通过命令行 flags 配置,例如通过 --name pz_etcd_1 配置 etcd 节点的名称。

  • Environment variables

    通过环境变量配置,跟命令行 flags 参数一一对应,由 ETCD_ 开头。

    例如命令行 flags 参数 --some-flag 对应的环境变量参数为 ETCD_SOME_FLAG

如果使用配置文件,将忽略其他两种配置(即使参数类型不同)。

不能同时使用命令行 flags 和环境变量配置同一个参数,否则 etcd 无法启动。


下面以 Command-line flags 的形式,介绍所有服务端配置参数(分类),你可以跳过去看后面更重要的内容。

member

参数名 默认值 作用
–data-dir ${name}.etcd 服务运行数据保存的路径
–wal-dir WAL 日志保存的路径(不指定则保存在 data-dir 下)
–listen-peer-urls http://localhost:2380 监听其他 etcd 节点(peer)通信的 URLs(真实环境不能设定 localhost)
–listen-client-urls http://localhost:2379 监听 client 请求的 URLs
–listen-metrics-urls 监听 metrics 和健康检查的 URLs
–max-snapshots 5 最大保留 snapshot 的数量(0 表示无限)
–max-wals 5 最大保留 wal 的数量(0 表示无限)
–name default etcd member 单节点的名字
–snapshot-count 100000 发起一次 snapshot 写入磁盘需要提交多少次事务
–heartbeat-interval 100 leader 多久发送一次心跳到 followers(单位:毫秒)
–election-timeout 1000 重新投票的超时时间,如果 follow 在该时间间隔没有收到心跳包,会触发重新投票
–initial-election-tick-advance true (没看明白)一个用于多节点时加快选举初始化的开关,如果打开,初始化会变快
–quota-backend-bytes 0 后端存储大小,超过后将报警,无法写入(0 表示默认 2G)
–backend-bbolt-freelist-type map (没看明白)etcd 后端 boltdb 使用的 freelist 的类型(可选值:map、list)
–backend-batch-interval 0 提交后端事务之前的最大时间
–backend-batch-limit 0 提交后端事务之前的最大操作次数
–max-txn-ops 128 单个事务中的最大操作次数
–max-request-bytes 1572864 客户端单次请求,最大可以多少字节(默认 1.5 MB)
–grpc-keepalive-min-time 5s 客户端等待服务端 ping,最少需要等待多久
–grpc-keepalive-interval 2h 客户端 ping 服务端以保持连接,时间间隔多久(0 表示禁用)
–grpc-keepalive-timeout 20s 关闭一个没有响应的连接之前,额外等待多久(0 表示禁用)
–socket-reuse-port false 开启 socket 配置 SO_REUSEPORT,以允许端口(port)复用
socket-reuse-address false 开启 socket 配置 SO_REUSEADDR,以允许服务端在 TIME_WAIT 状态时绑定(bind)地址
–max-concurrent-streams 1<<32 - 1 每个客户端最多同时开启并发流(concurrent streams)的数量

raft connection timeouts

参数名 默认值 作用
–raft-read-timeout 5s 每个 rafthttp 连接的读超时时间
–raft-write-timeout 5s 每个 rafthttp 连接的写超时时间

clustering

参数名 默认值 作用
–initial-advertise-peer-urls http://localhost:2380 给同集群内其他节点(peer)向自己通信用的 URLs 地址
–advertise-client-urls http://localhost:2379 给外界(指客户端)向自己发起请求用的 URLs 地址
=== 以下为动态发现 ===
–discovery 启动集群时用于动态发现的 URL(v2 API 使用参数,将在 3.7 deprecated)
–discovery-fallback exit 服务发现失败时该怎么办(可选值:exit、proxy,其中 proxy 仅 v2 可用)
–discovery-proxy 用于请求到发现服务的 HTTP 代理(将在 3.7 deprecated)
–discovery-srv 用于启动集群的 DNS srv 域名,用于 DNS 动态服务发现
–discovery-srv-name DNS 服务发现时的服务名
=== 以下为静态部署 ===
–initial-cluster default=http://localhost:2380 集群初始成员配置(当前集群有哪些 URLs)
–initial-cluster-token etcd-cluster 集群初始化 token(每个集群都应该有不同的 token,用于区分)
–initial-cluster-state new 集群初始状态(可选值:new 首次启动集群、existing 向集群增加新的节点)
=== 以下为其他 ===
–strict-reconfig-check true (没看明白)拒绝将导致法定人数(quorum)丢失的重配置请求
–pre-vote true 在 Raft vote 阶段前增加 pre-vote 阶段,增加选举稳定性
–enable-v2 false 在 v3 版本下是否接受 v2 版本的请求(3.5 deprecated)
–experimental-enable-v2v3 用带前缀的 v3 版本来模拟处理 v2 版本的请求(3.5 deprecated)
–v2-deprecation not-yet v2 版本的下线阶段,处理 v2 请求时会用到(可选值:not-yet、write-only、write-only-drop-data、gone)

proxy

将在 3.6 deprecated

(没看懂,但是已经要废弃了,不关注了)

参数名 默认值 作用
–proxy off 代理模式设置(可选值:off、readonly、on)
–proxy-failure-wait 5000 (没看明白)在被重新考虑之前,终端将被视为失败状态的时间(单位:毫秒)
–proxy-refresh-interval 30000 (没看明白)终端刷新间隔时间(单位:毫秒)
–proxy-dial-timeout 1000 请求(dial)超时时间(单位:毫秒, 0 表示禁用超时)
–proxy-write-timeout 5000 写超时时间(单位:毫秒, 0 表示禁用超时)
–proxy-read-timeout 0 读超时时间(单位:毫秒, 0 表示禁用超时)

security

参考资料:《ETCD:TLS

参数名 默认值 作用
–cert-file 客户端 TLS 证书文件的路径(CA 证书)
–key-file 客户端 TLS 私钥文件的路径
–client-cert-file (没看明白)如果 –client-cert-auth=true,作为初始化连接时的客户端证书,如果为空,使用 –cert-file
–client-key-file (没看明白)–client-cert-file 的私钥
–client-cert-auth false 是否开启客户端证书认证,如果开启,请求 etcd 需要携带证书
–client-crl-file 指定客户端认证的 CRL 文件列表(CRL:证书吊销列表,用于私钥丢失泄密时使用)
–client-cert-allowed-hostname 允许 TLS 认证使用主机名
–trusted-ca-file 受信任的证书颁发机构
–auto-tls false 使用自动生成的自签名证书进行与客户端的 TLS 连接
–peer-cert-file peer server TLS 证书文件的路径
–peer-key-file peer server TLS 私钥文件的路径
–peer-client-cert-file (没看明白)–client-cert-file 的 peer client 版
–peer-key-file (没看明白)–client-key-file 的 peer client 版
–peer-client-cert-auth false 开启 peer client 证书验证
–peer-trusted-ca-file peer TLS 受信任的证书颁发机构
–peer-auto-tls false 使用自动生成的自签名证书进行与 peer 之间的 TLS 连接
–self-signed-cert-validity 1 client 和 peer 的证书有效时间(单位:年)
–peer-crl-file 指定 peer 认证的 CRL 文件列表
–peer-cert-allowed-cn (没看明白)支持基于 CN(通用名称)的对等节点连接的身份验证
–peer-cert-allowed-hostname 内部 peer 验证时支持 TLS 主机名
–cipher-suites 受支持的 TLS 密码套件的逗号分隔列表(空将由 Go 自动填充)
–experimental-peer-skip-client-san-verification false (没看明白)跳过 peer 客户端验证时的 SAN 验证
–cors * CORS 白名单,由逗号分隔(空或 * 表示允许全部)
–host-whitelist * 如果客户端不使用安全配置,允许的 HTTP 客户端请求的主机名(空或 * 表示允许全部)

logging

参数名 默认值 作用
–logger zap 指定日志组件,3.5 版本后只能选择 zap
–log-outputs default 指定 stdout 或 stderr 以跳过输出日志记录(默认值代表 os.Stderr)
–log-level info 日志级别(可选值:debug, info, warn, error, panic, fatal,默认值: info)
–enable-log-rotation false 启用日志轮替(自动归档过期日志)
–log-rotation-config-json {“maxsize”: 100, “maxage”: 0, “maxbackups”: 0, “localtime”: false, “compress”: false} 日志轮替配置,配置包括:
MaxSize(单位:MB)
MaxAge(单位:天,0 表示无限制)
MaxBackups(归档日志数量,0 表示无限制)
LocalTime(使用机器本地时间,默认 UTC)
Compress(用 gzip 格式归档)

version

参数名 默认值 作用
–version false 打印版本,然后退出程序(os.Exit(0))

maintenance

参数名 默认值 作用
–auto-compaction-retention 0 自动压缩配置,根据 –auto-compaction-mode 不同分为两种
periodic:按时间来配置,比如 5m 代表每五分钟压缩一次(默认单位:小时)
revision:按版本数量来配置,比如 5000 代表每 5000 个版本压缩一次
–auto-compaction-mode periodic 自动压缩模式(可选值:periodic 按周期压缩,revision 按版本数量压缩)

pprof profiler via HTTP

参数名 默认值 作用
–enable-pprof false 开启 pprof(性能监控工具),访问地址是客户端 url + /debug/pprof/

additional metrics

参数名 默认值 作用
–metrics basic 设置 metrics 暴露级别,如果是 extensive 则额外暴露服务端 grpc metrics 直方数据

auth

参数名 默认值 作用
–auth-token simple 指定 v3 版本鉴权 token 类型(可选值:simple,jwt)
–bcrypt-cost 10 指定鉴权密码 bcrypt 算法的加密强度(合法值:4-31)
–auth-token-ttl 300 鉴权 token ttl(单位:秒)

gateway

参数名 默认值 作用
–enable-grpc-gateway true 开启 grpc 网关
开启后可以使用 RESTful 请求,服务端将翻译成 grpc 消息,例如
curl -L http://localhost:2379/v3/kv/put \
-X POST -d ‘{“key”: “Zm9v”, “value”: “YmFy”}’

experimental

参数名 默认值 作用
–experimental-enable-distributed-tracing false 开启分布式链路追踪(OpenTelemetry)
–experimental-distributed-tracing-address localhost:4317 用于分布式链路追踪的数据采集地址
–experimental-distributed-tracing-service-name etcd 分布式链路追踪服务名,所有 etcd 实例需要统一
–experimental-distributed-tracing-instance-id 分布式链路追踪服务 ID,所有 etcd 实例需要各自唯一
–experimental-initial-corrupt-check false 在提供服务之前,先检查数据是否损坏(用于检查集群各节点之间的数据一致性)
–experimental-corrupt-check-time 0s 检查集群间数据一致性的时间间隔
–experimental-enable-lease-checkpoint false 开启后,leader 将启用 checkpoints 机制,用于同步所有节点的 lease 信息
–experimental-enable-lease-checkpoint-persist false (没看明白)启动 persisting remainingTTL,以防止租约无限续订
–experimental-compaction-batch-limit 1000 (没看明白)设置每个批量压缩任务里的最大删除版本数量
–experimental-watch-progress-notify-interval 10m (没看明白)定期检查进程通知的时长
–experimental-downgrade-check-time 5s (没看明白)两次降级(downgrade)状态检查之间的时间间隔
–experimental-warning-apply-duration 100ms 如果请求超过这个时间,将报警
–experimental-memory-mlock false (没看明白)etcd 专属内存页加锁,主要是 mlock bbolt
–experimental-txn-mode-write-with-shared-buffer true 开启写事务,来让只读检查操作时使用共享缓冲区
–experimental-bootstrap-defrag-threshold-megabytes 0 (没看明白)在 etcd 启动过程中,如果超过了设定值,将清理内存碎片(defrag)(只有非零值会生效)

unsafe

参数名 默认值 作用
–unsafe-no-fsync false 禁用 fsync,可能会导致数据丢失
–force-new-cluster false 即使之前启动过,再次启动时也创建一个新的集群

etcd Client

下面介绍如何使用 etcdctl,我们将借着 etcdctl 命令,学习 etcd 都提供了哪些能力。

为确保 etcd 已经成功启动,你可以输入这行命令:

1
2
3
4
5
6
etcdctl endpoint status -w table
# +----------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
# | ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS |
# +----------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
# | 127.0.0.1:2379 | 8e9e05c52164694d | 3.5.4 | 20 kB | true | false | 3 | 21 | 21 | |
# +----------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+

先说一个历史包袱:etcd 有 v2 和 v3 两个版本,两个版本不兼容(v2 保存的数据用 v3 查不到),因此使用 etcdctl 时需要指定版本:

1
2
3
ETCDCTL_API=3 etcdctl get foo
# foo
# bar

不过在 etcd 3.4 时,已经默认 ETCDCTL_API=3(不输入也可以),这个改动的 MR 地址:https://github.com/etcd-io/etcd/pull/9784


etcdctl 有非常多的命令,你可以输入 etcdctl --help 查看,本文只介绍部分单节点相关命令。

下文将介绍的命令有:

  • get:查询
  • put:保存
  • del:删除
  • lease:租约,是 etcd 设置 key 过期时间的方式
  • watch:监听,如果监听了某个 key,每当该 key 有更新,都会监听到
  • lock:互斥锁,可以当做分布式锁来用
  • txn:开启事务,跟通常理解的事务不太一样,用不太上
  • version:查看 etcdctl 的版本
  • endpoint:etcd 节点信息
  • compaction:压缩版本,etcd 会存储所有版本的历史数据,可以通过 compaction 删除掉没用的,释放存储空间
  • defrag:清除存储碎片
  • alarm:报警

公共参数

etcdctl 有一些公共的命令行参数(flags),所有 etcdctl 命令可能都会用上,例如 -w 参数用于指定格式:

1
2
3
4
etcdctl put foo bar -w json
# {"header":{"cluster_id":14841639068965178418,"member_id":10276657743932975437,"revision":7,"raft_term":3}}
etcdctl get foo -w json
# {"header":{"cluster_id":14841639068965178418,"member_id":10276657743932975437,"revision":7,"raft_term":3},"kvs":[{"key":"Zm9v","create_revision":2,"mod_revision":7,"version":6,"value":"YmFy"}],"count":1}
选项名 选项名缩写 默认值 作用
–endpoints [127.0.0.1:2379] 提供 etcd 服务的节点列表
–debug false 是否开启调试日志
–write-out -w “simple” 查询结果的展示形态
可选值:[“fields”, “json”, “protobuf”, “simple”, “table”]
–hex false 查询结果用八进制编码打印
–dial-timeout 2s client 通过 grpc 与 server 建立连接的超时时间(context.WithTimeout
–command-timeout 5s 单一一条操作的超时时间(不包含建立连接的时间)(context.WithTimeout
–keepalive-time 2s client 通过 grpc 与 server 建立连接,每隔多久发送一次 ping
–keepalive-timeout 6s client 通过 grpc 与 server 建立连接,发送一次 ping 之后等多久
–disable true client 连接时允许非安全传输(不使用 TLS)
–insecure-discovery true 在获取集群节点信息时,允许采用不安全的 SRV 记录
–insecure-skip-tls-verify false 跳过 server 证书验证(注意:此选项应仅用于测试目的)
–cert TLS 安全验证时,自己的证书
–key TLS 安全验证时,自己的秘钥
–cacert TLS 安全验证时,CA 的证书
–user 身份验证,用户名
–password 身份验证,密码
–discovery-srv -d 通过 SRV 记录的域名,指定 server endpoint 进行操作
–discovery-srv-name 通过 SRV 记录的服务名称,指定 server endpoint 进行操作

get

1
2
3
4
5
# 前置执行:etcdctl put foo bar

etcdctl get foo
# foo
# bar

相关参数:

选项名 选项名缩写 默认值 作用
–consistency “l” l(Linearizable):线性读取
s(Serializable):并行读取(可能读取到旧数据,新数据还没更新过来)
–order ASCEND:读取结果顺序返回(默认)
DESCEND:读取结果倒序返回
–sort-by CREATE:按照创建所在的版本号排序(版本号作用域是集群)
KEY:按照 key 排序(默认)
MODIFY:按照最近一次修改所在的版本号排序(版本号作用域是集群)
VALUE:按照 value 排序
VERSION:按照 key 修改次数排序
–limit 0 读取结果的数量
–prefix false 读取所有前缀为给定查询内容的记录
etcd get --prefix foo 能够查到 foo、foo1、foo123……)
–from-key false 读取所有比给定查询内容大的记录
etcd get --from-key foo 能够查到 foo、foo1、fop、zoo……)
–rev 0 指定版本号
(比如 key 在 revision=1 时创建,在 revision=2 时更新,那么 –rev=1/2 都可以查到)
–keys-only false 只查询 key(返回结果不包含 value)
–count-only false 只查询匹配到的数量(要求 options --write-out=fields
–print-value-only false 查询结果只打印 value(返回结果不打印 key,但是实际上查询到了)

put

1
2
etcdctl put foo bar
# OK

相关参数:

选项名 选项名缩写 默认值 作用
–lease “0” 设置租约(租约代表着过期时间)
–prev-kv false 更新 key 和 value,并返回原来的 value
–ignore-value false 更新 key,继续使用原来的 value
–ignore-lease false 更新 key 和 value,继续使用原来的租约(否则会清除掉租约)

del

1
2
3
4
5
6
7
8
9
# 前置执行:etcdctl put foo bar
# 前置执行:etcdctl put foo1 bar1
# 前置执行:etcdctl put foo2 bar2

etcdctl del foo
# 1

etcdctl del foo1 foo2
# 2

相关参数:

选项名 选项名缩写 默认值 作用
–prefix false 删除所有 key 的前缀为给定查询内容的记录
–prev-kv false 删除记录,并返回删除的内容
–from-key false 删除所有 key 比给定查询内容大的记录
etcd del --from-key foo 会删除 foo、foo1、fop、zoo……)
–range false (etcd 3.6 引入)
为了避免误操作带来的范围删除,
如果不加 --range,请求会 sleep 两秒再执行(这两秒可以杀掉请求)

lease

租约,用于设置过期时间

lease grant

1
2
etcdctl lease grant 100
# lease 694d81cc2dd33d40 granted with TTL(100s)

使用方式:

1
2
3
4
5
6
7
8
9
10
11
etcdctl put --lease 694d81cc2dd33d40 foo bar
# OK

# 立即查询
etcdctl get foo
# foo
# bar

# 等 100 秒后再查询
etcdctl get foo
#

lease revoke

1
2
3
4
5
# 前置执行:etcdctl lease grant 100
# lease 694d81cc2dd33d46 granted with TTL(100s)

etcdctl lease revoke 694d81cc2dd33d46
# lease 694d81cc2dd33d46 revoked

WARNING:如果有 key 使用了 lease,将这个 lease revoke,key 也会被删除掉

lease timetolive

1
2
3
4
5
6
7
8
9
10
# 前置执行:etcdctl lease grant 100
# lease 694d81cc2dd33d49 granted with TTL(100s)

# 等 10 秒
etcdctl lease timetolive 694d81cc2dd33d49
# lease 694d81cc2dd33d49 granted with TTL(100s), remaining(90s)

# 等 100 秒
etcdctl lease timetolive 694d81cc2dd33d49
# lease 694d81cc2dd33d49 already expired

lease list

1
2
3
4
5
6
# 前置执行:etcdctl lease grant 100
# lease 694d81cc2dd33d49 granted with TTL(100s)

etcdctl lease list
# found 1 leases
# 694d81cc2dd33d49

lease keep-alive

1
2
3
4
5
6
7
# 前置执行:etcdctl lease grant 100
# lease 694d81cc2dd33d49 granted with TTL(100s)

etcdctl lease timetolive 694d81cc2dd33d49
# lease 694d81cc2dd33d49 keepalived with TTL(100)
# lease 694d81cc2dd33d49 keepalived with TTL(100)
# ……

keep-alive 的逻辑是这样的:

  1. 发出 keep-alive 请求之后,请求不会主动结束,而是一直 hang 住
  2. lease TTL 仍然正常自减
  3. lease TTL 减到 0 时,会重新变成初始值(上例是 100)
  4. keep-alive 请求打印一行日志
  5. 无限循环……

watch

监控数据变化

1
2
3
4
5
6
7
8
9
10
11
12
# 请求1
etcdctl watch foo
# 一直卡住

# 请求2
etcdctl put foo bar

# 此时,请求1
# etcdctl watch foo
# PUT
# foo
# bar

相关参数:

选项名 选项名缩写 默认值 作用
–interactive -i false 开启交互模式
有两种交互命令:watch、progress
–prefix false 监控所有 key 的前缀为给定内容的记录
–rev 0 从给定版本开始监控
(比如指定 --rev=1,当前版本是 10,那么会先打印 1-10 的所有改动,再继续监控)
–prev-kv false 监控到变化时,先打印原来的 key 和 value,再打印改动后的 key 和 value
–progress-notify false 如果没有变化,server 还是会周期性地告知 client
(对于 bash 命令行来讲,这个参数没用)

lock

互斥锁,可以当做分布式锁来用

1
2
3
4
5
6
7
8
9
10
11
# 请求1
etcdctl lock mutex1
# mutex1/694d81cc2dd33d7a

# 请求2
etcdctl lock mutex1
# 会卡在这里

# 杀掉请求1,再来看请求2
etcdctl lock mutex1
# mutex1/694d81cc2dd33d7e

相关参数:

选项名 选项名缩写 默认值 作用
–ttl session 的过期时间
如果在这段时间内 client 没有刷新 session,lock 会过期
WARNING:这个 option 不代表自动解锁

txn

事务,使用起来类似于这样:

1
2
3
4
if 判断条件
执行逻辑1
else
执行逻辑2

举例来说(看不明白的话,照着输入一遍就懂了):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 前置执行:etcdctl put foo bar

etcdctl txn -i
# compares:
value("foo") = "bar"

# success requests (get, put, del):
put flag 1

# failure requests (get, put, del):
put flag 2

# SUCCESS
#
# OK

# 此时去查询 etcdctl get flag,会查到 1

txn 的判断条件支持以下这些:

  • ver / version
  • c / create
  • m / mod
  • val / value
  • lease

相关参数:

选项名 选项名缩写 默认值 作用
–interactive -i false 开启交互模式

version

1
2
3
etcdctl version
# etcdctl version: 3.5.4
# API version: 3.5

endpoint

endpoint health

1
2
3
4
5
6
etcdctl endpoint health -w table
# +----------------+--------+------------+-------+
# | ENDPOINT | HEALTH | TOOK | ERROR |
# +----------------+--------+------------+-------+
# | 127.0.0.1:2379 | true | 5.578802ms | |
# +----------------+--------+------------+-------+

endpoint status

1
2
3
4
5
6
etcdctl endpoint status -w table
# +----------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
# | ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS |
# +----------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
# | 127.0.0.1:2379 | 8e9e05c52164694d | 3.5.4 | 25 kB | true | false | 4 | 191 | 191 | |
# +----------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+

endpoint hashkv

计算所有 MVCC keys 的哈希值

1
2
3
4
5
6
etcdctl endpoint hashkv -w table
# +----------------+------------+
# | ENDPOINT | HASH |
# +----------------+------------+
# | 127.0.0.1:2379 | 1639137920 |
# +----------------+------------+

相关参数:

选项名 选项名缩写 默认值 作用
–rev 0 指定到哪个版本号为止的 MVCC keys(默认全部)
比如 --rev=100 表示版本号到 100 为止的所有 MVCC keys 的哈希值

compaction

压缩版本,该版本之前的记录将无法访问

1
2
3
4
5
6
7
8
9
10
11
12
# 比如 revision 已经到 100

etcdctl get foo --rev=10
# foo
# bar

etcdctl compaction 20
# compacted revision

etcdctl get foo --rev=10
# {"level":"warn","ts":"2022-07-05T18:31:36.606+0800","logger":"etcd-client","caller":"v3/retry_interceptor.go:62","msg":"retrying of unary invoker failed","target":"etcd-endpoints://0xc000236000/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

相关参数:

选项名 选项名缩写 默认值 作用
–physical false 一直等到数据被真实删除掉

defrag

清理空间碎片(压缩版本之后,没有把原来占用的存储空间还给文件系统)

1
2
etcdctl defrag
# Finished defragmenting etcd member[127.0.0.1:2379]

相关参数:

选项名 选项名缩写 默认值 作用
–cluster false 清理整个集群的空间碎片

alarm

alarm list

查看所有报警

1
2
etcdctl alarm list
# memberID:13803658152347727308 alarm:NOSPACE

alarm disarm

解除所有报警

1
2
etcdctl alarm disarm
# memberID:13803658152347727308 alarm:NOSPACE

参考资料