etcd/13
· Kubernetes 控制面耦合 钉过 apiserver↔︎etcd
的分层边界、resourceVersion 与 Revision
映射、Node Lease 心跳路径,最后写明「apiserver
存储接口实现不在此展开,见续作控制面内核」。distributed/50 ·
etcd 深度解剖 给出了 Watch/MVCC/Lease 协调层百科,但
apiserver 的缓存层和链路拦截点只做了索引。k8s-network/ 覆盖了
CNI/Service/Pod
数据面,控制面存储层则明确不写。真正缺的一层是:一次
Create/Update 从 REST 到 etcd,失败落在 HandlerChain
的哪个插槽;504 是 APF 排队还是 etcd ReadIndex;410 Gone 是
cacher bookmark 过期还是 etcd ErrCompacted;Webhook 503 与
storage 超时如何分列,以及何时不该直连 etcd 排障
apiserver。
本文只做三件事:钉缺口、定义五条坐标系、给出 16
篇阅读路线。版本锚定 Kubernetes
v1.30.3(源码 tag
v1.30.3),etcd 后端对照钉 etcd v3.5.33。
本篇在系列中的位置
篇目 核心内容 第 1 篇 · 控制面全景 缺口、五轴坐标系、16 篇路线 第 2 篇 · 进程与请求路径 generic apiserver、HandlerChain、REST 路由 第 3 篇 · storage.Interface 与 etcd3 codec、prefix、CRUD/Watch 到 etcd 系列目录 关键问题、阅读路径、全部价值点
版本锚定:Kubernetes v1.30.3(源码 tag
v1.30.3,2024-08-14 补丁线)。机制叙述对齐该 tag 下staging/src/k8s.io/apiserver/;kubernetes.io/docs/为辅助参考,不以 live 版本冒充 v1.30.3。etcd 后端对照钉 v3.5.33——apiserver 存储适配行为以 v1.30.3 源码为准,etcd 侧五轴见 etcd 系列。无真实 K8s 集群则不粘贴伪造kubectl输出或 metrics 截图。
一、相对站内已有内容,缺口在哪
下表列出各已有系列的视角与本系列填补的格子。规则是:不重写已有内容,只填真正空着的格子。
| 已有内容 | 视角 | 本系列补什么 |
|---|---|---|
| etcd/01–16 | 单 Raft 组 → WAL/MVCC → Watch/Lease → K8s 耦合边界 | apiserver 侧 storage/cacher/admission/APF 全书 |
| etcd/13 | apiserver↔︎etcd 分层、rv、Node Lease | 成 16 篇可排障精度;回收悬空指针 |
| distributed/50 | Watch/MVCC/Lease/K8s 百科单篇 | apiserver watch cache 机制落格 |
| k8s-network/ | CNI、Service、Pod 包路径 | 控制面存储与 API 层;不抢数据面 |
| iam/、zero-trust/ | OAuth/OIDC/零信任 | AuthN/AuthZ 只钉 apiserver 路径;不重写 IAM 全书 |
结论:读者知道「只有 apiserver 直连 etcd」,但不知道 写失败是 admission 还是 etcd3、504 是 APF 排队还是 etcd ReadIndex、410 Gone 是 cache bookmark 还是 etcd ErrCompacted、Webhook 503 与 storage 超时如何分列;把 apiserver 当成 etcd 的 curl 代理,会在准入与缓存层指错组件。
Saltzer 端到端论证的含义:Saltzer, Reed & Clark(ACM TOCS 1984)的 end-to-end argument 指出,可靠性保证应在通信端点而非中间层实现。Kubernetes 控制面的单持久化入口(apiserver → etcd)体现了这一原则:RBAC 决策、Admission mutation、字段验证都在 apiserver 层完成,etcd 只见已授权的 protobuf bytes。把 admission 逻辑下沉到 etcd 层或分散到多个写入方,都会破坏这条端到端保证——这也是为什么只有 apiserver 持有 etcd 证书。
本系列刻意不写:Helm/kubeadm 安装全书、scheduler/controller-manager/kubelet 内核重讲、CRD codegen 全书、etcd Raft/MVCC 全书(外链 etcd 系列)、Kine 兼容层全书、CNI/mesh 数据面全书、未实测 P99/QPS 排行。若目标是「etcd Raft lag 与 apply lag 如何分列」,etcd 系列第 15 篇已够;若目标是「504 是 APF 还是 etcd ReadIndex、Webhook 503 与 storage 超时如何分列」,则必须沿本系列五轴下钻。
版本门禁(后续章节共用)
| 能力 | v1.30.3 | 处理 |
|---|---|---|
storage.Interface + etcd3 store |
有 | 第 3–4 篇 |
| watch cache / cacher | 有 | 第 5–7 篇 |
| APF(FlowSchema/PriorityLevel) | 有 | 第 12 篇 |
| Mutating/Validating Webhook v1 | 有 | 第 8–9 篇 |
| CRD v1 / aggregation | 有 | 第 13 篇边界 |
| v1.31+ 独有变更 | 相对 v1.30.3 正文不展开 | 第 14 篇升级门 |
| live docs 后版本能力 | 无 | 禁止写入正文当 v1.30.3 事实 |
二、五条坐标系(后续章节回指)
后面每一篇都落到下面某一条轴上。排障口诀:先点名轴,再下钻组件——不要一上来换 etcd 或扩 apiserver 副本。504 与 etcd lag 在轴 1 与轴 5 分列证据包。
flowchart LR
client["kubectl / controllers"]
apiserver["kube-apiserver"]
auth["AuthN AuthZ Audit"]
adm["Admission chain"]
storage["storage.Interface"]
cacher["watch cache"]
etcd["etcd v3.5.x"]
client --> apiserver
apiserver --> auth
auth --> adm
adm --> storage
storage <--> cacher
storage --> etcd
cacher -->|"ListAndWatch"| etcd
| 轴 | 可核对锚点 | 失败表象 | 主篇 |
|---|---|---|---|
| Storage / etcd 耦合 | storage.Interface、codec/prefix、etcd3
gRPC、compact revision |
写失败但 etcd 健康、transform 错误、rv 与 revision 不一致 | 03、04、15 |
| Watch / cache | cacher、bookmark、resourceVersion、reflector
语义 |
Watch 断流、410 Gone、List 风暴、cache miss 打穿 etcd | 05–07、15 |
| Admission | 链顺序、timeout、failurePolicy、CEL | 慢创建、Webhook 503、突变失败 | 08–09、15 |
| AuthN / AuthZ / Audit | SA/JWT、RBAC、SAR | 401/403 与存储层混淆 | 10–11、15 |
| 流控与可用性 | APF、max-in-flight、request timeout | apiserver OOM、排队、504 误判为 etcd | 12、15 |
Storage / etcd 耦合轴
定义:storage.Interface(k8s.io/apiserver/pkg/storage)是
apiserver 与后端的唯一接触面;etcd3 store 是该接口在 v1.30.3
原生栈的唯一实现。codec 负责对象序列化,pathPrefix
/registry/ 与 resourcePrefix 决定 key
命名,value.Transformer 处理加密与压缩。
etcd/13 已钉「只有 apiserver 直连
etcd」。本轴深化:写失败的 3 个落点——拒绝于
admission(不进 storage)、GuaranteedUpdate
冲突(rv 不匹配)、etcd3
本身(quota/Raft)——三者证据包完全不同。
「写成功但对象不符合预期」或「etcd 健康但 apiserver 写超时」优先落本轴。展开见 第 3 篇、第 4 篇。
Watch / cache 轴
定义:cacher(k8s.io/apiserver/pkg/storage/cacher)在
storage.Interface 之上维护一个按 GVR
分片的内存缓存,向多个 client Watch
扇出事件,同时对满足一致性条件的 List
走缓存路径。bookmark 事件推进 client 侧的
resourceVersion 锚点;cache miss 会打穿到
etcd。
410 Gone 可能来自两处:etcd 侧的
ErrCompacted(etcd compaction 窗口)与 cacher
侧的 watch channel overflow 或 bookmark
过期。两者排障路径不同——前者查 etcd MVCC 轴,后者查
apiserver watch_cache_capacity。
「Watch 断流但 PUT 仍成功」或「controller 大面积触发 resync」优先落本轴。展开见 第 5 篇–第 7 篇。
Admission 轴
定义:mutating admission 先运行(含
Mutating Webhook),再运行 validating admission(含
Validating Webhook)。内置插件在
k8s.io/apiserver/pkg/admission/ 中注册;Webhook
通过网络调用出站。每个 Webhook 有独立的
timeoutSeconds 与
failurePolicy(Fail/Ignore)。
「Create 失败但 etcd 无写入」或「Write 延迟高但 etcd 指标正常」优先落本轴。展开见 第 8 篇–第 9 篇。
AuthN / AuthZ / Audit 轴
定义:请求在 HandlerChain 早期即完成认证(Bearer/SA token/OIDC)和授权(RBAC/Node/Webhook);audit 事件在该阶段产生,不经 storage。401/403 不会产生 etcd 写入。
「403 但 etcd 有 Pod 记录」或「audit log 有请求但 etcd 无变更」优先落本轴。展开见 第 10 篇–第 11 篇。
流控与可用性轴
定义:APF(API Priority and
Fairness,k8s.io/apiserver/pkg/util/flowcontrol)在
HandlerChain
最外层对入站请求分组排队;max-in-flight 是 APF
之前的简单上限。两者都可以产生 429 或导致 client 侧感知
504,与 etcd lag 产生的 504
证据包完全不同。
「apiserver CPU 正常但请求排队」或「etcd 指标健康但 apiserver 返回 504」优先落本轴。展开见 第 12 篇。
三、坐标系背后的三个不变量
唯一写入方:只有 kube-apiserver 写 etcd(原生栈);scheduler/controller/kubelet 写 apiserver REST。Saltzer 端到端保证建立在这一前提上——任何绕开 apiserver 直写 etcd 的操作都会跳过 admission、RBAC 与字段验证。
串行失败,分层落格:一次 Create 请求沿 HandlerChain 推进——APF/max-in-flight → authn → authz → audit → admission → storage。任何一层拒绝,请求不继续。因此「失败在哪层」有唯一答案,不能混成「apiserver 慢」。
watch cache 改变 etcd 负载形态:cacher 把多个 client Watch 合并为一条 etcd Watch;满足条件的 List 走缓存不穿透 etcd。这使 etcd 的 QPS 与 apiserver 侧的请求数解耦——etcd 指标健康不等于 apiserver 侧 Watch 正常,反之亦然。排障时要分别看两侧指标。
四、设计谱系:从 etcd 适配层到 generic apiserver
Saltzer et al. 端到端论证(TOCS 1984)
→ K8s 控制面设计(2014–):唯一持久化入口 + 准入链
→ generic apiserver(k8s.io/apiserver):可复用的 REST/watch/admission 框架
→ kube-apiserver v1.30.3:
HandlerChain(APF → authn → authz → audit → admission)
→ storage.Interface(etcd3 实现)
→ watch cache / cacher(List/Watch 分层)
→ 仍争:watch cache SLO 与 etcd compaction 联合调参;Kine 兼容层语义差
| 维度 | etcd 系列 / etcd/13 | 本系列 | 开放问题 |
|---|---|---|---|
| 视角 | 持久化层五轴;K8s 耦合边界 | apiserver 生产内核;504 分列 | — |
| 深度来源 | Raft→MVCC→Watch 源码;K8s 官方文档 | v1.30.3 staging/src/k8s.io/apiserver/
源码 |
— |
| 写入路径 | Put/Txn → Raft → MVCC | REST → HandlerChain → storage.Interface → etcd3 | events 分集群架构 |
| 读路径 | ReadIndex / serializable 分叉 | cacher 命中 vs 穿透;rv 语义 | watch cache SLO |
| 对照 | etcd/13 | 本系列 16 | etcd/16 排除树 |
五、16 篇路线与阅读建议
flowchart TD
overview["01 Overview"] --> reqpath["02 Request Path"]
reqpath --> storage["03 storage etcd3"]
storage --> rv["04 resourceVersion"]
rv --> cacher["05 Watch Cache"]
cacher --> list["06 List Pagination"]
list --> watch["07 Watch Server"]
watch --> adm["08 Admission"]
adm --> webhook["09 Webhooks"]
webhook --> authn["10 Authentication"]
authn --> authz["11 AuthZ Audit"]
authz --> apf["12 APF"]
apf --> ext["13 CRD Boundary"]
ext --> ops["14 Ops Upgrade"]
ops --> trouble["15 Troubleshoot"]
trouble --> select["16 Selection"]
overview --> select
| 路径 | 篇目 | 适合 |
|---|---|---|
| 必读核心 | 1 → 3 → 5 → 12 → 15 | 快速建立五轴排障框架 |
| 504 归因 | 1 → 5 → 9 → 12 → 15 | apiserver 超时分列 |
| 读写与 Watch | 4 → 6 → 7 → 15 | 410 / List 风暴 |
| 安全与准入 | 8 → 10 → 11 | 403/503 分列 |
| 完整通读 | 1 → … → 16 | 系统掌握 |
读法:先读本篇;若症状是「etcd 健康但 apiserver 504」,优先 02→12→15;若是「Watch 断流或 410 Gone」,优先 04→05→07→15;若是「Create 失败但 etcd 无写入」,优先 02→08→09→15。etcd 侧五轴(no leader / quota / ErrCompacted / Lease TTL)见 etcd/15;本系列不重写 etcd 内核。
每篇一句话价值点
| 篇目 | 价值点 |
|---|---|
| 01 控制面全景 | 缺口、五轴坐标系、16 篇路线;版本门 v1.30.3 |
| 02 进程与请求路径 | HandlerChain 各插槽与失败落点;GVR 路由 |
| 03 storage.Interface 与 etcd3 | codec/prefix/Transformer/GuaranteedUpdate;存储轴核心 |
| 04 resourceVersion 与 Revision 映射 | mod revision → rv 字符串;continue token;一致性读期望 |
| 05 Watch cache / cacher 架构 | dispatch/bookmark/cache miss 穿透;Watch 轴核心 |
| 06 List / Pagination / 一致性 List | continue token 分页成本;一致性 List 与 rv 语义 |
| 07 Watch 路径(服务端视角) | 长连接、410/timeout;与 Informer 边界 |
| 08 Admission 链概览 | 链顺序、内置插件与 webhook 分工;Admission 轴核心 |
| 09 Mutating / Validating Webhook | timeout/failurePolicy;可用性门与排障证据包 |
| 10 Authentication | SA/Bearer/OIDC 边界;401 分列 |
| 11 Authorization 与 Audit | RBAC/SAR;audit 与 403 分列 |
| 12 APF 与 max-in-flight | FlowSchema/PriorityLevel;504 与 etcd lag 分列 |
| 13 CRD / aggregation / 扩展边界 | API 扩展停损线;聚合层故障边界 |
| 14 运维与升级 | HA、flags、graceful shutdown;与 etcd/14 联检 |
| 15 排障五轴 | Storage/Watch/Admission/Auth/APF 口令表;metrics 字段语义 |
| 16 选型收束与开放问题 | 排除树;回收 etcd/13 悬空指针;watch cache SLO 开放问题 |
六、开放问题:watch cache SLO 与 etcd compaction
etcd/13 已指出:compaction 保留窗口与 controller 断连时长共同决定 catch-up 成本。watch cache 在 apiserver 层增加了一个缓冲,但并未消除根本矛盾:
开放问题:apiserver watch cache
目前没有一个可以独立监控的
SLO——是否「足够新」取决于多个运行时条件(cacher 内部
startRevision、etcd compaction
--auto-compaction-retention、controller 的
Watch
重连时间窗口)。三者的联合调参没有统一的官方公式,也没有已
peer-reviewed 的模型。Kleppmann (2017, Designing
Data-Intensive Applications)
的外部一致性模型可作为分析框架,但 apiserver 缓存的精确
staleness bound 仍是工程估算而非形式证明。排障时若
controller 反复 full-resync,应分别查三个变量而不是默认调大
compaction 窗口。
本系列 第 5 篇 与 第 16 篇 展开;etcd/12 给 compaction 侧参数。
七、本篇不写什么
- etcd Raft/WAL/MVCC 内核(外链 etcd 系列)。
- scheduler/controller-manager/kubelet 内核全书。
- CRD codegen / API 聚合实现全书(第 13 篇停损线)。
- CNI / Service / Ingress 数据面全书(外链 k8s-network)。
- 未实测 apiserver vs 直连 etcd P99/QPS 排行榜。
- 把 live docs 后版本能力写成 v1.30.3。
- 伪造
kubectltrace、etcd metrics 截图。
参考资料
规范 / 官方文档 / 源码(A)
- Kubernetes v1.30.3(源码 tag
v1.30.3) kubernetes/kubernetestagv1.30.3:staging/src/k8s.io/apiserver/- Kubernetes · API Concepts(Watch/resourceVersion 语义)
- Kubernetes · Configure and upgrade etcd
- etcd v3.5.33(存储后端)
论文 / 书(A/B)
- Saltzer, J. H., Reed, D. P., & Clark, D. D. (1984). End-to-end arguments in system design. ACM Transactions on Computer Systems, 2(4).
- Li et al. (2017). etcd: A Distributed Key-Value Store… USENIX ;login:.
- Kleppmann, M. (2017). Designing Data-Intensive Applications. O’Reilly.(外部一致性模型参考框架)
站内对照(A/B)
实验台账
- 本篇无集群实测;无伪造
kubectl/etcdctl输出。
上一篇:系列目录
读完这篇,下一步读什么
优先读同系列或同问题的下一篇,把单篇消费变成主题集群。
kube-apiserver / Kubernetes 控制面内核:storage、cacher、Admission 与 APF
补齐 etcd 系列 K8s 耦合篇之上的 kube-apiserver 生产内核:storage.Interface、watch cache、resourceVersion、Admission/Webhook、APF,并以排障与相对 etcd 的分层收束。
【kube-apiserver】排障五轴:Storage、Watch、Admission、Auth、APF
按 Storage/Watch/Admission/Auth/APF 五轴做症状否证;给出完整五轴命令表与症状→轴映射(504、410、401、403、webhook 超时、List 风暴、OOM);说明 apiserver_request_duration_seconds 等核心 metrics 语义;并提供决策树:何时穿透到 etcd/15,何时留在 apiserver 轴。
【kube-apiserver】Watch cache / cacher:dispatch、bookmark 与穿透 etcd
钉 Kubernetes v1.30.3 cacher 对 storage.Interface 的包装:watchCache 滑动窗口与 Ready 门、bookmark 推送路径、cache miss 打穿 etcd 的触发条件,以及 List 风暴成因与 watch cache SLO 与 compaction 间隔之间的开放问题。
【kube-apiserver】storage.Interface 与 etcd3:codec、prefix 与 CRUD 路径
拆解 kube-apiserver 的 storage.Interface 契约与 etcd3 实现:codec 序列化、pathPrefix/resourcePrefix、value.Transformer 加密边界、GuaranteedUpdate 乐观并发,以及 Watch 到 etcd3 的完整路径。版本锚定 Kubernetes v1.30.3 / etcd v3.5.33。