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

【kube-apiserver】Admission 链概览:内置插件顺序与 webhook 边界

文章导航

分类入口
kubernetesdistributed
标签入口
#kubernetes#apiserver#admission#webhook#mutating#validating#namespace-lifecycle#resourcequota#v1.30.3

目录

一次 kubectl apply 为什么会被 503 拒绝,但 etcd 里没写任何脏数据?因为 Admission 链在 AuthZ 之后、storage.Interface 持久化之前运行——任何 Admission 插件或 webhook 返回非 OK 响应,整条请求就在这一层失败,不进 etcd。这个设计使 Admission 成为集群策略的最后一道门,也使其成为慢创建与 503 的高频来源。

生产里常见误判:把 Webhook 的 503 归因到 etcd,或把 ResourceQuota 拦截当成 storage 写入失败。定位时应先确认失败发生在 Admission 轴,再区分内置插件还是 webhook。

本篇钉 v1.30.3 的 Admission 链位置、Mutating → Validating 两阶段顺序、内置插件的注册入口(pkg/kubeapiserver/admission/)与典型示例、webhook 集成的边界与 timeout,以及 fail-open vs fail-closed 争议。第 9 篇详写 MutatingAdmissionWebhook 与 ValidatingAdmissionWebhook 的 timeout/failurePolicy/reinvocation 细节。

本篇在系列中的位置

篇目 核心内容
第 7 篇 · Watch 路径(服务端) 长连接、410 Gone、timeout
第 8 篇 · Admission 链概览 Mutating/Validating 顺序、内置插件、webhook 边界
第 9 篇 · Mutating/Validating Webhook timeout、failurePolicy 深度
系列目录 五轴、阅读路径

版本锚定:Kubernetes v1.30.3(源码 tag v1.30.3)。机制钉 staging/src/k8s.io/apiserver/pkg/admission/plugin/pkg/admission/pkg/kubeapiserver/admission/ @ kubernetes/kubernetes v1.30.3。内置插件的完整注册顺序以 K8s 官方文档(Admission Controllers Reference)和该 tag 源码为准;本篇只举具体示例,不尝试穷举。无真实集群则不粘贴伪造 kubectl 输出。


一、Admission 在请求路径中的位置

请求在 kube-apiserver 中经过:AuthN → AuthZ → Admission → storage.Interface(etcd)

flowchart LR
  authn["AuthN\n(JWT/OIDC/SA)"]
  authz["AuthZ\n(RBAC/Webhook)"]
  decode["对象解码 / 默认值填充"]
  mutating["Mutating Admission\n(内置 + MutatingWebhook)"]
  validate_obj["对象验证\n(schema / CEL)"]
  validating["Validating Admission\n(内置 + ValidatingWebhook)"]
  storage["storage.Interface\n(etcd3 / cacher)"]

  authn --> authz
  authz --> decode
  decode --> mutating
  mutating --> validate_obj
  validate_obj --> validating
  validating --> storage

几个关键点:


二、两阶段顺序:Mutating 与 Validating

Admission 在 v1 API 中固定分为两个阶段,顺序不可重排:

Mutating 阶段:所有实现了 admission.MutationInterface 的插件按注册顺序调用,包括 MutatingAdmissionWebhook 插件(负责调用用户配置的 MutatingWebhookConfiguration)。每个 mutating 插件可修改对象。

Validating 阶段:所有实现了 admission.ValidationInterface 的插件按注册顺序调用,包括 ValidatingAdmissionWebhookValidatingAdmissionPolicy(CEL 内联策略,v1.30 GA)。Validating 插件不修改对象,只返回通过或错误。

部分内置插件同时实现两个接口(既 mutate 又 validate),这类插件在两个阶段都会被调用(例如 ServiceAccount 插件:mutating 阶段注入 serviceAccountToken 挂载,validating 阶段检查 ServiceAccount 是否存在)。


三、内置插件:注册路径与典型示例

内置 Admission 插件通过 pkg/kubeapiserver/admission/ 下的注册入口集中装配(RegisterAllAdmissionPlugins),再由 kube-apiserver 的 --enable-admission-plugins / --disable-admission-plugins flag 控制启用。插件的实际注册顺序由 K8s 源码决定,官方文档 Admission Controllers Reference 给出 v1.30 中各插件的建议启用集合。

以下是三类典型内置插件及其关键行为(举例,非完整顺序):

NamespaceLifecycle(mutating + validating)

LimitRanger(mutating + validating)

ResourceQuota(validating)

这些插件展示了 Admission 链的典型模式:先修改(LimitRanger 填默认值),再校验(ResourceQuota 计数检查)。复杂对象(如 StatefulSet)在 Admission 阶段可能经历多个 mutating 插件的累积修改,最后才进入 ValidatingAdmissionWebhook 和 storage。


四、webhook 集成:MutatingAdmissionWebhook 与 ValidatingAdmissionWebhook

MutatingAdmissionWebhookValidatingAdmissionWebhook 本身是两个内置插件,分别在 Mutating 和 Validating 阶段被调用。它们读取集群中的 MutatingWebhookConfiguration / ValidatingWebhookConfiguration 对象,按配置的 rules、namespaceSelector、objectSelector 过滤,向注册的 webhook endpoint(用户自己部署的 HTTP 服务)发送 AdmissionReview 请求。

sequenceDiagram
  participant apiserver
  participant webhookSvc as webhook service\n(用户部署)

  apiserver->>webhookSvc: POST /validate\nAdmissionReview{request: ...}
  alt 允许
    webhookSvc-->>apiserver: AdmissionReview{response: {allowed: true}}
  else 拒绝
    webhookSvc-->>apiserver: AdmissionReview{response: {allowed: false, status: ...}}
  else 超时/连接失败
    webhookSvc-->>apiserver: (无响应)
    apiserver->>apiserver: failurePolicy 决定
  end

timeoutWebhookClientConfig.TimeoutSeconds(默认 10s,上限 30s)。超时后进入 failurePolicy 判断(见第 9 篇)。

失败在 storage 之前:无论 webhook 返回 allowed=false 还是超时被 failurePolicy=Fail 判为拒绝,请求都在此终止,etcd 不写入。


五、fail-open vs fail-closed:工程争议

Webhook 的 failurePolicy 控制当 webhook 服务本身不可达(网络故障、Pod 崩溃、超时)时的行为:

争议的实质:这是 availability vs safety 的经典 trade-off,在分布式系统中没有统一答案。

K8s 官方文档(Admission Webhooks · Availability)建议:

工程上,fail-closed + webhook HA 的组合优于 fail-open + 单副本 webhook——后者在 webhook 升级或节点驱逐时会形成静默策略窗口(silent policy gap)。这个权衡在 etcd/16 §5.1 开放问题列表中也有提及:apiserver 侧 webhook 可用性 SLO 目前没有与 etcd compaction SLO 联合建模的标准。


六、Admission 轴排障口令

症状 倾向
Create/Update 返回 4xx,etcd 无写入 Admission 轴(检查错误 message)
错误含 admission webhook ... denied ValidatingAdmissionWebhook 拒绝
错误含 failed calling webhook + 503/504 Webhook endpoint 不可达;查 failurePolicy
错误含 exceeded quota ResourceQuota 插件拒绝
错误含 LimitRange LimitRanger 插件拒绝
错误含 unable to create ... namespace ... terminating NamespaceLifecycle 插件拒绝
Create 成功但对象多了注入字段 MutatingAdmissionWebhook 修改了对象

第 9 篇深写 webhook 的 timeout/failurePolicy/reinvocation;第 15 篇给出五轴口令完整表。


参考资料

规范 / 源码(A)

论文 / 对照(B)

站内对照


上一篇Watch 路径(服务端):长连接、410 Gone 与 timeout

下一篇Mutating / Validating Webhook

读完这篇,下一步读什么

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

2026-08-28 · kubernetes / distributed

【kube-apiserver】Mutating / Validating Webhook:timeout、failurePolicy 与可用性门

钉 K8s v1.30.3 的 MutatingWebhookConfiguration / ValidatingWebhookConfiguration v1:timeoutSeconds、failurePolicy、sideEffects、reinvocationPolicy 字段语义;webhook 慢如何表现为写路径延迟而非 etcd lag;生产可用性门选取;CEL ValidatingAdmissionPolicy 作为内置替代路径;排障证据包。

2026-08-28 · kubernetes / distributed

【kube-apiserver】CRD / aggregation / 扩展边界:API 扩展停损线

厘清 CRD v1 与 Aggregated API 两条扩展路径在 kube-apiserver 中的存储与请求分界:CRD 对象存 etcd、conversion webhook 失败如何体现在 Storage 轴,APIService 则把请求转发到外部 Extension Server 可引发 503。明确 scheduler/controller/kubelet 为扩展停损线之外的数据面与控制循环。

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 .