准入控制(Webhook)
本教程共 65 篇 · 第 57 篇 · 更新于 2026-08-14 · 约 12 分钟阅读
本节目标:理解准入控制在请求链路中的位置,掌握 Mutating 与 Validating 两类 Webhook 的区别,并知道怎么注册一个准入 Webhook。
你提交一个 YAML,kubectl 发出请求,Kubernetes 就立刻创建资源了吗?不是。请求在通过认证、鉴权之后,还要经过一道”准入控制”的检查关卡。很多安全策略、默认值注入,都是在这里完成的。
57-1 准入控制做什么
认证解决”你是谁”,鉴权解决”你能不能做”,而准入控制处理的是”你提交的内容合不合法、要不要补点东西”。
它只对创建、更新、删除、连接这类”写操作”生效,对读操作无效。而且 Kubernetes 可以同时开启多个准入插件,请求必须被所有插件放行,才算通过。
早期 Kubernetes 有一堆内建插件,比如限制资源配额的 ResourceQuota、自动加默认限制的 LimitRanger、自动建 ServiceAccount 的 ServiceAccount 插件。这些仍然在用,但灵活性有限。更灵活、可编程的是 Webhook。
Note从 v1.25 起,PodSecurityPolicy(PSP)已被移除。替代它的是 Pod 安全标准(PSS)与 Pod 安全准入(PSA)。写新内容时不要再用 PSP 了。
57-2 两类 Webhook
可编程的准入控制主要靠两个插件:
- MutatingAdmissionWebhook(变更性):在对象真正入库前,修改它的内容。比如自动给所有 Pod 注入一个 sidecar、自动补上安全上下文。多个变更 Webhook 按顺序依次执行。
- ValidatingAdmissionWebhook(校验性):只检查、不修改。比如强制要求所有 Pod 都带某个标签、禁止用了 latest 镜像。多个校验 Webhook 并行调用,任意一个拒绝,请求就失败。
一个常见组合:先用 Mutating 注入默认值,再用 Validating 做最终合规检查。这样两道关卡配合,既友好又严格。
57-3 它是怎么工作的
Webhook 本质上是一个你自己的 HTTPS 服务。当 API 服务器收到符合条件的请求,会把对象内容打包成 AdmissionReview 发给你的服务,你的服务返回”放行”还是”拒绝”。
注册时,你要告诉 API 服务器:哪些资源、哪些操作要触发这个 Webhook。下面是一个校验 Webhook 的片段:
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
name: enforce-user-namespaces
webhooks:
- name: usernamespace.security.example.com
admissionReviewVersions: ["v1"]
rules:
- operations: ["CREATE", "UPDATE"]
apiGroups: [""]
apiVersions: ["v1"]
resources: ["pods"]
clientConfig:
service:
name: usernamespace-webhook
namespace: security-system
path: "/validate"
rules 决定了拦截范围:这里只拦 Pod 的创建和更新。clientConfig 指向集群内一个 Service,Webhook 服务就跑在那后面。
WarningWebhook 服务必须启用 TLS,并且要通过
caBundle向 API 服务器证明身份。更关键的是:Webhook 一旦配置,它出问题会直接卡住整个集群的对应请求。所以 failurePolicy 要想清楚——设为 Fail 就是”连不上就拒绝”,设为 Ignore 则是”连不上就放行”。生产环境对关键校验通常选 Fail,但要保证 Webhook 高可用。
57-4 一个变更 Webhook 的例子
变更 Webhook 自动给符合条件的 Pod 开启某项能力,比如自动加上用户命名空间配置:
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: auto-usernamespace
webhooks:
- name: auto-usernamespace.security.example.com
admissionReviewVersions: ["v1"]
rules:
- operations: ["CREATE"]
apiGroups: [""]
apiVersions: ["v1"]
resources: ["pods"]
namespaceSelector:
matchLabels:
tenant: "true"
clientConfig:
service:
name: usernamespace-mutator
namespace: security-system
path: "/mutate"
注意这里的 namespaceSelector:只有打了 tenant: "true" 标签的命名空间里的 Pod 才会被处理。这就是用标签精确控制影响范围。
57-5 典型使用场景
Webhook 能做的事很多:
- 安全加固:禁止特权容器、强制只读根文件系统、拦截 latest 镜像。
- 合规检查:要求资源必须带成本中心标签、必须设资源限制。
- 自动注入:给所有 Pod 加 sidecar、自动注入代理配置。
- 默认填充:给没写资源的 Pod 补上默认 CPU/内存请求。
Tip想快速体验,可以看看 cert-manager、Istio 这类项目:cert-manager 用准入 Webhook 做证书 CR 的校验与默认值注入,Istio 用变更 Webhook 自动注入 sidecar。看它们的配置比读文档更直观。
57-6 注意的事项
写准入 Webhook 有几个坑:
- 性能:每个相关请求都要调你的服务,延迟要低,否则拖慢整个 API。
- 可用性:Webhook 挂了,集群对应操作就卡住。务必做多副本和超时保护。
- 环路:你的 Webhook 自身创建的资源,可能又触发自己,造成死循环。要用标签或注解跳过自身。
- 幂等:请求可能重试,处理逻辑要能重复执行而不出错。
一句话记住:准入控制是”请求进门前最后一道安检”,Webhook 让你能把任意自定义规则接到这道门上。用好了是安全利器,用不好会拖垮整个集群。