「etcd 挂了」在工单里可能指五种互不相同的失败:Leader
丢失、WAL fsync 拖尾、quota 写拒绝、Watch 全量重同步、或
Node Lease 集体过期。一上来对所有节点
defrag,可能把 MVCC 轴
的维护窗口当成 Raft 轴 的 quorum
问题放大;在未确认 Leader 时对 follower 做破坏性
restore,则可能永久丢 quorum。
前序篇已分轴讲机制;本文是系列第 15 篇:症状 →
轴 映射与 etcdctl
字段语义。口诀不变:先点名轴,再下钻组件。K8s
耦合见 第
13 篇;运维动作见 第 14
篇。无 etcd 集群则不粘贴伪造
endpoint status 表格。
本篇在系列中的位置
篇目 核心内容 第 14 篇 · 运维与升级 member change、backup/restore 第 15 篇 · 排障五轴 Raft/WAL/MVCC/Watch/Lease 口令表 第 16 篇 · 选型收束 排除树、开放问题、边界关闭 系列目录 全部篇目
版本锚定:etcd v3.5.33(tag
v3.5.33)。etcdctl endpoint status列名以该版本 CLI 为准。distributed/50 的百科单篇可速览 Watch/MVCC;本篇坐标系仅指 etcd 生产内核五轴,不与 Istio/Linkerd 等同名五轴混用。
一、口诀与总图
轴 1 Raft 共识与成员 — Leader、term、index、learner、quorum、复制 lag
轴 2 WAL 持久化与恢复 — fsync、WAL 段、snapshot、committed vs applied、NOSPC
轴 3 MVCC 存储与容量 — Revision、treeIndex、bbolt、quota、compaction、defrag
轴 4 Watch 客户端同步 — start_rev、synced/unsynced、ErrCompacted、背压
轴 5 Lease TTL 与语义 — grant/KeepAlive/checkpoint、Leader 切换、Txn 锁边界
Raft lag 与 apply lag 分列:Raft index 涨而 applied index 停 → 优先 Apply/MVCC 轴;committed 不涨 → Raft/WAL 轴。
flowchart TD
symptom["Symptom"]
symptom --> name["Name etcd axis first"]
name --> a1["Axis1 Raft quorum"]
name --> a2["Axis2 WAL fsync"]
name --> a3["Axis3 MVCC quota"]
name --> a4["Axis4 Watch rev"]
name --> a5["Axis5 Lease TTL"]
a1 --> drill["Drill component metrics logs"]
a2 --> drill
a3 --> drill
a4 --> drill
a5 --> drill
二、症状 → 轴(入口表)
| 症状(入口) | 优先轴 | 先查 | 不要先做 |
|---|---|---|---|
no leader / 选举风暴 |
1 | 网络分区、quorum 成员数、磁盘慢 | defrag 全集群 |
写超时 / context deadline exceeded |
1→2 | Leader 是否存在;WAL fsync p99 | 升 quota |
mvcc: database space exceeded |
3 | quota、db size;alarm | 只 restart |
| 读到的数据「旧」 | 1 或 8 | 是否线性读;是否 follower 读 | 换应用代码 |
| Watch 断开 / controller 风暴 | 4 | ErrCompacted;start rev |
加 etcd 节点数 |
| Node 批量 NotReady | 5 | Lease TTL;KeepAlive | 查 Pod CNI |
| 重启极慢 | 2→3 | WAL 重放长度;db 大小 | force-new-cluster |
| member 不可达 | 1 | peer URL、防火墙 | 删 member 到 < quorum |
| apiserver 504(K8s) | 分列 | apiserver etcd 延迟 vs 本表 | 混因 |
默认顺序:轴 1 quorum → 轴 2 磁盘 → 轴 3 容量 → 轴 4 Watch → 轴 5 Lease。一次否证一轴。
三、轴 1:Raft 共识与成员
表象:集群不可写;etcdserver: no leader;Raft
选举频繁;follower RAFT INDEX 长期落后。
| 子问题 | 核对 | 工具/指标 |
|---|---|---|
| Quorum 丢失 | 存活 voting member 是否 \(\leq \lfloor N/2 \rfloor\) | member list、健康检查 |
| Leader 网络隔离 | Leader 能否连多数 peer | RTT、丢包 |
| 慢磁盘拖复制 | WAL fsync 高 → 轴 2 联动 | etcd_disk_wal_fsync_duration_seconds |
| Learner 误当 quorum | learner 无投票权 | endpoint status ROLE |
| 配置变更中途失败 | 最近 member add/remove | Raft log / 运维记录 |
committed index vs applied index(第 3、6 篇):
- committed 落后:复制/fsync(轴 1–2);
- applied 落后 committed:Apply 管道 / bbolt batch(轴 3)。
与 distributed/13 分工:PreVote、ReadIndex 代码走读 → distributed/13;本篇只问「是否 Leader、是否 quorum」。
四、轴 2:WAL 持久化与恢复
表象:进程 crash 后长时间
starting;corrupt WAL;磁盘满;snapshot
失败。
| 子问题 | 核对 |
|---|---|
| WAL fsync 慢 | 云盘 IOPS、与别的进程争用;--wal-dir 是否
SSD |
| WAL 与 data 同盘 | 官方建议 WAL 与 backend 可分盘(B 级 hardware 文档) |
| Snapshot 卡住 | --snapshot-count;db 过大 |
| NOSPC | 操作系统磁盘;非 quota alarm |
| restore 后 cluster ID 乱 | 是否混用 restore 与 live member |
指标(语义,非阈值截图):
| 指标 | 含义 |
|---|---|
etcd_disk_wal_fsync_duration_seconds |
WAL 持久化延迟 |
etcd_disk_backend_commit_duration_seconds |
bbolt batch commit |
etcd_server_proposals_failed_total |
Raft 提案失败计数 |
官方 hardware 文档给出 WAL fsync、backend commit 的 p99 告警参考(A 级)——具体毫秒数以 Hardware guidelines 为准,本站不固化「绿线」截图。
五、轴 3:MVCC 存储与容量
表象:database space exceeded;alarm
NOSPACE;读延迟升;defrag 后仍满;大 Value
写失败。
| 子问题 | 核对 |
|---|---|
| Quota | --quota-backend-bytes(默认 2GB,最大
8GB) |
| 历史 rev 膨胀 | auto-compaction 是否启用;retention |
| BoltDB 碎片 | compact 后是否 defrag(第 12 篇) |
| treeIndex 内存 | key 数 × revision 历史 |
| 大 object(K8s) | CRD/Secret 体积;接近 1.5MB 建议上限 |
alarm 处理顺序(语义):compact →
defrag(维护窗)→ alarm disarm——详见官方 alarm
文档;不要在生产高峰对全集群同时
defrag。
读旧 revision:Range 带
revision 参数读历史是 MVCC
特性;若业务「应读最新」却读到旧值,回到 第 8
篇 读一致性分列,不要与 Watch 轴混谈。
六、轴 4:Watch 客户端同步
表象:Watch
断流;etcdserver: mvcc: required revision has been compacted;apiserver/controller
大量 List;内存涨(unsynced watcher 追赶)。
| 子问题 | 核对 |
|---|---|
| start rev 过旧 | 客户端 resourceVersion / Watch
rev |
| Compaction 过 aggressive | --auto-compaction-retention |
| unsynced 追赶 | 历史 rev 回放读 BoltDB(第 9 篇) |
| gRPC 流背压 | 客户端消费慢;channel 阻塞 |
| K8s informer | apiserver watch cache 是否也重 List |
ErrCompacted 标准动作:全量 List 拿新
resourceVersion 再 Watch——无捷径。大集群成本是
开放问题(第 16 篇
§三)。
与轴 3 关系:compaction 清历史 rev → 触发轴 4 失败;调 retention 是 联合调参,不是单轴旋钮。
七、轴 5:Lease TTL 与语义
表象:Lease 集体过期;分布式锁提前释放;K8s Node NotReady 雪崩;TTL「重置」。
| 子问题 | 核对 |
|---|---|
| KeepAlive 停止 | 客户端 crash;网络 |
| Leader 切换 | TTL 是否 checkpoint(第 10 篇) |
| 时钟漂移 | LeaseRead 与 Leader lease(读路径边界) |
| K8s Node Lease | kubelet 续约;apiserver → etcd 写入 |
| 锁语义 | Jepsen:Lease 锁非 strict-serializable(distributed/53) |
KeepAlive 不经 Raft——Leader 故障时轴 5 与轴 1 同时亮;修复 Leader 后观察 Lease 是否 mass expire。
八、etcdctl 字段语义
以下解释 命令语义(A
级:etcdctl endpoint status、endpoint health
文档)。不粘贴本环境输出。
8.1
etcdctl endpoint health
- 对每个 endpoint 发 health RPC;
- 失败常见:无 Leader、超时、证书错误;
- 全绿不等于无 lag——需结合 status。
8.2
etcdctl endpoint status --write-out=table
常见列(v3;具体以 --help 为准):
| 字段 | 轴 | 解读要点 |
|---|---|---|
| ENDPOINT | — | 目标 URL |
| ID | 1 | member ID |
| VERSION | 运维 | 混合版本升级窗口 |
| DB SIZE | 3 | 当前 backend 大小 |
| IS LEADER | 1 | 是否 Raft Leader |
| IS LEARNER | 1 | learner 无投票 |
| RAFT TERM | 1 | 当前 term |
| RAFT INDEX | 1 | 已提交日志位置(口径以文档为准) |
| RAFT APPLIED INDEX | 1/3 | 已 apply 到 MVCC 的位置 |
| ERRORS | 任意 | 须展开日志 |
分列口诀:RAFT INDEX −
RAFT APPLIED INDEX 持续拉大 →
Apply/MVCC;两者都不涨 → Raft/WAL。
8.3 其它常用命令(语义)
| 命令 | 用途 |
|---|---|
etcdctl endpoint hashkv |
各 member KV 哈希是否一致 |
etcdctl alarm list |
NOSPACE 等 alarm |
etcdctl member list |
成员与 learner |
etcdctl get ... --rev= |
读历史 rev(MVCC) |
九、K8s 控制面对照
| K8s 症状 | 先分列 | 再落 etcd 轴 |
|---|---|---|
| apiserver 504 | apiserver metrics | 1–3 |
| 全 Node NotReady | Lease + 网络 | 5 → 1 |
| 单 controller 停更 | Watch/List | 4 |
| 仅 Events 丢 | events etcd | 3(分集群) |
| 升级后异常 | 升级窗 | 14 + 4(rev bump) |
完整耦合见 第 13 篇。
十、证据包写法
工单或 postmortem 建议 按轴贴证据,避免「etcd 日志一段」:
Axis1: endpoint status (Leader/term/index/applied)
Axis2: wal_fsync p99, disk free
Axis3: db size, quota, alarm, last compact
Axis4: compacted rev, client start rev, apiserver watch errors
Axis5: lease count, recent leader change, checkpoint flag
一次 incident 只验证一轴假设;否证后再换轴。
参考资料
规范 / 官方文档(A)
源码(A)
etcd-io/etcdtagv3.5.33:etcdctl/ctlv3/command/endpoint_status_command.go;server/storage/mvcc/watchable_store.go
站内
实验台账
endpoint status/health:未在本环境执行;字段语义来自官方文档与源码。
上一篇:运维与升级
下一篇:选型收束与开放问题
读完这篇,下一步读什么
优先读同系列或同问题的下一篇,把单篇消费变成主题集群。
【etcd】生产全景:缺口、五轴坐标系与 16 篇路线
相对 distributed/50、39、13 钉清 etcd 生产内核缺口;定义 Raft/WAL/MVCC/Watch/Lease 五轴排障坐标系,给出 16 篇阅读路线与 K8s 控制面耦合指针。版本锚定 v3.5.33。
etcd / 生产内核:Raft、WAL、MVCC 与 Kubernetes 控制面底座
补齐 distributed 百科单篇之上的 etcd 生产内核:单 Raft 组、WAL/快照、Revision MVCC、bbolt 单写者、Watch/Lease、K8s apiserver 耦合,并以排障与相对 TiKV/FoundationDB 的选型收束。
【etcd】treeIndex 与 Apply 管道:propose → commit → apply
走读 etcd v3.5.33 从 Raft commit 到 MVCC apply 的串行管道:treeIndex 与 bbolt 分工、consistent index、watchableStore 通知触发点,以及 committed/applied 分列排障。
【etcd】Watch 机制:watchableStore、synced/unsynced 与 ErrCompacted
钉 etcd v3.5.33 watchableStore 的 synced/unsynced/victims 三分法、Apply 后 notify 与历史追赶 syncWatchersLoop,以及 CompactRevision 触发 ErrCompacted 时的客户端重同步边界。