「apiserver 挂了」与「etcd 挂了」的修复动作完全不同——前者的可能原因包括 APF 队列打满、Admission webhook 超时、watch cache 未命中回 etcd,以及 Auth 拒绝;后者可能是 Raft quorum 丢失、quota 触顶、Watch ErrCompacted。混因最常见的结果是在 etcd 侧 defrag 而 apiserver APF 队列继续积压,或者在 apiserver 侧重启而 etcd 写超时持续。
本文是第 15 篇:症状 → 轴
映射与命令表。口诀不变:先点名轴,再下钻组件。etcd
生产排障见 etcd/15;运维动作见
第 14
篇。无 K8s 集群则不粘贴伪造 kubectl 输出或
metrics 截图。
本篇在系列中的位置
篇目 核心内容 第 14 篇 · 运维与升级 HA、flags、graceful shutdown 第 15 篇 · 排障五轴 Storage/Watch/Admission/Auth/APF 口令表 第 16 篇 · 选型收束 排除树、开放问题、边界关闭 系列目录 全部篇目
版本锚定:kube-apiserver v1.30.3(tag
v1.30.3)。指标名以该版本 apiserver 为准(metrics 注册在staging/src/k8s.io/apiserver/)。本篇坐标系仅指 kube-apiserver 五轴,不与 etcd 五轴混用;两轴分列见 §七。
一、口诀与总图
轴 1 Storage / etcd 耦合 — storage.Interface、etcd3 gRPC、rv 映射、compact revision
轴 2 Watch / cache — cacher、bookmark、resourceVersion、reflector、ErrCompacted
轴 3 Admission — webhook timeout/failurePolicy、CEL、内置插件
轴 4 Auth — AuthN 401、AuthZ 403、Audit webhook 失败
轴 5 APF / 流控 — FlowSchema、PriorityLevel、排队 504、max-in-flight
flowchart TD
symptom["Symptom"]
symptom --> name["Name apiserver axis first"]
name --> a1["Axis1 Storage/etcd"]
name --> a2["Axis2 Watch/cache"]
name --> a3["Axis3 Admission"]
name --> a4["Axis4 Auth"]
name --> a5["Axis5 APF"]
a1 --> drill["Drill: metrics / logs / etcd/15?"]
a2 --> drill
a3 --> drill
a4 --> drill
a5 --> drill
默认顺序(无其他线索时):轴 4 Auth → 轴 3 Admission → 轴 5 APF → 轴 1 Storage → 轴 2 Watch。实际应先看错误码和 audit log,用下一节的映射表直接定轴。
二、症状 → 轴(入口表)
| 症状(入口) | 优先轴 | 先查 | 不要先做 |
|---|---|---|---|
| 所有请求 401 | 4 | AuthN 配置、SA token、OIDC provider | 重启 etcd |
| 所有请求 403 | 4 | RBAC
ClusterRoleBinding;SubjectAccessReview |
增加 apiserver 副本 |
| 特定资源写返回 503(webhook) | 3 | Webhook endpoint 可达性;webhook
timeoutSeconds |
扩 apiserver |
| 写请求慢 / 504 | 5→1 | APF 队列深度;etcd write 延迟 | 直接 defrag etcd |
| Watch 返回 410 Gone | 2 | resourceVersion;cacher bookmark | 删 pod 重建 |
| List 引发 OOM / 内存暴涨 | 2→5 | List 是否 consistent;reflector resync | 扩 etcd quota |
| kubectl get 返回数据「旧」 | 2 | List resourceVersionMatch;cacher miss |
换 etcd backend |
| controller reconcile 停止 | 2→1 | Informer Watch 断流;ErrCompacted | 加 etcd 节点 |
etcd request failed 日志 |
1 | etcd_request_duration_seconds;etcd
健康 |
只重启 apiserver |
| audit log 停写 | 4 | audit webhook failurePolicy;磁盘 | 扩 apiserver |
原则:症状匹配多轴时,从最靠近客户端的轴(4 → 3 → 5 → 1 → 2)开始否证。
三、轴 1:Storage / etcd 耦合
表象:写操作返回 500
或超时;etcd request failed;rv
不一致;对象版本回退。
| 子问题 | 核对 | 工具/指标 |
|---|---|---|
| etcd gRPC 连接断开 | etcd endpoint 地址;证书有效期 | apiserver
日志;etcd_request_duration_seconds |
| etcd 写超时 | etcd Leader 是否存在;WAL fsync | 落 etcd/15 轴 1–2 |
| quota 写拒绝 | etcd NOSPACE alarm | 落 etcd/15 轴 3 |
| rv 冲突 409 | 客户端 rv 是否已过期;并发写 | 正常乐观并发;客户端 retry |
| 存储加密失败 | KMS provider 健康;encryption-provider-config | apiserver 日志 |
| compact revision 导致 storage 读历史失败 | etcdserver: mvcc: required revision has been compacted |
落轴 2(ErrCompacted) |
与 etcd/15 分列口诀:apiserver 日志报
etcd request failed +
etcd_request_duration_seconds 持续高 → 穿透到
etcd/15
做 etcd 五轴;若 etcd 自身健康(endpoint health
全绿、wal_fsync 正常)但 apiserver Storage 仍报错 → 留在
apiserver 轴(codec、encrypt、prefix 路径)。
四、轴 2:Watch / cache
表象:Watch 断流;客户端收到 410 Gone;List 引发内存暴涨;controller 停更。
| 子问题 | 核对 |
|---|---|
| 410 Gone | cacher bookmark 落后客户端 rv;或 etcd compaction 清掉 start_rev |
| ErrCompacted(透传) | etcd compaction retention < Watch 断开时长;落 etcd/15 轴 4 |
| List 风暴 | List 是否指定
resourceVersionMatch=NotOlderThan;是否触发
consistent list 穿透 etcd |
| reflector resync 循环 | informer 本地缓存与 apiserver 的 rv
对齐;--resync-period |
| cacher 未命中 | 资源类型是否支持 cacher;cacher 未初始化完成(启动阶段) |
410 Gone 分列:410 来自 cacher bookmark
未推进 OR etcd compaction → 先查 apiserver cacher 日志(是否
cache miss);再查 etcd compaction
rev(etcdctl endpoint status RAFT APPLIED INDEX
vs 客户端 rv)。
List 风暴关键点:consistent
list(resourceVersion="")每次都穿透 etcd
Range;大量 consistent list 并发是 etcd 轴 3/4 的放大器——APF
轴(轴 5)应优先拦截,再处理 etcd 侧成本。
五、轴 3:Admission
表象:特定资源创建/更新返回
503;admission webhook denied;写慢但 etcd
健康。
| 子问题 | 核对 |
|---|---|
| Webhook endpoint 不可达 | webhook Service/Pod 健康;DNS 解析 |
Webhook 慢超过 timeoutSeconds |
webhook
自身延迟;apiserver_admission_webhook_admission_duration_seconds |
failurePolicy: Fail |
webhook 503 → 写请求 503;改 Ignore
有安全含义 |
| Mutating webhook 修改对象后 CEL 验证失败 | reinvocation 轮次;MutatingWebhookConfiguration
reinvocationPolicy |
| CRD conversion webhook 慢 | 见第 13 篇 §二 |
| 内置插件(ResourceQuota、LimitRanger) | namespace quota
是否触顶;kubectl describe resourcequota |
Admission 不是 etcd 问题:Admission 链在
storage.Interface 调用之前执行。webhook 503 时
etcd 无写入记录,不要在 etcd 侧查原因。
六、轴 4:Auth
表象:所有/特定请求 401 或 403;audit
log 中 decision: deny。
| 子问题 | 核对 |
|---|---|
| 401 Unauthorized | Bearer token 过期;SA token 轮换;OIDC provider 不可达 |
| 403 Forbidden | RBAC 缺少
Role/ClusterRole;SubjectAccessReview 否决 |
| Node Authorization 403 | kubelet 证书是否有效;TLS bootstrap |
| audit webhook 失败阻塞 | failurePolicy: Block;audit webhook
endpoint 可达性 |
| OIDC provider 证书过期 | --oidc-issuer-url 可达;JWKS 有效 |
401 vs 403 分列:401 = 身份未确认(AuthN 层);403 = 身份确认但无权限(AuthZ 层)。两者都在 Admission 链之前——收到 403 不意味着 webhook 或 etcd 有问题。
七、轴 5:APF / 流控
表象:请求被 429 拒绝;504
超时(排队超时);apiserver_current_inflight_requests
高位震荡;OOM。
| 子问题 | 核对 |
|---|---|
| FlowSchema 未命中 | 请求落入 catch-all;优先级过低 |
| PriorityLevel 队列满 | apiserver_flowcontrol_current_inqueue_requests |
| List 风暴挤占流控 | 大批 List 消耗 FlowSchema seats |
| max-in-flight(旧机制) | APF 启用前的 --max-requests-inflight /
--max-mutating-requests-inflight |
| 请求过大(OOM) | List
无分页;--max-request-bytes-per-sec(如配置) |
504 归因分列:
flowchart TD
t504["504 Gateway Timeout"]
t504 --> apf{"APF queue\nfull / timeout?"}
apf -->|"Yes: apiserver_flowcontrol\n_current_inqueue_requests 高"| fix_apf["调 FlowSchema/PriorityLevel\nor 降低请求速率"]
apf -->|"No"| etcd_lat{"etcd_request_duration\n_seconds 高?"}
etcd_lat -->|"Yes"| etcd15["穿透 etcd/15\n轴 1–3"]
etcd_lat -->|"No"| adm{"Admission\nwebhook 慢?"}
adm -->|"Yes"| fix_adm["检查 webhook 延迟"]
adm -->|"No"| other["apiserver 进程本身:\ncpu/memory;gc 压力"]
APF 与 etcd lag 不互斥:etcd 写慢 → apiserver 请求挂起 → APF 席位被占满 → 后续请求 504。故障序列可能两轴同时亮——从客户端时间戳倒推,先到的轴是根因。
八、命令表(语义;无伪造输出)
以下命令均基于 v1.30.3 apiserver 与标准
kubectl,未在本环境执行。命令格式以
kubectl --help 与官方文档为准。
| 目的 | 命令(语义) |
|---|---|
| 检查 apiserver 健康 | kubectl get --raw /readyz |
| 列出 FlowSchema 与优先级 | kubectl get flowschema,prioritylevelconfiguration |
| 查看 APF 状态 | kubectl get --raw /metrics \| grep apiserver_flowcontrol |
| 查看 in-flight 请求计数 | kubectl get --raw /metrics \| grep apiserver_current_inflight |
| 查看 webhook 延迟分布(语义) | kubectl get --raw /metrics \| grep apiserver_admission_webhook_admission_duration |
| 查看 etcd 请求延迟(语义) | kubectl get --raw /metrics \| grep etcd_request_duration_seconds |
| 查看 Watch 连接数 | kubectl get --raw /metrics \| grep apiserver_longrunning_requests |
| 触发 SubjectAccessReview | kubectl auth can-i <verb> <resource> --as=<user> |
| 查 audit log | journalctl -u kube-apiserver --since "5m ago" \| grep '"decision":"deny"' |
实验台账:上述命令未在本环境执行,输出未展示;数字阈值以你的环境 baseline 为准,本篇不固化告警值。
九、关键 metrics 语义(名称;无截图)
| metrics 名 | 轴 | 语义 |
|---|---|---|
apiserver_request_duration_seconds |
全轴 | 各 verb/resource 的请求延迟分布(包含排队时间) |
etcd_request_duration_seconds |
1 | apiserver 视角的 etcd gRPC 调用延迟 |
apiserver_current_inflight_requests |
5 | 当前 in-flight 请求数(读/写分开) |
apiserver_flowcontrol_current_inqueue_requests |
5 | APF 当前排队请求数(按 FlowSchema 分) |
apiserver_flowcontrol_dispatched_requests_total |
5 | APF 派发请求计数 |
apiserver_flowcontrol_rejected_requests_total |
5 | APF 拒绝(429/504)计数 |
apiserver_admission_webhook_admission_duration_seconds |
3 | Admission webhook 调用延迟 |
apiserver_longrunning_requests |
2 | 当前 Watch/Long-running 连接数 |
apiserver_watch_events_total |
2 | Watch 事件推送总量 |
apiserver_watch_events_sizes |
2 | Watch 事件字节分布 |
使用原则:这些指标名以 v1.30.3 apiserver
metrics
注册(staging/src/k8s.io/apiserver/pkg/endpoints/metrics/)为准;不写告警阈值(依赖环境
baseline 与 SLO,不在此硬编码)。
十、与 etcd/15 五轴的分列
| 维度 | apiserver 五轴(本篇) | etcd 五轴(etcd/15) |
|---|---|---|
| 层级 | apiserver 进程内;存储接口之上 | etcd 服务器内;Raft/WAL/MVCC |
| 分轴依据 | 请求路径层(Auth→Adm→APF→Storage→Watch) | 存储协议层(Raft→WAL→MVCC→Watch→Lease) |
| 504 | APF 排队;Admission 慢;etcd gRPC 超时 | Raft Leader 丢失;WAL fsync 慢 |
| 410 | cacher bookmark;reflector rv 过旧 | etcd ErrCompacted |
| Watch 断流 | cacher miss;List 穿透 | etcd Watch unsynced;compaction |
| 401/403 | Auth 轴(apiserver) | 无对等轴(etcd 无 RBAC) |
穿透判定:若
etcd_request_duration_seconds 高位(Storage
轴有信号)→ 穿透到 etcd/15;否则留在 apiserver 五轴。一次
incident 优先在一层否证,不要同时跑两套排障流程。
与 etcd 五轴的互补分工口诀:
轴 1 Storage/etcd ← etcd_request_duration_seconds → 穿透 etcd/15 轴 1–3
轴 2 Watch/cache ← ErrCompacted → 穿透 etcd/15 轴 4
轴 3 Admission ← webhook 504/timeout → 留 apiserver 轴 3
轴 4 Auth ← 401/403 → 留 apiserver 轴 4
轴 5 APF ← 排队/429 → 留 apiserver 轴 5;间接驱动 etcd 负载
十一、证据包写法
工单或 postmortem 建议按轴贴证据:
Axis1 Storage: etcd_request_duration_seconds p99; apiserver etcd connection errors
Axis2 Watch: apiserver_longrunning_requests; cacher logs; ErrCompacted events
Axis3 Admission: webhook admission_duration_seconds; webhook endpoint health
Axis4 Auth: audit log decision=deny; AuthN provider health
Axis5 APF: flowcontrol_current_inqueue_requests; rejected_requests_total; inflight
一次 incident 只验证一轴假设;否证后再换轴。
参考资料
规范 / 官方文档(A)
- Kubernetes v1.30 · API Priority and Fairness
- Kubernetes v1.30 · Auditing
- Kubernetes v1.30 · Admission Controllers
源码(A)
kubernetes/kubernetestagv1.30.3:staging/src/k8s.io/apiserver/pkg/endpoints/metrics/;staging/src/k8s.io/apiserver/pkg/util/flowcontrol/;staging/src/k8s.io/apiserver/plugin/pkg/admission/
站内
- etcd/15 · 排障五轴
- 第 3 篇 · storage.Interface
- 第 5 篇 · Watch cache
- 第 9 篇 · Webhook
- 第 12 篇 · APF
- 第 16 篇 · 选型收束
实验台账
- 命令与 metrics 名:未在本环境执行;名称与语义来自 v1.30.3 源码与官方文档。不粘贴伪造输出。
上一篇:运维与升级
下一篇:选型收束与开放问题
读完这篇,下一步读什么
优先读同系列或同问题的下一篇,把单篇消费变成主题集群。
【kube-apiserver】控制面全景:缺口、五轴坐标系与 16 篇路线
相对 etcd/13、distributed/50、k8s-network 补齐 kube-apiserver 生产内核缺口;以 Storage/Watch/Admission/Auth/APF 五轴为坐标系定义 16 篇阅读路线;版本锚定 Kubernetes v1.30.3。
kube-apiserver / Kubernetes 控制面内核:storage、cacher、Admission 与 APF
补齐 etcd 系列 K8s 耦合篇之上的 kube-apiserver 生产内核:storage.Interface、watch cache、resourceVersion、Admission/Webhook、APF,并以排障与相对 etcd 的分层收束。
【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。
【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 间隔之间的开放问题。