【kube-apiserver】进程与请求路径:generic apiserver、HandlerChain 与 REST 路由

💡 原文中文,约8700字,阅读约需21分钟。
📝

内容提要

本文拆解kube-apiserver请求路径,从TLS终止到etcd写入,需经过APF流控、认证、授权、Admission等拦截点。APF在认证前,Admission在REST handler内。请求失败时需区分是Webhook拒绝、APF排队还是etcd问题,不能简单归因于etcd慢。GVR路由将请求映射到对应storage实现。

🔎

延伸解读

排障定位:先确认请求是否到达 storage

请求失败时,不能简单归因于 etcd 慢。若 APF 排队超时,症状是 504,但 etcd 指标不会抬头;若 Webhook 拒绝,apiserver 日志显示 admission 错误,而 etcd 完全健康。排障时应先确认请求是否到达 storage.Interface,再结合各层指标(如 apiserver_flowcontrol_rejected_requests_total、etcd_request_duration_seconds)定位失败落点。

HandlerChain 顺序的版本敏感性

HandlerChain 的中间件顺序由 DefaultBuildHandlerChain 函数决定,而非固定不变。v1.30.3 中 APF 在认证之前,Admission 在 REST handler 内部。不同版本或自定义 apiserver 可能调整顺序,排障时应以对应源码 tag 的实现为准,避免依赖非版本化文档的笼统描述。

APF 前置的权衡:匿名请求占队列

APF 放在认证之前,意味着未认证请求也会消耗队列资源,可能影响已认证请求。社区在 KEP-1040 中讨论过此权衡:若放在认证之后,认证本身可能成为无保护的瓶颈;放在之前则需接受匿名请求占队列的代价。v1.30.3 选择了前置方案,理解这一设计有助于解释为何匿名请求也可能触发 429。

Q&A

kube-apiserver 处理请求时,APF 流控和认证的顺序是怎样的?

在 Kubernetes v1.30.3 中,APF(API Priority and Fairness)流控位于认证之前。请求先经过 APF 流控,再进入认证。这意味着流控层看到的是未认证请求,按 IP/UA 分类,不能依赖用户身份。

Admission 在 kube-apiserver 请求路径中的位置在哪里?

Admission 不是独立的 HTTP 中间件,而是在 REST handler 内部,在调用 storage.Interface 之前显式调用 admission.Interface.Admit/Validate。因此 Admission 拒绝的错误由 REST handler 返回,而不是中间件链直接短路。

当 apiserver 返回 503 时,可能的原因有哪些?如何区分是 Webhook 拒绝还是 etcd 问题?

apiserver 返回 503 可能由 Webhook 拒绝(failurePolicy=Fail 时 Webhook 不可达)或 APF 排队超时导致,不一定意味着 etcd 不可用。若 etcd 指标(如 etcd_request_duration_seconds)无异常,应优先检查 Admission 和 APF;若 etcd 指标异常且写超时,则查 Storage/etcd。

kube-apiserver 如何将 HTTP 请求路由到对应的 storage 实现?

kube-apiserver 使用 GVR(GroupVersionResource)路由机制。每个 API 组在启动时调用 Install 注册资源类型为 HTTP 路径,如 /apis/{group}/{version}/{resource}。路径匹配由 go-restful 路由树完成,每条路径映射到一个 rest.Storage 接口,该接口内部持有 storage.Interface 实例。HTTP 方法(GET、POST、PUT、PATCH、DELETE)映射到对应的 storage 方法,如 PUT 映射到 GuaranteedUpdate。

kubectl create deployment 请求在到达 etcd 前可能被哪些拦截点拒绝?

请求在到达 etcd 前可能被三个拦截点拒绝:1. APF/max-in-flight 流控,队列满时返回 429;2. 认证(401)和授权(403);3. Admission(Mutating 和 Validating Webhook),任何一个拒绝即返回错误。只有三个拦截点全部通过,storage.Interface.Create 或 GuaranteedUpdate 才会被调用。

为什么 APF 流控放在认证之前?有什么权衡?

APF 放在认证之前是为了对认证请求本身提供速率保护,避免认证成为无保护的瓶颈。但代价是匿名请求也会占用 APF 队列资源,可能影响已认证请求。这是 Kubernetes 社区在 KEP-1040 中讨论过的权衡,v1.30.3 选择了 APF 在认证之前。

🏷️

标签

➡️

继续阅读