Kubernetes ValidatingAdmissionPolicy 怎样减少准入 Webhook 依赖
来源:17golang原创
时间:2026-10-29 06:24:44 355浏览 收藏
我第一次认真拆准入 Webhook,是因为一个看似很小的校验规则也要经过独立服务、证书、超时和重试。规则本身只是“Deployment 的副本数不能超过某个值”,却把一次 API 请求变成了对外部服务可用性的依赖。
如果校验只需要读取请求对象,判断字段、标签、命名空间或用户信息,并返回允许或拒绝,那么 Kubernetes 的 ValidatingAdmissionPolicy 往往更合适。它用 CEL 在 API 服务器侧做声明式校验,再由 ValidatingAdmissionPolicyBinding 决定作用范围和处置动作。这样可以减少一部分 Webhook,但不是把所有 Webhook 都替换掉。
判断标准很简单:规则能否仅凭 Admission 请求及声明好的参数完成?能,就优先考虑 ValidatingAdmissionPolicy;需要调用外部系统、修改对象或执行复杂副作用,就保留相应的 Webhook 或其他扩展机制。
官方地址:https://kubernetes.io/docs/reference/access-authn-authz/validating-admission-policy/
先把“校验规则”和“外部能力”分开
ValidatingAdmissionPolicy 适合的是确定性的验证:字段是否存在、数值是否在范围内、标签组合是否满足约束、请求者是否属于某个用户组,以及对象和旧对象之间是否满足关系。CEL 表达式可以访问 Admission 请求中的对象字段,Binding 再把策略绑定到具体资源和命名空间。
我会先把旧 Webhook 的逻辑分成三类:
| 逻辑类型 | 更适合的承载方式 | 判断理由 |
|---|---|---|
| 只读请求对象的字段校验 | ValidatingAdmissionPolicy | 不需要网络调用,规则可以声明化 |
| 依赖外部 CMDB、镜像服务或授权中心 | 保留 Webhook | 校验结果依赖 API 服务器之外的数据 |
| 需要修改对象内容 | 使用对应的变更机制 | ValidatingAdmissionPolicy 的职责是验证,不是改写对象 |
| 需要副作用或复杂状态机 | 保留专用服务 | 不应把外部流程硬塞进 CEL |

策略负责写规则,Binding 负责决定在哪里生效
一个常见误区是只创建 ValidatingAdmissionPolicy,然后期待它自动拦截请求。官方文档明确要求至少有策略和对应的 ValidatingAdmissionPolicyBinding,Binding 还需要配置一个或多个 validationActions。
下面这个例子只限制带有 team.example.com/owner 标签的 Deployment,并把副本数上限写成策略规则。代码中的注释只解释关键配置,便于后续维护。
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
name: deployment-replica-limit
spec:
failurePolicy: Fail # CEL 或策略配置出错时拒绝请求,适合必须守住的硬约束
matchConstraints:
resourceRules:
- apiGroups: ["apps"]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"] # 只检查创建和更新,不影响读取
resources: ["deployments"]
validations:
- expression: "object.spec.replicas
这里的拆分很重要:策略描述“什么算不合规”,Binding 描述“对谁生效以及失败后怎么处理”。如果一开始不想改变发布链路,可以把动作先设成 Warn 或 Audit,观察规则命中范围后再切换到 Deny。官方支持的动作包括 Deny、Warn 和 Audit,其中 Deny 与 Warn 不应同时使用。
用 CEL 和 matchConditions 收窄误伤范围
外部 Webhook 难维护,常常不是规则太复杂,而是匹配范围太宽。迁移到策略后,我更愿意先缩小资源、操作和命名空间,再用 matchConditions 过滤系统请求。所有匹配条件都为真时,策略才会继续评估。
spec:
matchConditions:
- name: exclude-leases # 避免把租约心跳纳入业务策略
expression: "request.resource.group != 'coordination.k8s.io' || request.resource.resource != 'leases'"
- name: exclude-node-users # 节点身份的系统请求不套用团队业务规则
expression: "!(\"system:nodes\" in request.userInfo.groups)"
validations:
- expression: "has(object.metadata.labels) && 'team.example.com/owner' in object.metadata.labels"
message: "Deployment 必须带有 owner 标签"
这里要特别留意故障策略。failurePolicy: Fail 表示策略配置错误或 CEL 评估出错时拒绝请求;Ignore 则让请求继续,但跳过这次策略。对核心安全约束,我会选择 Fail 并把表达式写得更窄;对试运行或非关键治理规则,可以先用 Ignore 或通过 Binding 使用 Warn、Audit。
需要不同环境阈值时,把参数放进 Binding
如果开发、测试、生产的阈值不同,不必复制三份 CEL。策略可以声明 paramKind,Binding 通过 paramRef 找到参数资源,表达式使用 params 读取阈值。这样规则保持稳定,环境差异落在参数对象和 Binding 范围上。
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
name: deployment-replica-limit-by-environment
spec:
failurePolicy: Fail # 参数或表达式出错时不放行,避免静默绕过限制
paramKind:
apiVersion: rules.example.com/v1
kind: ReplicaLimit
matchConstraints:
resourceRules:
- apiGroups: ["apps"]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["deployments"]
validations:
- expression: "object.spec.replicas
parameterNotFoundAction 不能省略思考:Allow 会把找不到参数当成通过,Deny 会让它进入策略的故障处理路径。对生产限制来说,参数对象丢失通常比一次请求失败更值得暴露,因此我更倾向显式使用 Deny,并给参数资源配置清楚的权限与生命周期。

减少 Webhook 依赖时,别把边界推得太远
ValidatingAdmissionPolicy 最适合“请求进来后,根据已知字段给出确定判断”的场景。它不能替代所有准入扩展,也不应该为了减少服务数量而承载外部查询或复杂副作用。
- 可以优先迁移:副本数、资源字段、标签组合、命名空间范围、用户组和对象新旧值关系等纯校验。
- 谨慎迁移:需要大量参数、复杂表达式或跨团队维护的策略。先用 Warn/Audit 观察,再决定是否 Deny。
- 保留 Webhook:需要查外部数据库、镜像签名服务、CMDB、实时配额,或者需要修改对象和触发副作用的逻辑。
我的落地清单是:先盘点旧 Webhook 的每条规则;为每条规则标出数据来源和失败影响;把纯校验拆成策略与 Binding;先用小范围命名空间和非阻断动作观察;最后才扩大范围并给关键规则设置明确的 failurePolicy 和参数缺失策略。这样减少的是不必要的网络依赖与运维面,而不是把 Webhook 当成必须消失的技术。
常见问题
只创建 ValidatingAdmissionPolicy 为什么没有效果?
因为还需要对应的 ValidatingAdmissionPolicyBinding,Binding 至少要指定 policyName 和 validationActions,并按需要设置资源或命名空间范围。
ValidatingAdmissionPolicy 能调用外部 HTTP 服务吗?
不要把它当作外部调用机制。它适合基于请求和声明参数做 CEL 校验;需要外部数据时,应评估保留 Webhook 或调整数据注入方式。
failurePolicy 和 validationActions 有什么区别?
failurePolicy 处理策略配置或表达式评估错误;validationActions 处理校验结果不满足时如何反馈,包括拒绝、警告或写入审计。
-
214 收藏
-
Golang · Go教程 | 4个月前 | 性能优化 · kubernetes · Go教程 · 生产实践 · Go1.25 · golang Go Kubernetes 性能优化 GOMAXPROCS473 收藏
-
234 收藏
-
144 收藏
-
Golang · Go教程 | 2个月前 | 容器 · go · 性能 · kubernetes · 运行时 · Kubernetes GOMAXPROCS cgroup Go 1.25 容器 CPU 限额438 收藏
-
123 收藏
-
125 收藏
-
170 收藏
-
331 收藏
-
307 收藏
-
161 收藏
-
344 收藏
-
130 收藏
-
416 收藏
-
257 收藏
-
497 收藏
-
284 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习