3. 内置准入控制器详解:常用内置准入控制器列表、功能说明

Kubernetes 内置了数十个准入控制器,它们被编译进 kube-apiserver 二进制文件中,无需额外安装即可启用。本章聚焦于与资源配额、命名空间隔离、安全策略及资源限制密切相关的核心内置控制器,帮助您理解其工作原理与配置方式。

3.1 常用内置准入控制器一览

下表列出了生产集群中最常启用且与策略即代码(Policy-as-Code)及资源配额模型集成最紧密的 6 个内置准入控制器。每个控制器在 API 请求处理链中扮演特定角色,按执行顺序排列。

控制器名称 类型 核心职责 影响资源 默认启用状态
NamespaceLifecycle Mutating + Validating 防止在删除中的命名空间创建资源;拒绝不存在的命名空间请求 所有命名空间资源 ✅ 是
LimitRanger Mutating + Validating 为未设置资源限制的 Pod 注入默认资源请求/限制;验证 Pod 资源不超出最小值/最大值 Pod、Container ✅ 是
ResourceQuota Validating 验证命名空间内资源总量不超过配额;拒绝超出配额的创建/更新请求 Pod、Service、PVC、ConfigMap 等 ✅ 是
PodSecurity Validating 根据 Pod Security Standards(基线/受限/特权)验证 Pod 安全上下文 Pod ✅ 是(v1.25+)
NodeRestriction Validating 限制 kubelet 只能修改自身节点及绑定到该节点的 Pod 对象 Node、Pod ✅ 是
MutatingAdmissionWebhook Mutating 调用外部 Webhook 对资源进行修改(注入 sidecar、设置标签等) 所有资源 ✅ 是
关键提示: 内置控制器与动态准入 Webhook 的核心区别在于:内置控制器是静态编译进 API Server 的,无法通过策略即代码工具(如 OPA/Gatekeeper)动态修改其行为;而 Webhook 控制器是策略引擎的入口点。理解内置控制器的边界,是设计资源配额模型的前提。

3.2 核心控制器功能详解

3.2.1 NamespaceLifecycle

该控制器确保命名空间的生命周期状态与资源创建操作一致。当命名空间处于 Terminating 状态时,所有创建新资源的请求都会被拒绝。同时,它也会验证请求中引用的命名空间是否真实存在,防止因命名空间不存在导致的悬空资源。

  • Mutating 行为: 无(仅验证)。
  • Validating 行为: 检查 namespace.spec.finalizers 与 namespace.status.phase。
  • 典型场景: 配合 ResourceQuota 实现租户隔离,确保删除命名空间时不会产生孤儿资源。

3.2.2 LimitRanger

LimitRanger 在 Pod 创建或更新时,为未显式设置资源请求(requests)或限制(limits)的容器注入默认值。它同时验证容器资源是否在命名空间定义的 min/max 范围内。

apiVersion: v1
kind: LimitRange
metadata:
  name: default-limits
  namespace: production
spec:
  limits:
  - max:
      cpu: "2"
      memory: "2Gi"
    min:
      cpu: "100m"
      memory: "128Mi"
    default:
      cpu: "500m"
      memory: "512Mi"
    defaultRequest:
      cpu: "200m"
      memory: "256Mi"
    type: Container
  • Mutating 行为: 为未设置 resources.requests 或 resources.limits 的容器注入默认值。
  • Validating 行为: 验证容器资源不超出 max 且不低于 min。
  • 与 ResourceQuota 的关系: LimitRanger 控制单个 Pod 的资源边界,ResourceQuota 控制命名空间内所有 Pod 的聚合资源总量。

3.2.3 ResourceQuota

ResourceQuota 是资源配额模型的核心执行者。它定义命名空间内可消耗的计算资源(CPU、内存)和对象数量(Pod、Service、PVC 等)的上限。当请求导致命名空间内任何资源总量超过配额时,API Server 会拒绝该请求。

apiVersion: v1
kind: ResourceQuota
metadata:
  name: compute-quota
  namespace: production
spec:
  hard:
    requests.cpu: "10"
    requests.memory: "20Gi"
    limits.cpu: "20"
    limits.memory: "40Gi"
    pods: "50"
    services: "10"
    persistentvolumeclaims: "5"
  • Validating 行为: 在请求处理链的后期(LimitRanger 之后)执行,确保聚合资源不超配额。
  • 作用域: 支持 BestEffort、NotBestEffort、Terminating、NotTerminating 等作用域,实现精细化的配额控制。
  • 与策略即代码的集成: ResourceQuota 是静态配额,而策略引擎(如 Gatekeeper)可以动态生成或覆盖配额约束,实现更灵活的配额模型。

3.2.4 PodSecurity

PodSecurity 控制器(自 Kubernetes v1.23 起 GA)替代了废弃的 PodSecurityPolicy。它根据预定义的 Pod Security Standards(Privileged、Baseline、Restricted)验证 Pod 的安全上下文,包括特权容器、主机网络、卷类型、Seccomp 配置等。

apiVersion: v1
kind: Namespace
metadata:
  name: secure-ns
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/audit: baseline
    pod-security.kubernetes.io/warn: baseline
  • Validating 行为: 根据命名空间标签 pod-security.kubernetes.io/enforce 定义的级别执行强制验证。
  • 三种模式: enforce(拒绝不符合的 Pod)、audit(记录审计日志但不拒绝)、warn(返回警告但不拒绝)。
  • 与资源配额的关系: PodSecurity 控制 Pod 的安全合规性,ResourceQuota 控制资源消耗量,两者共同构成安全与资源的双重准入防线。

3.3 内置准入控制器执行流程

下图展示了在 Pod 创建请求中,上述核心内置控制器的执行顺序与交互关系。注意 Mutating 控制器先于 Validating 控制器执行,且 ResourceQuota 在 LimitRanger 之后执行以获取准确的资源数值。

内置准入控制器执行流程(Pod 创建请求) API 请求进入 Mutating 阶段 MutatingAdmissionWebhook → LimitRanger Validating 阶段 NamespaceLifecycle → PodSecurity → ResourceQuota 验证通过? 拒绝请求 写入 etcd 执行顺序说明 1. Mutating 控制器先执行,注入默认值(LimitRanger)或修改资源(Webhook) 2. Validating 控制器后执行,NamespaceLifecycle → PodSecurity → ResourceQuota 依次验证

3.4 控制器之间的依赖与冲突

在集成资源配额模型时,必须理解控制器之间的隐式依赖关系,否则可能导致策略失效或意外拒绝。

依赖关系 说明 潜在问题
LimitRanger → ResourceQuota LimitRanger 先注入默认资源值,ResourceQuota 再基于注入后的值进行总量验证 若 LimitRanger 未启用,未设置资源限制的 Pod 可能绕过配额验证
NamespaceLifecycle → ResourceQuota NamespaceLifecycle 确保命名空间可用后,ResourceQuota 才执行 若 NamespaceLifecycle 被禁用,可能在 Terminating 命名空间中创建资源导致配额混乱
PodSecurity → ResourceQuota PodSecurity 先验证安全合规性,ResourceQuota 后验证资源总量 安全合规的 Pod 仍可能因资源不足被拒绝,需在配额中预留安全 Pod 的资源空间
常见陷阱: 在启用 ResourceQuota 但未启用 LimitRanger 的命名空间中,如果用户创建未设置 resources.requests 的 Pod,ResourceQuota 无法准确计算该 Pod 的资源消耗,可能导致配额验证失效。最佳实践是始终同时启用 LimitRanger 与 ResourceQuota。

3.5 内置控制器与策略即代码的协作模式

内置控制器提供基础准入能力,而策略即代码引擎(如 OPA/Gatekeeper、Kyverno)通过 MutatingAdmissionWebhook 和 ValidatingAdmissionWebhook 扩展准入能力。下图展示了这种分层协作架构。

内置控制器与策略即代码协作架构 内置准入控制器层(静态编译) NamespaceLifecycle | LimitRanger | ResourceQuota | PodSecurity | NodeRestriction 提供基础隔离、配额、安全与资源默认值 动态准入 Webhook 桥接层 MutatingAdmissionWebhook → 策略引擎注入 | ValidatingAdmissionWebhook → 策略引擎验证 策略即代码引擎层(动态扩展) OPA/Gatekeeper ConstraintTemplate | Kyverno ClusterPolicy | jsPolicy 实现自定义安全策略、动态配额、合规检查、资源标签注入 协作原则:内置控制器处理基础准入,策略引擎通过 Webhook 扩展高级策略,两者互补而非替代

3.6 生产环境启用建议

  • 始终启用核心控制器: NamespaceLifecycle、LimitRanger、ResourceQuota、PodSecurity 应作为生产集群的强制启用项,不要轻易关闭。
  • 控制器顺序不可更改: 内置控制器的执行顺序由 API Server 内部硬编码,无法通过配置调整。设计策略时需假设 LimitRanger 在 ResourceQuota 之前执行。
  • Webhook 超时处理: 动态准入 Webhook 可能因网络或策略引擎故障导致超时。建议为 Webhook 设置合理的 timeoutSeconds(默认 30s),并配置 failurePolicy: Fail 或 failurePolicy: Ignore 以控制故障行为。
  • 审计与监控: 启用 --audit-log-path 记录所有准入决策,配合 kube-apiserver 的指标 apiserver_admission_webhook_rejection_count 监控 Webhook 拒绝率。
架构要点: 内置准入控制器是 Kubernetes 资源配额模型的第一道防线,策略即代码引擎是第二道动态防线。理解两者的执行顺序、依赖关系与协作模式,是设计可扩展、可审计的准入控制体系的基础。下一章将深入分析 ResourceQuota 控制器的内部实现与配额计算模型。