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

【kube-apiserver】排障五轴:Storage、Watch、Admission、Auth、APF

文章导航

分类入口
kubernetesdistributed
标签入口
#kubernetes#apiserver#troubleshooting#storage#watch#admission#auth#apf#five-axes#metrics#v1.30.3

目录

「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)

源码(A)

站内

实验台账


上一篇运维与升级

下一篇选型收束与开放问题

读完这篇,下一步读什么

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


By .