Kubernetes 中的 Mutating 与 Validating Webhooks
Source: Dev.to
什么是 Admission Controllers?
Admission Controller 是一段代码,它会在 身份验证和授权 之后、对象写入 etcd 之前 拦截对 Kubernetes API Server 的请求。
通俗来说:它们是 Kubernetes API 的中间件。
如果你运行:
kubectl apply -f deployment.yaml
请求的流转过程如下:
请求 → Authentication → Authorization → Mutating Admission → Schema Validation → Validating Admission → etcd
Admission Controllers 正好位于这条流水线的中间。
两类主要的 Admission 控制器
变更(Mutating)Admission 控制器
这些可以在请求被存储之前修改传入的请求。
常见示例:
- 添加默认标签
- 注入 sidecar 容器(例如使用 Istio)
- 添加默认资源限制
- 覆盖缺失的字段
变更控制器首先运行。它们接收你的原始对象并被允许对其进行更改。
验证(Validating)Admission 控制器
这些不能修改请求;它们只做出以下决定:
- 允许 ✅
- 拒绝 ❌
示例:
- 阻止特权容器
- 强制执行镜像仓库策略
- 验证必需标签
- 强制执行命名标准
验证控制器在变更之后运行,这意味着它们看到的是对象的最终版本。此顺序非常重要。
静态 vs. 动态 Admission 控制器
静态(内置)
这些随 Kubernetes 一起提供,并通过 API 服务器标志启用:
--enable-admission-plugins
常见的内置插件:
NamespaceLifecycleLimitRangerResourceQuotaServiceAccount
例如,NamespaceLifecycle 会阻止你在正在终止的命名空间中创建新资源。许多人认为的“核心 Kubernetes 行为”实际上是通过这些内置 admission 控制器实现的。
动态(基于 Webhook)
这些更灵活,包括:
MutatingAdmissionWebhookValidatingAdmissionWebhook
Kubernetes 不再将逻辑直接嵌入 API 服务器,而是调用外部 HTTPS 服务(Webhook),并询问:
- “这个请求可以吗?”
- “你想要修改什么吗?”
你可以使用任何能够提供 HTTPS 的语言实现自定义逻辑(Go、Python、Node 等)。这就是它强大的地方。
Source: …
为什么 Admission Controllers 很重要
在真实的集群中,大多数使用场景可以归为两类:安全 和 治理。
安全
Admission controller 可以在整个集群范围内强制执行安全基线。
示例:
- 阻止以 root 身份运行的容器
- 只允许来自可信仓库的镜像
- 强制只读根文件系统
- 防止使用
hostPath
例如,你可以拒绝任何包含以下内容的 Deployment:
securityContext:
privileged: true
仅此一项就能防止严重的安全风险。
治理与合规
它们还帮助强制组织标准:
- 命名约定
- 必需的标签
- 资源限制
- 副本数限制
例如,你可以强制要求每个 Deployment 必须包含:
labels:
environment: production
没有标签?不允许部署。简单而有效。
真实案例:Ingress 控制器
在安装像 F5 NGINX Ingress Controller 这样的 Ingress 控制器时,你会注意到它会创建:
MutatingWebhookConfigurationValidatingWebhookConfiguration
为什么?因为 Kubernetes 并不理解 NGINX 特有的配置逻辑。
该 Webhook:
- 验证 Ingress 注解
- 防止无效的配置
- 阻止错误的 NGINX 重载
- 保护生产流量
如果没有这一层,错误的 Ingress 定义可能会生成无效的 NGINX 配置,从而影响实时流量。Webhook 就是你的安全网。
Source: …
变更(Mutating)和验证(Validating)如何协同工作
假设你创建了如下的 Deployment:
replicas: 1
可能会发生的情况:
- 变更(mutating) webhook 将
replicas改为3。 - 验证(validating) webhook 检查
replicas是否不大于5。- 若符合要求 → 对象被存入 etcd。
这种分层方式确保:
- 应用默认值
- 强制执行策略
- 错误的配置永远不会进入集群状态
启用准入控制器
在 API 服务器上,使用以下方式启用它们:
--enable-admission-plugins=MutatingAdmissionWebhook,ValidatingAdmissionWebhook
验证 webhook 支持:
kubectl api-versions | grep admissionregistration.k8s.io
如果看到:
admissionregistration.k8s.io/v1
则表示可以继续。
编写自己的 Admission Controller
如果你想自己构建一个,以下是高级流程:
- 构建 HTTPS 服务
- 接受
AdmissionReview对象 - 返回
allowed: true/false- 可选:JSON patch(用于变更)
- 使用以下方式注册
MutatingWebhookConfiguration或ValidatingWebhookConfiguration
你的 webhook 必须:
- 使用 TLS
- 在集群内部可达
- 在配置中包含 CA 包
配置完成后,Kubernetes 将在每次创建、更新或删除匹配的资源时调用你的服务。
最后思考
Admission Controllers 是 Kubernetes 中最强大 — 且常被忽视 — 的功能之一。
它们在 API 服务器内部提供了一个可编程的控制层。
如果你在生产环境中运行 Kubernetes,却没有使用 Admission Controllers,那么你完全依赖开发者自行“做好事”。我们都知道这通常会怎样。
明智地使用它们 — 你的集群将变得更安全、更可预测。
