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

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

文章导航

分类入口
kubernetesdistributed
标签入口
#kubernetes#apiserver#crd#aggregation#apiservice#extension#webhook#v1.30.3

目录

kube-apiserver 处理 GET /apis/example.com/v1/foos 与处理 GET /api/v1/pods 的路径不一样长。前者可能被转发到集群外的 Extension Server,也可能在 apiserver 内部走 CRD 转换 webhook;后者则全程在 apiserver 进程里落 storage.Interface。两条扩展路径的失败模式、排障锚点与影响半径都不同,但故障现象却可能同样表现为 503 或超时。

本文是第 13 篇,专门钉这两条扩展路径的机制边界失败模式,并写明停损线:哪些属于本系列范围,哪些属于 scheduler/controller/kubelet 或 CRD codegen 领域。

本篇在系列中的位置

篇目 核心内容
第 12 篇 · APF 与 max-in-flight 公平排队、504 与 etcd lag 分列
第 13 篇 · 扩展边界 CRD v1 存储路径、APIService 转发、停损线
第 14 篇 · 运维与升级 HA、flags、graceful shutdown、etcd 联检
系列目录 全部篇目

版本锚定:Kubernetes v1.30.3(源码 tag v1.30.3)。etcd 后端对照 etcd v3.5.33。CRD v1 GA 状态以 v1.30.3 为准,不以 /docs/ live 版本冒充。


一、两条扩展路径

Kubernetes 扩展 API 分两类,内部路由完全不同:

flowchart TD
  client["kubectl / client"]
  apiserver["kube-apiserver"]
  crd["CRD handler\n(internal)"]
  etcd["etcd"]
  conv["conversion webhook\n(optional)"]
  agg["aggregation handler"]
  ext["Extension API Server"]

  client --> apiserver
  apiserver -->|"/apis/example.com/v1/* (CRD)"| crd
  crd -->|"storage.Interface"| etcd
  crd -->|"hub version conversion"| conv
  apiserver -->|"/apis/metrics.k8s.io/*"| agg
  agg -->|"proxy"| ext
扩展类型 定义对象 请求落点 持久化 失败模式
CRD v1 CustomResourceDefinition 资源(存 etcd) apiserver 内部 CRD handler etcd(与内置资源同后端) conversion webhook 慢/503;schema 验证
Aggregated API APIService 资源(存 etcd) apiserver 转发 → Extension Server Extension Server 自管 Extension Server 不可用 → 503

两条路径共同点:定义对象(CustomResourceDefinitionAPIService)自身都存在 etcd 里,其变更通过 apiserver Storage 轴落地。区别在于读写 CR/AA 资源时请求是否离开 apiserver 进程。


二、CRD v1:存储路径

2.1 CustomResourceDefinition 本身的存储

CustomResourceDefinition 是内置 API 资源,存储路径形如 /registry/apiextensions.k8s.io/customresourcedefinitions/<name>,走标准 storage.Interface + etcd3 store(Storage 轴)。CRD 变更由 apiextensions-apiserver(嵌套在 kube-apiserver 进程内,实现为 generic apiserver 委托链的一部分)处理。

当 CRD 定义落 etcd 后,kube-apiserver 动态注册该 GVR 路由(GroupVersionResource)。此后对 CR 对象的读写请求走同一个 etcd 后端。

2.2 CR 对象的存储 key

以 CRD 定义的 group=example.comversion=v1plural=foos 为例,etcd key 形如:

/registry/example.com/foos/<namespace>/<name>

存储格式默认为 protobuf(如果 CRD 定义的 scheme 支持)或 JSON;encryption provider 配置会对这条路径生效(与内置资源统一)。

2.3 多版本与 conversion webhook

CRD 支持多存储版本(spec.versions[].storage: true)。当 CR 以旧版本存入 etcd、客户端请求新版本时,apiserver 调用 conversion webhookspec.conversion.strategy: Webhook)做版本转换。

失败模式

场景 表象
conversion webhook 不可达 GET/Watch CR 返回 500503 Admission(webhook 子分类)
conversion webhook 慢(超过 webhooks[].timeoutSeconds 请求超时;apiserver_request_duration_seconds 增大 Admission/Storage 轴边界
存储版本与 hub 版本不匹配 批量 migrate 时数据转换失败 Storage 轴
CRD 定义被删除(CR 仍存 etcd) GVR 路由消失;客户端 404

conversion webhook 超时不等于 etcd 慢——排障时先查 webhook 端到端延迟,再查 etcd_request_duration_seconds。两者联动见第 15 篇

2.4 CRD 验证 webhook(ValidatingAdmissionWebhook/MutatingAdmissionWebhook)

CRD 资源与内置资源一样走 Admission 链。自定义资源的 CEL 验证(spec.validation.openAPIV3Schema.x-kubernetes-validations,v1.25+ GA)在 apiserver 进程内执行,不需要 webhook roundtrip。外部 Validating/Mutating webhook 规则匹配 CRD GVR 时,失败模式与第 9 篇一致。


三、Aggregated API:请求离开 apiserver

3.1 APIService 对象

APIService 资源(apiregistration.k8s.io/v1)指定哪些 group/version 由外部 Extension API Server 处理。典型例子:

APIService 对象本身存 etcd,通过 kube-aggregator(嵌入 kube-apiserver)管理。

3.2 请求转发路径

sequenceDiagram
  participant Client
  participant kube-apiserver (aggregation handler)
  participant Extension Server

  Client->>kube-apiserver (aggregation handler): GET /apis/metrics.k8s.io/v1beta1/nodes
  kube-apiserver (aggregation handler)->>Extension Server: proxy HTTP request (mTLS)
  Extension Server-->>kube-apiserver (aggregation handler): response
  kube-apiserver (aggregation handler)-->>Client: response

关键点:请求经 apiserver 认证/授权后,聚合层将原始请求(含 Authorization header 中的 impersonation 信息)代理到 Extension Server。Extension Server 自己管理存储——可以是独立 etcd、内存,也可以是任意后端。

3.3 失败模式

场景 表象 排障起点
Extension Server 未运行 APIService 状态 Available=False;请求 503 kubectl get apiservice;检查 Extension Server Pod
Extension Server 响应慢 客户端超时;kube-apiserver 聚合超时(默认 60s) Extension Server 自身日志;kube-apiserver audit log
Extension Server 证书过期 mTLS 握手失败;503 APIService 状态、证书有效期
Extension Server 内 etcd 不可达 请求读写失败;语义由 Extension Server 决定 Extension Server 日志;其后端 etcd(独立排障链)

与 CRD 分列:CRD 失败时 kube-apiserver 进程内有确定的 Storage/Admission 报错;Aggregated API 失败时 kube-apiserver 只是代理,错误来自下游——不要把 Extension Server 不可用误判为 kube-apiserver etcd 连接问题。


四、停损线:不在本系列的三块

4.1 CRD codegen 与 controller-runtime 全书

CRD 开发侧:controller-gen 生成 deepcopy/CRD YAML、controller-runtime Reconcile 框架、informer/cache 配置——这些是客户端库与开发者工具,不是 kube-apiserver 内核。本系列停在「CR 如何存 etcd、conversion webhook 如何在 apiserver 侧失败」;CRD 开发全书见官方 controller-runtime 文档与 Kubebuilder book。

4.2 scheduler / controller-manager 内核

kube-schedulerkube-controller-manager 是 apiserver 的客户端:通过 informer 监听资源变化,不持有 etcd 连接。它们的控制循环失败(reconcile 慢、queue 积压)属于控制面逻辑层,不是 apiserver Storage/Watch/APF 五轴。排障时若发现 controller 停更,应先确认 apiserver Watch 轴是否正常,再进入 controller 日志分析。

4.3 kubelet 数据面

kubelet 运行在每个 Node,通过 apiserver 更新 Pod/Node 状态,但不直连 etcd。Node Lease 是 apiserver 经 storage.Interface 写 etcd 的操作(见 etcd/13 §四)。kubelet 内核(容器运行时、CNI 调用、设备插件)不在本系列范围;数据面见 k8s-network/


五、边界汇总

问题 本系列范围 停损线外
CRD 对象存 etcd 路径 是(Storage 轴)
CRD conversion webhook 超时 是(Admission/Storage 轴)
APIService 代理失败 503 是(聚合层) Extension Server 后端细节
CRD codegen、controller-runtime kubebuilder book
scheduler reconcile 逻辑 kube-scheduler 内核
kubelet 容器运行时 k8s-network/

排障分列:CRD conversion webhook 慢 → 第 15 篇 Admission 轴;Extension Server 不可达 → 聚合层 503,不走 etcd 五轴;存储层写入 CRD CR → Storage 轴(与内置资源一致)。


参考资料

规范 / 官方文档(A)

源码(A)

站内

实验台账


上一篇APF 与 max-in-flight

下一篇运维与升级

读完这篇,下一步读什么

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

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 作为内置替代路径;排障证据包。


By .