Kubernetes 准入控制基础:Admission Controller 工作原理
准入控制(Admission Control)是 Kubernetes API Server 请求处理链中的关键环节,位于认证(Authentication)与授权(Authorization)之后、对象持久化(etcd 存储)之前。它拦截所有对 API Server 的写请求(Create、Update、Delete),在对象被持久化前执行校验、修改或拒绝操作,是集群安全策略与租户隔离的“最后一道防线”。
1. 准入控制工作原理
Kubernetes API Server 处理请求的完整流程如下:
- 认证(Authentication):验证请求发起者的身份(如 TLS 证书、、用户名/密码)。
- 授权(Authorization):基于 RBAC、ABAC 等策略判断请求者是否有权执行操作。
- 准入控制(Admission Control):对请求对象进行拦截处理,包含两个阶段:
- 变更(Mutating)阶段:先执行 MutatingAdmissionWebhook,可修改请求对象(如注入 Sidecar、设置默认值)。
- 验证(Validating)阶段:再执行 ValidatingAdmissionWebhook,只校验不修改,拒绝不符合策略的请求。
- 持久化(Persistence):通过准入控制后,对象被写入 etcd 存储。
关键理解:准入控制器是同步调用的,每个请求必须等待所有配置的准入控制器返回结果后,才会继续后续流程。这意味着准入控制器的性能直接影响 API Server 的响应延迟。
2. MutatingWebhookConfiguration 与 ValidatingWebhookConfiguration 的区别
Kubernetes 提供了两种动态准入控制 Webhook 配置资源,分别对应变更和验证两个阶段。它们的核心区别如下:
| 对比维度 | MutatingWebhookConfiguration | ValidatingWebhookConfiguration |
|---|---|---|
| 执行阶段 | 变更阶段(Mutating),先执行 | 验证阶段(Validating),后执行 |
| 核心能力 | 可修改请求对象(如注入 Sidecar、设置默认值、修正字段) | 只校验请求对象,不可修改(如检查命名空间标签、资源配额) |
| 响应要求 | 必须返回 JSON Patch 格式的修改内容 | 只需返回 allowed(true/false)及拒绝原因 |
| 幂等性要求 | 必须幂等,避免重复修改导致对象不一致 | 无幂等性要求,但需保证校验逻辑稳定 |
| 典型场景 | 自动注入 Istio Sidecar、设置 Pod 安全上下文默认值 | 校验 Pod 是否使用允许的镜像仓库、检查资源限制 |
| 失败策略 | 支持 failurePolicy: Ignore(忽略失败)或 Fail(拒绝请求) | 同左,但通常建议关键校验使用 Fail |
重要提醒:MutatingWebhook 的修改结果会作为 ValidatingWebhook 的输入。如果 MutatingWebhook 修改后的对象仍不满足 ValidatingWebhook 的校验规则,请求最终会被拒绝。因此,两个阶段的 Webhook 必须协同设计,避免冲突。
3. Webhook 配置核心字段
两种 Webhook 配置的 YAML 结构基本一致,主要区别在于 apiVersion 和 kind。以下是关键字段说明:
| 字段路径 | 说明 | 示例值 |
|---|---|---|
clientConfig.service |
Webhook 后端服务的 Kubernetes Service 引用 | namespace: webhook-system, name: admission-webhook |
clientConfig.caBundle |
验证 Webhook 服务端 TLS 证书的 CA 证书(Base64 编码) | LS0tLS1CRUdJTiBDRV...== |
rules |
匹配哪些资源、操作、API 组触发 Webhook | apiGroups: [""], apiVersions: ["v1"], resources: ["pods"], operations: ["CREATE"] |
failurePolicy |
Webhook 调用失败时的处理策略 | Fail 或 Ignore |
sideEffects |
Webhook 是否有副作用(影响其他系统) | None 或 NoneOnDryRun |
timeoutSeconds |
Webhook 调用超时时间(默认 10 秒,最大 30 秒) | 5 |
reinvocationPolicy |
(仅 Mutating)是否允许在对象被其他 Webhook 修改后再次调用 | IfNeeded 或 Never |
4. 两种 Webhook 的协同工作流程
在实际集群中,MutatingWebhook 和 ValidatingWebhook 通常配合使用,形成“先修改、后校验”的完整准入控制链。以下是一个典型的 Pod 创建请求处理流程:
- 步骤 1:用户提交 Pod 创建请求(YAML 中可能缺少某些字段)。
- 步骤 2:MutatingWebhook 拦截请求,自动注入 Sidecar 容器、设置默认资源限制、添加安全上下文。
- 步骤 3:ValidatingWebhook 拦截修改后的 Pod 对象,校验是否满足租户隔离策略(如命名空间标签、镜像来源白名单)。
- 步骤 4:校验通过后,Pod 对象被持久化到 etcd,调度器开始调度。
5. 实践建议与避坑指南
最佳实践:
- 幂等性设计:MutatingWebhook 必须保证多次调用同一对象结果一致,避免 Sidecar 被重复注入。
- 超时控制:将
timeoutSeconds设置为合理值(如 5 秒),避免 Webhook 超时导致请求阻塞。 - 失败策略选择:关键安全校验(如镜像白名单)使用
failurePolicy: Fail;非关键注入(如添加标签)可使用Ignore。 - 日志与监控:Webhook 服务必须记录详细的请求日志,并暴露 Prometheus 指标,便于排查准入控制问题。
常见陷阱:
- 循环调用:Webhook 服务自身创建 Pod 时可能触发自身 Webhook,导致死循环。需通过
namespaceSelector或objectSelector排除 Webhook 所在命名空间。 - 证书过期:
caBundle中的 CA 证书过期会导致 API Server 无法验证 Webhook 服务端 TLS,所有准入请求失败。建议使用 cert-manager 自动管理证书。 - 资源冲突:多个 MutatingWebhook 可能修改同一字段,执行顺序由
webhooks[].rules的匹配优先级决定,需通过reinvocationPolicy控制重入行为。