4. Kubernetes 准入控制器:Admission Webhook 原理、Mutating vs Validating Webhook、Webhook 配置示例
4.1 什么是准入控制器?
准入控制器(Admission Controller)是 Kubernetes API Server 请求链中的一道关键拦截层。当用户通过 kubectl、客户端库或 Dashboard 向 API Server 发送资源创建、更新、删除请求时,请求在通过身份认证(Authentication)和授权(Authorization)之后、被持久化到 etcd 之前,会依次经过准入控制器的处理。
准入控制器可以拦截请求并执行以下操作:
- 变更(Mutate):修改请求中的资源对象,例如注入 Sidecar 容器、设置默认标签、调整资源配额。
- 验证(Validate):检查请求中的资源对象是否符合集群策略,例如禁止使用特权容器、检查镜像来源、验证资源配额是否超限。
Kubernetes 内置了多种准入控制器(如 NamespaceLifecycle、LimitRanger、ResourceQuota),但内置控制器的逻辑是固定的,无法满足自定义策略需求。因此,Kubernetes 提供了 Admission Webhook 机制,允许用户通过 HTTP 回调的方式接入自定义的准入逻辑。
4.2 Admission Webhook 工作原理
Admission Webhook 的工作流程可以概括为:API Server 在收到资源请求后,将请求对象序列化为 AdmissionReview 请求,发送给用户部署的 Webhook 服务;Webhook 服务处理完毕后,将处理结果(允许/拒绝、是否修改)封装在 AdmissionReview 响应中返回给 API Server;API Server 根据响应决定是否继续执行请求。
4.3 Mutating vs Validating Webhook
Admission Webhook 分为两种类型,它们在请求链中的执行顺序和职责不同:
| 对比维度 | Mutating Webhook | Validating Webhook |
|---|---|---|
| 执行顺序 | 先执行(变更阶段) | 后执行(验证阶段) |
| 核心职责 | 修改请求中的资源对象 | 检查资源对象是否符合策略 |
| 响应方式 | 返回 JSON Patch 或 JSON Merge Patch | 返回 allowed: true/false |
| 典型场景 | 注入 Sidecar、设置默认标签、调整资源请求/限制 | 禁止特权容器、检查镜像仓库白名单、验证资源配额 |
| 幂等性要求 | 必须幂等,避免重复注入 | 无特殊要求 |
| 配置资源 | MutatingWebhookConfiguration | ValidatingWebhookConfiguration |
4.4 Webhook 配置示例
以下是一个完整的 ValidatingWebhookConfiguration 示例,用于验证 Pod 是否使用了允许的镜像仓库:
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
name: "pod-image-validator.example.com"
webhooks:
- name: "pod-image-validator.example.com"
clientConfig:
service:
namespace: "webhook-system"
name: "webhook-service"
path: "/validate"
port: 443
caBundle: "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0t..."
rules:
- operations: ["CREATE", "UPDATE"]
apiGroups: [""]
apiVersions: ["v1"]
resources: ["pods"]
scope: "Namespaced"
admissionReviewVersions: ["v1"]
sideEffects: None
timeoutSeconds: 5
failurePolicy: Fail
matchPolicy: Equivalent
namespaceSelector:
matchExpressions:
- key: "kubernetes.io/metadata.name"
operator: NotIn
values: ["kube-system"]
objectSelector: {}
reinvocationPolicy: Never
对应的 MutatingWebhookConfiguration 示例,用于为 Pod 注入灰度标签:
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: "pod-greylabel-injector.example.com"
webhooks:
- name: "pod-greylabel-injector.example.com"
clientConfig:
service:
namespace: "webhook-system"
name: "webhook-service"
path: "/mutate"
port: 443
caBundle: "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0t..."
rules:
- operations: ["CREATE"]
apiGroups: [""]
apiVersions: ["v1"]
resources: ["pods"]
scope: "Namespaced"
admissionReviewVersions: ["v1"]
sideEffects: None
timeoutSeconds: 5
failurePolicy: Fail
matchPolicy: Equivalent
reinvocationPolicy: IfNeeded
namespaceSelector:
matchLabels:
greyscale-enabled: "true"
4.5 配置关键字段解析
| 字段 | 说明 | 推荐值 |
|---|---|---|
clientConfig.service |
Webhook 服务的 Kubernetes Service 地址 | 与 Webhook 部署在同一集群 |
clientConfig.caBundle |
用于验证 Webhook 服务端证书的 CA 证书(Base64 编码) | 使用 cert-manager 自动签发 |
rules |
定义哪些资源、操作、API 版本会触发 Webhook | 尽量精确,避免拦截无关请求 |
failurePolicy |
Webhook 不可用时的处理策略:Fail(拒绝请求)或 Ignore(允许请求) | 生产环境建议 Fail |
sideEffects |
Webhook 是否产生副作用:None 或 Some | 推荐 None |
timeoutSeconds |
API Server 等待 Webhook 响应的超时时间 | 5-10 秒 |
reinvocationPolicy |
Mutating Webhook 是否允许被再次调用(用于处理其他 Webhook 的变更) | IfNeeded |
- Webhook 服务必须使用 TLS,证书由集群信任的 CA 签发。
- 避免将
failurePolicy设置为 Ignore 用于关键策略,否则 Webhook 故障时策略将失效。 - 使用
namespaceSelector和objectSelector缩小 Webhook 的拦截范围,降低 API Server 负载。 - Webhook 服务应部署多个副本,并使用 PDB(PodDisruptionBudget)保证高可用。
4.6 在 GitOps 灰度发布中的应用
在本课程 GitOps 灰度发布场景中,Admission Webhook 承担以下职责:
- Mutating Webhook:在 Pod 创建时自动注入灰度版本标签(如
version: canary)、调整资源配额(如 CPU 限制)、注入日志采集 Sidecar。 - Validating Webhook:验证灰度 Pod 的镜像标签是否来自允许的仓库、灰度比例是否超过集群配额、是否与现有生产 Pod 存在端口冲突。
通过 Webhook 的自动化和策略化处理,GitOps 工具(如 Argo CD、Flux)在同步应用时无需手动配置灰度参数,所有准入策略由 Webhook 统一管控,实现“配置即策略”的灰度发布治理。