审视Kubernetes的Admission Webhook和Kyverno的策略管理结构,会发现某些资源无法通过Kyverno策略进行验证或修改。其中最典型的例子就是ValidatingWebhookConfiguration和MutatingWebhookConfiguration。
本文将深入探讨这一现象的原因,解释为何需要这样的设计,以及在实际操作中可以考虑哪些替代方案。

https://kyverno.io/docs/introduction/how-kyverno-works/
🧩 首先,什么是Admission Controller?
所有进入Kubernetes API服务器的请求都会经过多个阶段。
典型的过程如下:
- Authentication (认证) – 谁发出了请求?
- Authorization (授权) – 请求是否被允许?
- 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只执行以下步骤:
- 在etcd存储前执行基本模式验证
- 检查已注册的Admission Webhook列表(对于MutatingWebhookConfiguration、ValidatingWebhookConfiguration类型,跳过调用)
- 将资源提交到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配置资源并非简单的限制,
而是为了系统稳定性和安全而设的必要防线。
发表回复