4. K8s 准入控制机制

准入控制(Admission Control)是 Kubernetes API Server 在请求经过认证与授权之后、对象被持久化到 etcd 之前的一道关键拦截层。它允许集群管理员通过插件化的方式对资源请求进行校验、修改或拒绝,是实现安全策略、资源配额、容量优化和合规治理的核心枢纽。

核心定位:准入控制器是 API Server 请求链路的最后一道内置防线,位于认证(Authentication)→ 授权(Authorization)→ 准入控制(Admission Control)→ 持久化(etcd)之间。

4.1 准入控制器概念

准入控制器本质上是一个拦截并处理 Kubernetes API 请求的插件。当用户通过 kubectl、客户端库或自动化工具向 API Server 发送资源创建、更新、删除请求时,请求会依次经过以下阶段:

  1. 认证(Authentication):验证请求者身份(如证书、、用户名/密码)。
  2. 授权(Authorization):判断请求者是否有权限执行该操作(RBAC/ABAC)。
  3. 准入控制(Admission Control):对请求内容进行语义检查、默认值注入或策略拦截。
  4. 持久化(etcd):将最终对象写入存储。

准入控制器可以执行两类操作:

  • 变更(Mutating):在对象被持久化之前修改其字段,例如注入 Sidecar 容器、设置默认资源限制、添加标签或注解。
  • 验证(Validating):检查对象是否符合集群策略,例如禁止使用特权容器、校验 Pod 资源请求是否超过配额、拒绝不符合安全上下文的部署。
最佳实践:变更控制器先于验证控制器执行。如果多个变更控制器对同一字段进行修改,后执行的控制器可能覆盖前者的结果,因此控制器执行顺序至关重要。

4.2 Mutating 与 Validating 控制器

Kubernetes 将准入控制器分为两大类,它们在请求处理管道中的执行顺序和职责不同:

特性 Mutating 准入控制器 Validating 准入控制器
执行顺序 先执行(Mutating 阶段) 后执行(Validating 阶段)
核心功能 修改请求对象(注入、补全、转换) 校验请求对象(拒绝、警告、审计)
典型场景 自动注入 Istio Sidecar、设置默认资源请求/限制、添加节点亲和性 禁止使用 latest 镜像标签、校验 Pod 安全策略、检查资源配额
失败行为 变更失败 → 请求被拒绝,不进入 Validating 阶段 校验失败 → 请求被拒绝,不写入 etcd
实现方式 内置控制器 + MutatingAdmissionWebhook 内置控制器 + ValidatingAdmissionWebhook

下图展示了 Mutating 与 Validating 控制器在 API 请求处理管道中的位置与协作关系:

Mutating 与 Validating 准入控制器执行流程 Mutating 与 Validating 准入控制器执行流程 API 请求 认证 授权 Mutating 准入 (修改对象) Validating 准入 (校验对象) etcd 持久化 请求被拒绝 执行顺序:Mutating → Validating 任一阶段失败,请求立即被拒绝,不进入下一阶段

4.3 内置准入控制器列表

Kubernetes 内置了数十个准入控制器,覆盖安全、资源管理、存储、网络等多个领域。以下列出在生产环境中最常用且与容量优化、安全加固强相关的控制器:

控制器名称 类型 核心功能 容量优化关联
LimitRanger Mutating + Validating 为未设置资源请求/限制的 Pod 注入默认值,并校验是否超出 LimitRange 范围 防止 Pod 无限制消耗节点资源,保障容量可预测性
ResourceQuota Validating 校验 Namespace 级别的资源总量是否超出配额(CPU、内存、存储、对象数量) 防止单个 Namespace 过度抢占集群容量
PodNodeSelector Mutating + Validating 强制 Pod 使用 Namespace 级别的节点选择器,限制调度范围 引导 Pod 到特定节点池,优化资源利用率
PodTolerationRestriction Mutating + Validating 限制 Pod 可以使用的容忍度,防止调度到不期望的节点 配合污点策略实现节点隔离与容量预留
Priority Mutating 为未设置优先级类的 Pod 注入默认优先级 确保高优工作负载在资源竞争时获得调度保障
PodSecurity Validating 根据 Pod Security Standards(特权、基线、受限)校验 Pod 安全上下文 避免特权容器引发安全风险导致节点不可用
NodeRestriction Validating 限制 kubelet 只能修改自身节点及绑定到自身的 Pod 防止节点伪装篡改容量数据
StorageObjectInUseProtection Validating 防止删除正在被 Pod 使用的 PVC 或 PV 避免存储资源意外释放导致容量浪费
容量优化关键提醒:在生产集群中,LimitRanger 和 ResourceQuota 必须同时启用。仅启用 LimitRanger 而不设置 ResourceQuota,单个 Namespace 仍可能通过创建大量 Pod 耗尽集群容量;反之,仅启用 ResourceQuota 而不设置 LimitRanger,未设置资源限制的 Pod 可能因默认值缺失导致调度失败或资源争抢。

4.4 准入控制器启用与配置

准入控制器通过 API Server 的启动参数 --enable-admission-plugins 和 --disable-admission-plugins 进行管理。在 kubeadm 部署的集群中,配置文件位于 /etc/kubernetes/manifests/kube-apiserver.yaml。

推荐的生产环境准入控制器组合(容量优化视角):

--enable-admission-plugins=NamespaceLifecycle,LimitRanger,ResourceQuota,
PodNodeSelector,PodTolerationRestriction,Priority,PodSecurity,
NodeRestriction,StorageObjectInUseProtection,PersistentVolumeClaimResize,
MutatingAdmissionWebhook,ValidatingAdmissionWebhook
性能考量:每个准入控制器都会增加 API 请求的延迟。对于延迟敏感场景,建议将 MutatingAdmissionWebhook 和 ValidatingAdmissionWebhook 的超时时间设置为 5-10 秒,并启用 failurePolicy: Fail 以确保关键策略不被绕过。同时,避免启用不必要的控制器(如 AlwaysPullImages 在非安全敏感环境可关闭)。

下图展示了内置准入控制器在集群中的分层架构与协作关系:

内置准入控制器分层架构 内置准入控制器分层架构 资源管理层 LimitRanger ResourceQuota Priority 调度与拓扑层 PodNodeSelector PodTolerationRestriction NodeRestriction 安全策略层 PodSecurity SecurityContextDeny AlwaysPullImages 存储管理层 StorageObjectInUseProtection PersistentVolumeClaimResize Webhook 扩展层 MutatingAdmissionWebhook ValidatingAdmissionWebhook 生命周期层 NamespaceLifecycle EventRateLimit 各层控制器按顺序执行,资源管理 → 调度拓扑 → 安全 → 存储 → Webhook → 生命周期

4.5 准入控制与容量优化的关联

在容量优化实践中,准入控制器扮演着“守门员”角色,从以下维度直接影响集群容量:

  • 资源规范化:LimitRanger 确保每个 Pod 都携带明确的资源请求与限制,避免“无限制 Pod”导致的节点过载。
  • 配额治理:ResourceQuota 在 Namespace 级别设置硬上限,防止单个团队或应用无节制消耗集群容量。
  • 调度引导:PodNodeSelector 和 PodTolerationRestriction 将工作负载引导到合适的节点池,避免资源碎片化。
  • 优先级保障:Priority 控制器确保关键业务 Pod 在资源紧张时获得调度优先权,避免容量争抢导致核心服务降级。
  • 安全加固:PodSecurity 防止特权容器运行,避免因安全漏洞导致节点被攻陷进而影响集群整体容量。
容量优化检查清单:
✅ 是否启用了 LimitRanger 并为所有 Namespace 配置了默认资源限制?
✅ 是否启用了 ResourceQuota 并为每个 Namespace 设置了 CPU/内存/存储配额?
✅ 是否启用了 Priority 并为关键工作负载设置了高优先级类?
✅ 是否启用了 PodNodeSelector 或 PodTolerationRestriction 来引导调度?
✅ 是否启用了 PodSecurity 并设置为 Baseline 或 Restricted 模式?