3. 传统准入控制机制回顾:Admission Webhook 的工作原理、Mutating 与 Validating Webhook 的区别、传统模式的痛点
在深入 Kyverno 的策略移植适配之前,有必要先厘清 Kubernetes 原生的准入控制机制。Admission Webhook 是 Kubernetes 1.9+ 引入的扩展机制,它允许集群管理员在资源被持久化到 etcd 之前,拦截并修改或验证请求。理解这一机制的工作原理、两种 Webhook 的差异以及传统模式的固有痛点,是后续评估 Kyverno 优势的基础。
3.1 Admission Webhook 的工作原理
Kubernetes API Server 在处理资源请求时,会经过一个严格的请求处理管线。Admission Webhook 位于身份认证(Authentication)和授权(Authorization)之后,对象持久化(etcd)之前。其核心流程如下:
核心流程: 用户/客户端 → API Server 认证 → 授权 → Mutating Admission Webhooks → 对象 Schema 验证 → Validating Admission Webhooks → 持久化到 etcd。
- 请求到达 API Server: 用户通过 kubectl、客户端库或 Dashboard 发起资源创建/更新/删除请求。
- 认证与授权: API Server 验证请求者身份(TLS 证书、 等),并检查 RBAC 权限。
- 准入控制链: 请求进入准入控制阶段。Kubernetes 内置了多种准入控制器(如 NamespaceLifecycle、ResourceQuota),同时支持通过 Admission Webhook 动态注册外部控制器。
- Webhook 调用: API Server 根据配置的
MutatingWebhookConfiguration和ValidatingWebhookConfiguration规则,向注册的 Webhook 服务发送 HTTP 请求(HTTPS 强制)。 - Webhook 响应: 外部服务处理请求,返回
allowed: true/false以及可选的patch操作(仅限 Mutating)。 - 最终持久化: 如果所有准入控制器均通过,对象被序列化并写入 etcd。
关键点: Webhook 是同步调用的。API Server 会等待所有配置的 Webhook 返回响应后,才会继续处理请求。这意味着 Webhook 的延迟会直接转化为 API Server 的请求延迟。
3.2 Mutating 与 Validating Webhook 的区别
两种 Webhook 在准入控制链中扮演不同角色,它们的核心差异体现在执行时机、功能范围和响应格式上。
| 对比维度 | Mutating Webhook | Validating Webhook |
|---|---|---|
| 执行顺序 | 先执行(在对象 Schema 验证之前) | 后执行(在对象 Schema 验证之后) |
| 核心功能 | 修改(Mutate)请求对象,例如注入 Sidecar、设置默认值、修正标签 | 验证(Validate)请求对象,例如检查镜像来源、强制安全策略、校验资源配额 |
| 响应格式 | 必须返回 allowed: true/false,并可返回 jsonPatch 操作 |
仅返回 allowed: true/false 及可选的拒绝原因 |
| 幂等性要求 | 必须幂等,因为同一对象可能被多次修改 | 无强制幂等要求,但建议保持确定性 |
| 典型场景 | Istio Sidecar 注入、资源标签标准化、默认资源限制设置 | Pod 安全策略检查、镜像签名验证、禁止特权容器 |
常见误区: 不要将业务逻辑验证放在 Mutating Webhook 中。Mutating Webhook 的主要职责是修改对象,而非验证。将验证逻辑放在 Mutating Webhook 中会导致执行顺序混乱,且难以调试。
3.3 传统模式的痛点
尽管 Admission Webhook 提供了强大的扩展能力,但在实际生产运维中,传统模式暴露出了三个核心痛点:延迟、稳定性和运维复杂度。
3.3.1 延迟:同步调用带来的性能瓶颈
- 请求串行化: API Server 必须等待所有 Webhook 返回响应,才能继续处理。如果某个 Webhook 响应慢(例如网络延迟、后端处理超时),整个 API Server 的吞吐量会急剧下降。
- 冷启动问题: Webhook 服务通常以 Pod 形式运行在集群内。当 Webhook 服务刚启动或扩缩容时,可能出现短暂的不可用或高延迟,导致 API Server 请求排队。
- 资源消耗: 每个 Webhook 调用都需要建立 HTTPS 连接、序列化/反序列化 AdmissionReview 对象,频繁的调用会消耗大量 CPU 和内存资源。
3.3.2 稳定性:单点故障与级联影响
- Webhook 故障导致集群不可用: 如果 Webhook 服务崩溃或网络不可达,API Server 默认行为是拒绝所有请求(除非配置了
failurePolicy: Ignore)。一个不稳定的 Webhook 可能导致整个集群的创建/更新操作瘫痪。 - 证书管理风险: Webhook 强制使用 HTTPS,证书过期或配置错误会导致 API Server 无法调用 Webhook,进而影响所有准入操作。
- 级联故障: 当 Webhook 服务依赖其他集群组件(如 ConfigMap、Secret)时,这些组件的故障会级联影响到 Webhook 的可用性。
3.3.3 运维复杂度:配置、调试与升级的挑战
- 配置繁琐: 每个 Webhook 都需要创建
MutatingWebhookConfiguration或ValidatingWebhookConfiguration资源,配置rules、clientConfig、namespaceSelector、objectSelector等参数,容易出错。 - 调试困难: 当 Webhook 拒绝请求时,API Server 返回的错误信息往往不够详细。开发者需要查看 Webhook 服务的日志,而日志可能分散在多个 Pod 中。
- 升级复杂: 更新 Webhook 逻辑需要重新构建镜像、滚动更新 Deployment,并确保新旧版本兼容。如果 Webhook 配置了
failurePolicy: Fail,升级期间的短暂不可用会直接影响集群操作。 - 策略分散: 每个 Webhook 服务通常只负责单一策略(如镜像检查、标签注入),导致策略管理分散在多个代码仓库和部署单元中,难以统一审计和治理。
传统模式痛点总结:
| 痛点维度 | 具体表现 | 影响范围 |
|---|---|---|
| 延迟 | 同步调用、冷启动、序列化开销 | API Server 吞吐量下降,用户请求超时 |
| 稳定性 | 单点故障、证书风险、级联故障 | 集群准入功能不可用,甚至整个集群不可用 |
| 运维复杂度 | 配置繁琐、调试困难、升级复杂、策略分散 | 运维成本高,策略治理困难,故障排查周期长 |