跳到正文
复制成功
请遵守本站许可
报告
章节_文章 // 现场报告

文章编号: RL-ADMISSIO

2026.08.25

Admission Control:准入插件、PSA、Webhook 与 CEL 策略

Chavy
Chavy
#Kubernetes#Admission#Pod Security#安全
档案

摘要:梳理准入插件、Pod Security Admission、动态 Webhook 与 CEL 策略,理解准入变更与校验、Pod 安全标准以及策略落地的适用边界。

例如:

某个开发人员拥有创建 Pod 的权限,但他提交了这样的配置:

PRTCL // YAML
apiVersion: v1
kind: Pod
metadata:
name: dangerous-pod
spec:
containers:
- name: nginx
image: nginx
securityContext:
privileged: true
volumeMounts:
- name: host-root
mountPath: /host
volumes:
- name: host-root
hostPath:
path: /

这个 Pod:

  • 使用了特权容器。
  • 挂载了宿主机根目录。
  • 可能获得非常高的宿主机访问能力。

即使用户拥有创建 Pod 的权限,我们也不希望它被直接创建。

这时候就需要 Admission Control。

1. Admission Control 是什么?#

Admission Control 中文叫准入控制。

它是 Kubernetes API Server 请求处理流程中的一个重要环节。

主要作用:

在资源对象被持久化到 etcd 之前,对请求进行额外的修改、检查或拒绝。

例如:

  • 禁止创建特权容器。
  • 限制 Pod 使用 hostPath。
  • 强制容器设置资源限制。
  • 自动注入 Sidecar。
  • 强制使用指定镜像仓库。
  • 检查资源是否符合企业安全规范。

1.1 API Server 的请求处理流程#

先看完整流程:

flowchart TB
    C["客户端 kubectl / API Client"] --> A["Authentication<br/>验证请求者身份"]
    A --> R["Authorization<br/>检查 RBAC 等授权规则"]
    subgraph AD["Admission 与对象校验"]
        M["Mutating Admission<br/>修改资源对象"] --> V["对象校验"]
        V --> P["Validating Admission<br/>验证资源是否符合策略"]
    end
    R --> M
    P --> E["通过后保存到 etcd"]

注意:这是便于理解的逻辑示意。实际 API Server 内部还包括请求解码、默认值处理、对象校验、准入插件执行、存储前处理等阶段,具体顺序依赖请求类型和 Kubernetes 实现。

1.2 三个安全环节的区别#

环节解决的问题示例
Authentication你是谁?Alice 身份认证成功
Authorization你能做什么?Alice 可以创建 Pod
Admission这个请求能否被接受?拒绝特权容器

举一个完整例子:

Alice 执行:

PRTCL // BASH
Terminal window
kubectl apply -f privileged-pod.yaml

处理过程:

  1. API Server 验证 Alice 的客户端证书。
  2. RBAC 判断 Alice 是否拥有创建 Pod 的权限。
  3. Admission Control 检查 Pod 是否使用了不允许的配置。
  4. 如果触发安全策略,拒绝创建。
  5. 如果全部通过,继续完成资源持久化。

RBAC 负责控制操作权限,Admission Control 负责控制资源内容及请求是否符合策略。

2. Admission Control 的两种核心机制#

Admission Control 最重要的两种机制:

  1. Mutating Admission:变更准入。
  2. Validating Admission:验证准入。

它们可以通过内置准入插件实现,也可以通过 Admission Webhook 扩展。

2.1 Mutating Admission:修改资源#

Mutating Admission 的主要作用是:

在资源创建或更新过程中,自动修改资源对象。

例如,用户提交:

PRTCL // YAML
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx

企业要求所有 Pod 必须设置 CPU 和内存请求值。

那么 Mutating Admission 可以自动添加:

PRTCL // YAML
resources:
requests:
cpu: 100m
memory: 128Mi

最终实际提交给后续处理阶段的对象就包含这些字段。

常见应用:

  • 自动注入 Sidecar。
  • 自动添加 Label。
  • 自动设置默认值。
  • 自动注入环境变量。
  • 自动设置资源请求和限制。

2.2 Validating Admission:验证资源#

Validating Admission 的主要作用是:

检查资源对象是否符合安全策略和业务规则,不符合则拒绝请求。

例如:

PRTCL // YAML
securityContext:
privileged: true

企业禁止所有业务容器使用特权模式。

Validating Admission 就可以拒绝这个 Pod。

常见应用:

  • 禁止特权容器。
  • 禁止使用 latest 镜像标签。
  • 限制镜像仓库。
  • 限制 HostPath。
  • 强制使用指定标签。
  • 检查资源配额和业务规则。

2.3 两者有什么区别?#

比较MutatingValidating
中文变更准入验证准入
主要作用修改对象检查对象
能否修改对象可以不可以
能否拒绝请求可以可以
典型场景自动注入 Sidecar禁止特权容器

例如:

假设企业有以下要求:

  1. 所有 Pod 自动添加 company=demo 标签。
  2. 禁止 Pod 使用特权容器。

可以分别使用:

  • Mutating:自动添加标签。
  • Validating:检查是否使用特权容器。

两者组合后,就形成了一套准入策略。

3. Kubernetes 内置 Admission Controllers#

前面讲的是准入控制的基本原理。实际上,Kubernetes 已经内置了很多 Admission Controller,不需要我们自己开发 Webhook。

它们直接集成在 API Server 中。

3.1 常见内置准入控制器#

Admission Controller主要作用
NamespaceLifecycle防止在不存在或正在删除的 Namespace 中创建资源
LimitRanger限制资源使用,并可设置默认 requests/limits
ResourceQuota限制 Namespace 的资源总量
ServiceAccount自动化处理 ServiceAccount 相关配置
DefaultStorageClass为未指定 StorageClass 的 PVC 设置默认存储类
DefaultIngressClass为未指定 IngressClass 的 Ingress 设置默认类别
PodSecurity执行 Pod 安全标准检查
RuntimeClass处理 RuntimeClass 和 Pod Overhead
MutatingAdmissionWebhook调用变更型 Webhook
ValidatingAdmissionWebhook调用验证型 Webhook

这些控制器分别负责不同的安全和资源管理任务。

官方文档:Admission Controllers 官方说明。

3.2 NamespaceLifecycle#

这个控制器负责 Namespace 生命周期相关的保护。

例如:

PRTCL // BASH
Terminal window
kubectl create namespace test
kubectl delete namespace test

当 Namespace 进入 Terminating 状态时,不允许继续在其中创建新的普通资源。

它还会防止删除一些系统保留 Namespace,例如:

PRTCL // TEXT
default
kube-system
kube-public

这可以避免误操作破坏集群基础环境。

3.3 LimitRanger#

LimitRanger 负责限制 Namespace 内资源的使用,并且能够为没有设置资源请求的容器提供默认值。

如果用户设置的资源超过最大值,则会被拒绝。

注意:LimitRange 定义约束,LimitRanger 准入插件负责执行这些约束。

3.4 ResourceQuota#

ResourceQuota 负责限制 Namespace 的资源总量。

如果用户继续创建 Pod,导致资源总量超过配额,准入阶段就会拒绝请求。

这里要区分:

  • ResourceQuota:定义资源配额。
  • LimitRange:定义单个对象或容器的资源限制及默认值,由 LimitRanger 准入插件执行。

它们经常结合使用。

4. Pod Security Admission(PSA):Pod 安全准入#

4.1 为什么需要 PSA?#

假设开发人员有创建 Pod 的权限。

他可能创建:

PRTCL // YAML
securityContext:
privileged: true

或者:

PRTCL // YAML
volumes:
- name: host
hostPath:
path: /

这些配置可能让容器获得宿主机敏感资源的访问能力。

如果只依赖 RBAC,就很难针对 Pod 的具体安全字段进行精细约束。

Kubernetes 因此提供了 Pod Security Admission(PSA)。

它根据 Pod Security Standards(PSS)定义的安全标准,检查 Pod 是否符合要求。

PSA 自 Kubernetes 1.25 起稳定提供。

官方文档:Pod Security Admission。

4.2 三种安全级别#

Pod Security Standards 定义了三个安全级别:

Privileged

最低限制

几乎不施加 PSS 安全限制,适用于需要特殊系统权限的可信工作负载。

Baseline

基础安全

防止已知的权限提升和常见危险配置,适用于一般业务工作负载。

Restricted

严格限制

执行更严格的安全约束,要求容器遵循更完善的安全配置。

三个级别的限制关系:

flowchart TB
    P["Privileged<br/>最低限制"] -->|"约束增加"| B["Baseline<br/>基础安全"]
    B -->|"约束增加"| R["Restricted<br/>严格限制"]

从上到下,安全约束逐渐严格。

4.3 PSA 的三种模式#

PSA 还提供三种执行模式:

模式作用
enforce违反策略的 Pod 直接拒绝创建
audit允许创建,但记录违规信息到审计事件
warn允许创建,同时向客户端返回警告

注意:audit 模式记录的是 Kubernetes 审计事件相关信息,不代表一定会自动保存完整审计日志;还需要配置审计策略和日志后端。

三种模式可以同时使用。

例如:

PRTCL // YAML
apiVersion: v1
kind: Namespace
metadata:
name: dev
labels:
pod-security.kubernetes.io/enforce: baseline
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restricted

这段配置表示:

  • enforce:必须符合 Baseline。
  • audit:记录不符合 Restricted 的情况。
  • warn:向用户提示不符合 Restricted 的情况。

这种配置非常适合生产环境的渐进式安全改造。

4.4 PSA 常见安全约束#

Restricted 模式会涉及很多安全要求,例如:

安全配置主要要求
privileged不允许特权容器
allowPrivilegeEscalation必须设置为 false
capabilities必须 drop: ALL,只允许添加 NET_BIND_SERVICE
runAsNonRoot必须以非 root 用户运行
seccompProfile使用 RuntimeDefault 或 Localhost
hostNetwork不允许使用 HostNetwork
hostPID不允许使用 HostPID
hostIPC不允许使用 HostIPC
hostPathRestricted 不允许使用 HostPath 卷

注意:Baseline 与 Restricted 的具体规则不同。不能把所有安全限制都简单归到 Baseline。部分限制与 Pod 操作系统及所选 PSS 版本有关。

4.5 PSA 与旧版 PodSecurityPolicy#

早期 Kubernetes 使用 PodSecurityPolicy(PSP)实现 Pod 安全限制。

但 PSP 已在 Kubernetes 1.25 移除。

现在主要使用:

  • Pod Security Admission。
  • ValidatingAdmissionPolicy。
  • Admission Webhook。

5. Admission Webhook:动态准入控制#

前面介绍的 PSA 和内置 Admission Controller 能解决很多问题。

但企业可能有更复杂的需求。

例如:

  • 所有镜像必须来自公司私有镜像仓库。
  • Deployment 必须设置指定业务标签。
  • 禁止使用未经批准的镜像版本。
  • 创建 Pod 时自动注入安全代理。
  • 根据业务系统的配置判断资源是否合法。

内置插件无法覆盖所有业务场景。

因此 Kubernetes 提供了 Admission Webhook。

5.1 Webhook 是什么?#

Webhook 可以理解为:

API Server 在处理资源请求时,向外部 HTTPS 服务发送请求,让外部程序决定是否修改或允许这个资源。

例如:

用户提交一个 Pod:

PRTCL // YAML
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx

API Server 将请求发送给 Webhook 服务。

Webhook 可以:

  • 修改 Pod。
  • 检查 Pod。
  • 拒绝 Pod。

整个流程:

flowchart TB
    C["kubectl apply<br/>提交 Pod YAML"] --> A["Kubernetes API Server<br/>认证、授权及准入处理"]
    A -->|"HTTPS AdmissionReview 请求"| W["外部 Webhook Server<br/>执行自定义业务逻辑"]
    W -->|"返回 AdmissionReview 响应"| D{"准入决定"}
    D -->|"允许 / 修改"| P["API Server 继续处理"]
    D -->|"拒绝"| E["返回错误"]

Webhook 需要遵循 Kubernetes 定义的 AdmissionReview 请求和响应格式。

5.2 两种 Webhook#

Kubernetes 有两种主要的 Webhook 配置对象:

Webhook 类型配置对象作用
MutatingMutatingWebhookConfiguration修改资源
ValidatingValidatingWebhookConfiguration验证资源

例如:

假设公司要求所有 Pod 自动添加:

PRTCL // YAML
metadata:
labels:
company: demo

可以开发 Mutating Webhook。

假设公司要求禁止使用:

PRTCL // YAML
image: nginx:latest

可以开发 Validating Webhook。

5.3 Webhook 如何匹配请求?#

Webhook 并不是接收所有 API 请求。

管理员可以指定匹配条件:

PRTCL // YAML
rules:
- operations:
- CREATE
- UPDATE
apiGroups:
- ""
apiVersions:
- v1
resources:
- pods
scope: Namespaced

含义:

  • operations:匹配创建和更新。
  • apiGroups:核心 API 组。
  • apiVersions:v1。
  • resources:Pod。
  • scope:只匹配 Namespace 资源。

这样,Webhook 就只会接收符合条件的请求。

5.4 Validating Webhook 配置示例#

下面展示一个简化的配置结构:

PRTCL // YAML
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
name: pod-policy
webhooks:
- name: pod-policy.example.com
admissionReviewVersions:
- v1
sideEffects: None
failurePolicy: Fail
clientConfig:
service:
namespace: security
name: policy-webhook
path: /validate
port: 443
caBundle: BASE64_CA_CERT
rules:
- operations:
- CREATE
- UPDATE
apiGroups:
- ""
apiVersions:
- v1
resources:
- pods
scope: Namespaced

重点理解以下字段:

字段作用
nameWebhook 名称
admissionReviewVersions支持的请求版本
sideEffects声明是否产生副作用
failurePolicyWebhook 调用失败时如何处理
clientConfigWebhook 服务地址与 CA
rules匹配哪些 API 请求

5.5 failurePolicy:非常重要#

这个参数直接影响集群可用性。

有两个主要选项:

Fail

如果 Webhook 无法正常调用,API 请求失败。

PRTCL // YAML
failurePolicy: Fail

例如:

Webhook 服务宕机,用户创建 Pod 就可能失败。

Ignore

如果 Webhook 无法正常调用,API Server 忽略这次调用失败,继续处理请求。

PRTCL // YAML
failurePolicy: Ignore

例如:

Webhook 服务宕机,Pod 仍可能被创建。

两者区别:

配置Webhook 不可用时安全性与可用性
Fail拒绝请求策略强制性更高,但可能影响可用性
Ignore跳过该 Webhook可用性较高,但可能绕过策略

failurePolicy 处理调用错误或超时。Webhook 明确返回拒绝时,Ignore 不会将该拒绝改为允许。

生产环境需要根据策略的重要程度选择。

例如:

  • 强制执行的安全策略,通常考虑 Fail。
  • 非关键的辅助校验,可以考虑 Ignore。

但不能简单认为 Fail 永远更安全,因为 Webhook 服务自身如果没有高可用设计,可能导致整个集群无法创建或更新相关资源。

5.6 Webhook 为什么需要 TLS?#

API Server 调用 Webhook 时通常使用 HTTPS。

因此需要配置:

PRTCL // YAML
clientConfig:
service:
namespace: security
name: policy-webhook
path: /validate
port: 443
caBundle: BASE64_CA_CERT

其中:

  • service:Webhook 的 Kubernetes Service。
  • caBundle:用于验证 Webhook 服务端证书的 CA。

注意:客户端验证 API Server、API Server 验证客户端证书,以及 API Server 验证 Webhook 服务,是不同方向的信任关系。这里的 caBundle 用于 API Server 验证 Webhook 服务端证书。

5.7 Webhook 的生产环境注意事项#

Webhook 运行在 API Server 的关键请求链路上,设计不当会影响整个集群。

需要特别注意:

  1. Webhook 服务必须具备高可用能力。
  2. 设置合理的 timeoutSeconds。
  3. 只匹配需要检查的 API 请求,避免拦截所有资源。
  4. 使用 namespaceSelector、objectSelector 缩小范围。
  5. 对修改操作保证幂等性。
  6. 避免 Webhook 调用 API Server 产生循环依赖。
  7. 谨慎设计 failurePolicy。

特别是循环依赖:

例如 Webhook 服务自身运行在 Kubernetes 中,而 Webhook 服务 Pod 的创建又必须调用该 Webhook。

如果 Webhook 服务还没有启动,就可能出现:

flowchart TB
    P["创建 Webhook Pod"] --> A["API Server 调用 Webhook"]
    A --> W["Webhook 服务尚未启动"]
    W --> F["Pod 创建失败"]
    F --> U["Webhook 服务无法启动"]
    U -.->|"后续调用仍然失败"| A

这可能造成集群中的工作负载无法正常创建。

因此生产部署通常需要设置合理的排除规则和启动策略。

参考:Dynamic Admission Control、Admission Webhook Good Practices。

6. ValidatingAdmissionPolicy:使用 CEL 实现准入策略#

这里介绍一个比传统 Webhook 更轻量的方式。

在 Kubernetes 中,很多准入规则其实并不复杂。

例如:

  • 禁止使用 latest 镜像标签。
  • 要求必须包含某个 Label。
  • 限制 Deployment 的副本数量。
  • 限制容器的某些安全配置。

如果每个规则都开发一个 Webhook 服务,会增加很多运维成本。

Kubernetes 提供了:

ValidatingAdmissionPolicy(VAP)

它使用 CEL(Common Expression Language)表达式,直接在 API Server 内部执行资源验证。

6.1 CEL 是什么?#

CEL 是一种轻量级表达式语言。

例如:

PRTCL // TEXT
object.metadata.name == "nginx"

意思是:

资源名称必须为 nginx。

再看:

PRTCL // TEXT
object.spec.replicas <= 5

意思是:

Deployment 的副本数量不能超过 5。

CEL 常用于:

  • 条件判断。
  • 字段检查。
  • 数组遍历。
  • 资源内容校验。

6.2 创建 ValidatingAdmissionPolicy#

假设我们规定:

所有 Deployment 的副本数量不能超过 5。

创建:

PRTCL // YAML
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
name: deployment-replica-limit
spec:
failurePolicy: Fail
matchConstraints:
resourceRules:
- apiGroups: ["apps"]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["deployments"]
validations:
- expression: "object.spec.replicas <= 5"
message: "Deployment replicas cannot exceed 5"

这里:

  • matchConstraints:决定哪些请求需要检查。
  • validations:定义 CEL 验证表达式。
  • message:验证失败时显示的信息。

6.3 创建 Binding#

仅创建 Policy 还不够。

还需要通过 Binding 将策略关联到实际请求范围,并指定执行动作。

PRTCL // YAML
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicyBinding
metadata:
name: deployment-replica-limit-binding
spec:
policyName: deployment-replica-limit
validationActions:
- Deny
matchResources:
namespaceSelector:
matchLabels:
environment: production

现在只有带有:

PRTCL // YAML
environment: production

标签的 Namespace 才会应用这条策略。

6.4 ValidatingAdmissionPolicy 与 Webhook 区别#

比较ValidatingAdmissionPolicyValidating Webhook
实现方式CEL 表达式外部 HTTP 服务
是否需要部署服务不需要需要
复杂业务逻辑适合简单规则适合复杂规则
外部系统调用不支持任意外部调用可以自行实现
运维复杂度较低相对较高
执行位置API Server 内部外部 Webhook 服务

在较新的 Kubernetes 版本中,MutatingAdmissionPolicy 也提供了基于 CEL 的声明式修改能力。

它与 ValidatingAdmissionPolicy 相对应:

  • ValidatingAdmissionPolicy:检查资源。
  • MutatingAdmissionPolicy:修改资源。

版本方面要特别注意:

  • ValidatingAdmissionPolicy 从 Kubernetes 1.30 起稳定提供。
  • MutatingAdmissionPolicy 在 Kubernetes 1.36 起进入稳定阶段。

具体是否可用,应以目标集群版本和 API 发现结果为准。官方参考:Kubernetes Admission Policies 教程。

7. Admission Controller 如何启用和查看?#

现在理解一下 Admission Controller 在 API Server 中是如何工作的。

7.1 查看 API Server 配置#

在 kubeadm 集群中:

PRTCL // BASH
Terminal window
cat /etc/kubernetes/manifests/kube-apiserver.yaml

查找:

PRTCL // YAML
- --enable-admission-plugins=NodeRestriction,PodSecurity,...

这个参数用于指定启用的内置准入插件。

也可以指定:

PRTCL // YAML
- --disable-admission-plugins=SomePlugin

禁用指定插件。

注意:不要随意禁用系统关键插件,例如 ServiceAccount、NamespaceLifecycle、ResourceQuota 等,否则可能破坏集群预期功能。

7.2 查看当前集群的准入插件#

可以查看 API Server 的帮助信息:

PRTCL // BASH
Terminal window
kube-apiserver -h | grep enable-admission-plugins

不过,这只能看到当前二进制支持的插件及相关参数说明,并不能直接反映运行中集群实际启用了哪些插件。

实际启用情况还需要结合:

PRTCL // BASH
Terminal window
kubectl get pods -n kube-system

以及 API Server 静态 Pod 配置进行判断。

7.3 查看 Webhook 配置#

查看变更型 Webhook:

PRTCL // BASH
Terminal window
kubectl get mutatingwebhookconfigurations

查看验证型 Webhook:

PRTCL // BASH
Terminal window
kubectl get validatingwebhookconfigurations

查看某个 Webhook:

PRTCL // BASH
Terminal window
kubectl describe validatingwebhookconfiguration pod-policy

7.4 查看 Admission Policy#

查看验证型策略:

PRTCL // BASH
Terminal window
kubectl get validatingadmissionpolicies

查看绑定:

PRTCL // BASH
Terminal window
kubectl get validatingadmissionpolicybindings

查看变更型策略(目标集群支持时):

PRTCL // BASH
Terminal window
kubectl get mutatingadmissionpolicies

8. Admission Control 的适用边界#

这一部分非常重要,避免把准入控制理解成万能安全机制。

8.1 Admission 不负责普通读取请求#

例如:

PRTCL // BASH
Terminal window
kubectl get pods
kubectl get services
kubectl get nodes

这些读取操作通常不会经过 Admission Control。

Admission 主要处理创建、修改、删除等请求,以及某些连接类操作。

因此:

  • RBAC 控制谁能读取 Pod。
  • Admission 控制符合条件的创建、修改等请求。

例如,一个用户没有读取 Secret 的权限,应该由 RBAC 拒绝,而不是依赖 Admission。

8.2 Admission 不能替代 RBAC#

假设:

用户 Alice 没有创建 Pod 的权限。

即使 Pod 完全符合安全策略,也不能创建成功。

因为请求已经在 Authorization 阶段被拒绝。

反过来:

用户 Bob 有创建 Pod 的权限,但 Pod 使用了特权模式。

如果 PSA 或其他准入策略禁止特权模式,请求仍然会被拒绝。

因此,两者必须结合。

8.3 Admission 不能替代运行时安全#

假设 Pod 创建时符合所有安全策略。

但应用程序运行之后,可能出现:

  • 容器进程被攻击。
  • 应用程序发生内存漏洞。
  • 恶意程序执行异常操作。
  • 容器访问不应该访问的网络服务。

这些问题不属于单纯的准入控制范围。

还需要结合:

  • Linux Namespace。
  • Linux Capabilities。
  • Seccomp。
  • AppArmor。
  • SELinux。
  • NetworkPolicy。
  • 容器运行时安全监控。

这也解释了为什么 Kubernetes 安全不是只靠 RBAC 或 Admission 就能完成的。

参考资料:

归档于 2026.08.25
// 档案结束
Classified
章节_06
协议编号: CC-BY-NC-SA-4.0

Admission Control:准入插件、PSA、Webhook 与 CEL 策略

作者:Chavy发布日期:2026.08.25

基于 CC BY-NC-SA 4.0

© 2026 Chavy
Powered by Astro