🚫 Kyverno为何无法控制ValidatingWebhookConfiguration和MutatingWebhookConfiguration?

审视Kubernetes的Admission Webhook和Kyverno的策略管理结构,会发现某些资源无法通过Kyverno策略进行验证或修改。其中最典型的例子就是ValidatingWebhookConfigurationMutatingWebhookConfiguration

本文将深入探讨这一现象的原因,解释为何需要这样的设计,以及在实际操作中可以考虑哪些替代方案。

https://kyverno.io/docs/introduction/how-kyverno-works/


🧩 首先,什么是Admission Controller?

所有进入Kubernetes API服务器的请求都会经过多个阶段。

典型的过程如下:

  1. Authentication (认证) – 谁发出了请求?
  2. Authorization (授权) – 请求是否被允许?
  3. Admission Control (准入控制) – 请求内容是否可以被修改(变异)或验证?

在Admission Controller阶段,有两个重要的子系统:

  • Mutating Admission Webhook: 可以“修改(mutating)”请求的资源
  • Validating Admission Webhook: “验证(validating)”请求资源的有效性

📘 也就是说,从API服务器的角度来看,当一个资源被创建或更新时,它会调用一个外部Webhook来询问:“这个资源可以吗?”或者“需要填充必要的字段吗?”


🧠 什么是Kyverno?

Kyverno是一个Kubernetes原生的策略引擎,它通过以下三种方式控制资源:

  • Validation Policy: 验证资源是否符合集群策略
  • Mutation Policy: 自动修改资源请求
  • Generation Policy: 在特定事件发生时生成其他资源

Kyverno内部作为Admission Webhook运行。

这意味着Kyverno自身也注册了独立的MutatingWebhookConfiguration和ValidatingWebhookConfiguration资源,从而介入所有资源请求的流程。


🚫 然而问题:Kyverno无法管理Kyverno自身的Webhook?

正是在这里,“循环依赖(circular dependency)”问题出现了。

在Kubernetes的Admission阶段,对于特定资源类型,即

ValidatingWebhookConfiguration和MutatingWebhookConfiguration资源,

Admission Webhook的调用会被跳过

换句话说,API服务器不会将与Webhook相关的资源发送给另一个Webhook。

原因很简单,但非常重要。


⚙️ 设计原因:防止循环Webhook调用(Circular Webhook Invocation)

如果Admission Webhook配置本身可以被另一个Admission Webhook验证或修改,可能会发生以下情况:

  • Kyverno尝试修改一个新的Webhook配置
  • 但这个行为本身又会触发Kyverno的Webhook调用
  • 结果,Webhook调用会不断地触发自身
  • 最终导致无限递归(Infinite recursion) 💥

Kubernetes设计者为了提前防止这种情况,设计了API服务器不将ValidatingWebhookConfiguration和MutatingWebhookConfiguration资源请求转发给Webhooks。

也就是说,在Admission阶段,这两个资源被完全作为例外处理。

因此,Kyverno甚至无法“看到”这些资源。


🔒 也存在安全原因

从安全角度来看,这个决定也至关重要。

如果Admission Webhook可以修改其他Webhook配置,就可能存在注入恶意配置的风险。

例如,如果攻击者可以通过Kyverno策略或其他MutatingWebhook自动创建自己的Webhook,那么拦截集群中所有API请求就成为可能。

这可能导致集群被攻陷(Cluster compromise) 级别的漏洞。

因此,从源头上阻止这种“自我变异(self-mutation)”是维护系统稳定性和安全的核心设计理念


👀 实际如何运作?

实际上,当使用kubectl apply创建或修改MutatingWebhookConfiguration时,kube-apiserver只执行以下步骤:

  1. 在etcd存储前执行基本模式验证
  2. 检查已注册的Admission Webhook列表(对于MutatingWebhookConfiguration、ValidatingWebhookConfiguration类型,跳过调用)
  3. 将资源提交到etcd

在此过程中,Kyverno没有机会观察或修改此请求。

查看Kyverno的日志,其他资源(如Deployment、Pod等)会作为Webhook请求进入,

但WebhookConfiguration相关的事件根本不会被检测到。


🧩 那么,是否完全无法通过策略进行控制?

仅凭Kyverno是无法实现的。但是,存在以下替代方案。

✅ 方法 1: 使用外部Admission Controller

可以自行实现Admission Webhook来监控WebhookConfiguration资源。然而,由于K8s自身的设计,无法“阻止更改”,仅限于审计(audit-only) 用途。

✅ 方法 2: Controller级别监控

通过Controller或Operator而非Kyverno,监控kube-apiserver将事件存储到etcd后的情况,一旦检测到不当的Webhook配置,立即进行恢复(mitigate)。

示例:使用基于Controller Runtime、Kubernetes Informer的Go应用程序构建“webhook-config watcher”。

✅ 方法 3: 使用RBAC保护

这是最实际和安全的方法。

MutatingWebhookConfiguration和ValidatingWebhookConfiguration资源是ClusterScope对象,因此应通过最小化编辑这些资源的权限(Role, ClusterRole)来实施管理员的访问控制。


⚠️ DevOps操作时的注意事项

在集群操作中,如果将Kyverno作为CI/CD管道中的自动化工具使用,有时可能会看到以下错误:

text

Error: Policy cannot be applied to resource type MutatingWebhookConfiguration

在这种情况下,这不是问题,而是正常行为 😀

Kyverno会按照设计忽略受限资源,不应强行尝试更改。


💡 总结

项目说明Kyverno策略应用情况

Deployment / Pod 通用资源 ✅ 可行
Namespace 通用集群资源 ✅ 可行
CustomResourceDefinition (CRD) 资源定义 ⚠️ 受限 (需要特殊配置)
MutatingWebhookConfiguration 准入系统配置 ❌ 不可行
ValidatingWebhookConfiguration 准入系统配置 ❌ 不可行

🔍 结论:信任边界的划分重于控制

Kubernetes的核心哲学强调“信任边界的划分(Separation of Trust)”而非“控制(Control)”。

Admission Webhook介入集群的核心部分,如果这个组件可以被另一个Webhook控制或验证,可能会威胁到系统的完整性。

因此,Kyverno无法管理Webhook配置资源并非简单的限制,

而是为了系统稳定性和安全而设的必要防线



Comments

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注