土法炼钢 · 系统与基础设施

【kube-apiserver】控制面全景:缺口、五轴坐标系与 16 篇路线

文章导航

分类入口
kubernetesdistributed
标签入口
#kubernetes#apiserver#control-plane#storage#watch-cache#admission#apf#overview#v1.30.3

目录

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 不一致 0304、15
Watch / cache cacher、bookmark、resourceVersion、reflector 语义 Watch 断流、410 Gone、List 风暴、cache miss 打穿 etcd 0507、15
Admission 链顺序、timeout、failurePolicy、CEL 慢创建、Webhook 503、突变失败 0809、15
AuthN / AuthZ / Audit SA/JWT、RBAC、SAR 401/403 与存储层混淆 1011、15
流控与可用性 APF、max-in-flight、request timeout apiserver OOM、排队、504 误判为 etcd 12、15

Storage / etcd 耦合轴

定义storage.Interfacek8s.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 轴

定义cacherk8s.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 有独立的 timeoutSecondsfailurePolicyFail/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 篇


三、坐标系背后的三个不变量

  1. 唯一写入方:只有 kube-apiserver 写 etcd(原生栈);scheduler/controller/kubelet 写 apiserver REST。Saltzer 端到端保证建立在这一前提上——任何绕开 apiserver 直写 etcd 的操作都会跳过 admission、RBAC 与字段验证。

  2. 串行失败,分层落格:一次 Create 请求沿 HandlerChain 推进——APF/max-in-flight → authn → authz → audit → admission → storage。任何一层拒绝,请求不继续。因此「失败在哪层」有唯一答案,不能混成「apiserver 慢」。

  3. 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 侧参数。


七、本篇不写什么


参考资料

规范 / 官方文档 / 源码(A)

论文 / 书(A/B)

站内对照(A/B)

实验台账


上一篇系列目录

下一篇apiserver 进程与请求路径

读完这篇,下一步读什么

优先读同系列或同问题的下一篇,把单篇消费变成主题集群。

2026-08-28 · kubernetes / distributed

【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 轴。


By .