Skip to content

本轮为理论笔记与静态审读,示例、安装命令和验收器均未执行。下文命令用于解释步骤,预期结果不代表本轮实测;“历史验收”仅指此前批次记录。阅读和书面练习不需要启动服务。

etcd v3:从键值到一致性边界 ​

环境与版本 ​

etcd 保存配置、选主状态等小而重要的数据。客户端通过 v3 API 读写键值,服务端通过 Raft 提交变更;它不是存放大文件、业务日志或无限历史的地方。先会终端、JSON 和 TCP 端口,再开始本课程;不用预先掌握 Go。

本课固定 etcd v3.6.8,镜像 gcr.io/etcd-development/etcd:v3.6.8,校验 digest sha256:397189418d1a00e500c0605ad18d1baf3b541a1004d768448c367e48071622e5。这是可复跑教学版本,不宣称当前最新补丁。官方维护策略按当前及前一个次版本分支维护,升级前仍须查发行记录、安全修复与版本兼容性。核对日期 2026-10-17。

历史批次的验证环境为 Windows PowerShell、Node 24.21.0、Docker Desktop Linux amd64 引擎 29.8.2。Windows 负责执行命令,etcd/etcdctl/etcdutl 在 Linux 容器中运行;这不是 Windows 原生 etcd 服务验证。Linux Bash 可使用下方单行 docker run,Node 脚本相同;macOS 不属于本轮验收。

安装采用固定容器镜像,不在 Windows 主机安装原生服务。从仓库根目录运行;首次创建,名称存在时先检查,不盲目重复执行:

powershell
docker pull gcr.io/etcd-development/etcd:v3.6.8
docker run -d --name showdocs-m4b-etcd-main -p 127.0.0.1:22379:2379 -v showdocs-m4b-etcd-data:/etcd-data gcr.io/etcd-development/etcd:v3.6.8 /usr/local/bin/etcd --name main --data-dir /etcd-data --listen-client-urls http://0.0.0.0:2379 --advertise-client-urls http://127.0.0.1:2379 --listen-peer-urls http://0.0.0.0:2380 --initial-advertise-peer-urls http://main:2380 --initial-cluster main=http://main:2380 --initial-cluster-token showdocs-m4b-etcd-source
docker exec showdocs-m4b-etcd-main etcdctl endpoint health
docker exec showdocs-m4b-etcd-main etcd --version

预期 is healthy,版本 3.6.8。主机端口只绑定 127.0.0.1:22379;docker exec 内客户端连接容器自己的 2379,不是主机端口。数据写入任务独立卷。示例没有启用 TLS/RBAC,只用于本机隔离练习,真实部署应配置身份、证书与网络隔离。

键、前缀和输出 ​

v3 的 key 是字节串;/course/app/color 中的斜线只是命名约定,不会生成目录。前缀查询按字节范围读取,而不是文件系统遍历。所有练习使用 /course/ 避免碰其他键。

powershell
docker exec showdocs-m4b-etcd-main etcdctl put /course/app/color blue
docker exec showdocs-m4b-etcd-main etcdctl get /course/app/color
docker exec showdocs-m4b-etcd-main etcdctl get /course/app/ --prefix -w json
docker exec showdocs-m4b-etcd-main etcdctl del /course/app/color

put 输出 OK,get 输出键和值,del 输出删除数量。不存在的键读取成功但没有 kv,不等于网络失败。JSON 输出中的 key/value 是 Base64 编码;revision、count 等字段用来判断状态,不应解析面向人的表格文本。删除前缀会影响前缀下所有键,不能把空前缀用于共享服务。

单节点与读取一致性 ​

单节点只有一个投票成员,quorum 是 1;停掉该节点就没有读写服务,因此单节点实验不能证明容错。三个投票成员的 quorum 是 2,可容忍一个不可用成员,但这也取决于网络、磁盘和部署故障域。不要为追求偶数节点误以为两个成员可以容忍一个宕机。

默认读取采用线性一致性语义,会检查集群一致性进度。serializable 读取可能从本地状态返回旧值,适合明确允许陈旧数据的场景;不能用它完成配置 CAS 的“先读后写”保证。先读再无条件 put 即使读是线性一致的,中间仍可能被其他客户端修改;下一篇用服务端事务解决。

练习与参考解法 ​

题目:写入 /course/apps/a 和 /course/apps/ab,只想删第一个时能否直接 del /course/apps/a --prefix?先列举再执行。

提示:先把 a 与 ab 当作字节串比较,列出前缀实际匹配的两个键。

参考答案与边界

不能。第二个键也满足该字节前缀。精确删除不带 --prefix;若要模拟目录,使用 /course/apps/a/ 作子键前缀并坚持命名规则。常见错误是将前缀当作目录边界、将空 get 当作请求失败、将单节点健康当成高可用。

资料:官方 v3.6 文档、维护策略、v3.6 发行变更。中文实践参考 Apache APISIX 的 etcd 治理分享,参数与保证以官方所选版本为准。

从旧目录 API 迁移到 v3 模型 ​

etcd mkdir/setdir 如何迁到 v3,三节点参数是否证明 quorum? 历史 3.1.5 笔记的 set/get/update/mk、mkdir/setdir/rmdir/ls 是 v2 目录 API 语境,不能逐字搬到本课 v3。v3 的键是字节串,斜线只是命名约定;get --prefix 扫描范围不是列真实目录,删除前缀会影响所有匹配键。旧 3.3.10 的“放入”例实际重复 get,不能据此认为已写入;当前基本操作以本篇 put/get/del 为准。旧包的 ETCDCTL_API 选择也不是新客户端通用安装要求。

v2 的条件更新与 TTL 用途应迁为事务比较与租约,而非继续维护旧目录命令。lease 可附多个键,keep-alive 延长存活,过期或 revoke 删除附着键;注册键存在不等于业务健康。watch 观察变化,不是永久事件日志;v3 需保存 revision,断线后续读,历史压缩后全量重建。旧 --after-index/exec-watch 与 v3 revision 不混用,外部命令触发也不提供事务。详见本课事务与 lease/watch 两篇。

服务发现还需要注册/健康信号和消费者查找连接,etcd 只保存相关状态,不能凭 proxy 模式保证所有业务端互通。历史单节点日志中的 heartbeat/election/snapshot 数值不是调优建议;UUID 与 leader 输出不证明容错。三成员 Docker 草稿只写了 node2 的启动语句,未证明其余成员存在或 quorum 成立。listen 与 advertise 需区分,0.0.0.0 不能作为远端可连接地址,持久化卷也不是备份。

旧 systemd root 单元、默认端口、HTTP 明文和成员 add/remove/backup 配方均撤回为本课部署或恢复流程;成员变更依赖现有多数派,不能随便删除唯一成员。v3 快照保存与独立恢复由运维篇承接,不把旧 backup 数据目录命令当成同等保证。原图像仅有引用,未逐图验证,不依图推定新环境正确。

继续阅读