3. K8s 准入控制机制:Admission Controller 工作原理,Mutating 与 Validating Webhook 的区别

Kubernetes 的准入控制(Admission Control)是 API Server 请求链中一道关键的“安全门”。任何对集群资源进行创建、更新、删除的请求,在通过认证(Authentication)和授权(Authorization)之后,但在资源被持久化到 etcd 之前,都必须经过准入控制器的检查与处理。本章将深入剖析其工作原理,并重点对比两种 Webhook 准入控制器的核心差异。

3.1 准入控制请求处理流程

一个完整的 API 请求在 Kubernetes 中的处理顺序如下:

  1. 认证(Authentication):验证请求发起者的身份(如 TLS 证书、、用户名/密码)。
  2. 授权(Authorization):判断该身份是否拥有执行请求操作的权限(如 RBAC 检查)。
  3. 准入控制(Admission Control):在资源被持久化前,执行一系列内置或动态的准入插件。
  4. 资源持久化:将最终的对象数据写入 etcd。

准入控制阶段又细分为两个子阶段:Mutating(变更) 和 Validating(验证)。所有 Mutating 控制器先执行,所有 Validating 控制器后执行。如果任一阶段失败,请求将被拒绝。

K8s API 请求准入控制流程 1. 认证 Authentication 2. 授权 Authorization 3. 准入控制 Mutating 阶段 变更/注入默认值 Validating 阶段 校验/拒绝非法请求 4. 持久化 写入 etcd 拒绝请求(返回错误) Mutating 阶段先执行,Validating 阶段后执行;任一阶段拒绝则请求终止。

3.2 Admission Controller 工作原理

Admission Controller 本质上是一段代码(插件),它拦截 API 请求并执行特定的逻辑。Kubernetes 内置了多种控制器(如 NamespaceLifecycle、LimitRanger、ResourceQuota、PodSecurity 等),同时也支持通过 Webhook 机制动态扩展自定义的准入控制逻辑。

Webhook 准入控制器将决策权委托给集群外部的 HTTP 回调服务。当 API Server 收到请求时,它会构造一个 AdmissionReview 对象,发送给 Webhook 服务器,并根据服务器返回的响应决定是否允许请求继续。

核心概念: AdmissionReview 是 API Server 与 Webhook 服务器之间的标准通信协议。请求中包含 object(目标资源)、oldObject(更新前的资源)、userInfo(请求用户信息)等字段。

3.3 Mutating 与 Validating Webhook 的对比

两种 Webhook 的核心区别在于执行时机与职责:

对比维度 Mutating Webhook Validating Webhook
执行顺序 先执行(在 Validating 之前) 后执行(在 Mutating 之后)
主要职责 修改/注入资源对象的字段(如设置默认值、注入 Sidecar) 校验资源对象的合法性(如检查命名规范、配额限制)
对请求的影响 可以修改请求中的对象内容 只能允许或拒绝请求,不能修改对象
典型场景 自动注入 Istio Sidecar、设置 Pod 默认资源限制 校验 Pod 是否使用了禁止的镜像仓库、检查 Deployment 副本数是否在允许范围内
失败策略 可配置 failurePolicy: Fail 或 Ignore 可配置 failurePolicy: Fail 或 Ignore
配置资源 MutatingWebhookConfiguration ValidatingWebhookConfiguration

3.4 两种 Webhook 的协同工作流程

在同一个资源请求中,Mutating 和 Validating Webhook 可以协同工作,形成“先修改、后校验”的流水线。这种设计确保了校验逻辑能够基于最终的对象状态进行判断。

Mutating 与 Validating Webhook 协同流程 API 请求进入 Mutating Webhook 列表(按顺序执行) Webhook-A: 注入默认标签 → Webhook-B: 设置资源限制 → Webhook-C: 注入 Sidecar 每个 Webhook 可以修改对象,修改后的对象传递给下一个 Webhook Validating Webhook 列表(按顺序执行) Webhook-D: 校验命名规范 → Webhook-E: 校验配额 → Webhook-F: 校验安全策略 每个 Webhook 只能允许或拒绝,不能修改对象 资源持久化到 etcd 拒绝请求

3.5 配置示例:MutatingWebhookConfiguration

以下是一个典型的 MutatingWebhookConfiguration 配置片段,用于注入默认资源限制:

apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
  name: "resource-limits-injector.example.com"
webhooks:
- name: "resource-limits.injector.example.com"
  clientConfig:
    service:
      namespace: "webhook-system"
      name: "resource-limits-webhook"
      path: "/mutate"
    caBundle: "LS0tLS1CRUdJTiBDRV...=="
  rules:
  - operations: ["CREATE"]
    apiGroups: [""]
    apiVersions: ["v1"]
    resources: ["pods"]
  admissionReviewVersions: ["v1", "v1beta1"]
  sideEffects: None
  timeoutSeconds: 5
  failurePolicy: Fail
  reinvocationPolicy: IfNeeded
  objectSelector:
    matchLabels:
      inject-resource-limits: "true"

3.6 配置示例:ValidatingWebhookConfiguration

以下是一个典型的 ValidatingWebhookConfiguration 配置片段,用于校验 Pod 是否使用了禁止的镜像仓库:

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
  name: "image-registry-validator.example.com"
webhooks:
- name: "image-registry.validator.example.com"
  clientConfig:
    url: "https://validator.example.com/validate"
    caBundle: "LS0tLS1CRUdJTiBDRV...=="
  rules:
  - operations: ["CREATE", "UPDATE"]
    apiGroups: [""]
    apiVersions: ["v1"]
    resources: ["pods"]
  admissionReviewVersions: ["v1", "v1beta1"]
  sideEffects: None
  timeoutSeconds: 3
  failurePolicy: Fail
  namespaceSelector:
    matchExpressions:
    - key: "kubernetes.io/metadata.name"
      operator: NotIn
      values: ["kube-system", "webhook-system"]

重要注意事项:

  • 循环依赖风险:Webhook 服务本身不能触发自身的准入控制,否则会导致死锁。建议将 Webhook 部署在排除 Webhook 检查的命名空间中。
  • 超时设置:Webhook 的 timeoutSeconds 建议设置在 5 秒以内,避免阻塞 API Server 的请求处理。
  • 失败策略:生产环境建议将关键校验的 failurePolicy 设置为 Fail,防止 Webhook 服务不可用时绕过安全策略。
  • 幂等性:Mutating Webhook 应保证幂等性,因为同一对象可能被多次调用(如 reinvocationPolicy: IfNeeded)。

3.7 容量规划视角下的准入控制影响

从容量规划的角度,准入控制机制会引入额外的延迟和资源消耗:

  • API Server 负载:每个准入 Webhook 调用都会增加 API Server 的 CPU 和内存开销,尤其是在高并发创建 Pod 的场景下。
  • 网络延迟:Webhook 服务与 API Server 之间的网络往返时间(RTT)会直接影响请求处理延迟。
  • Webhook 服务容量:Webhook 服务本身需要足够的副本数和资源配额,以应对突发流量。

容量规划建议:

  • 监控 API Server 的 admission_webhook_request_duration_seconds 指标,识别慢 Webhook。
  • 为 Webhook 服务设置 HorizontalPodAutoscaler,根据请求量自动扩缩容。
  • 在集群规模较大时,考虑将非关键 Webhook 的 failurePolicy 设置为 Ignore,避免级联故障。
  • 使用 objectSelector 和 namespaceSelector 缩小 Webhook 的生效范围,减少不必要的调用。