验证性准入策略

特性状态: Kubernetes v1.30 [稳定]

本页面提供了验证准入策略的概述。

什么是验证准入策略?

验证准入策略提供了一种声明式的、进程内的替代方案,用于验证准入 webhook。

验证准入策略使用通用表达式语言 (CEL) 来声明策略的验证规则。验证准入策略是高度可配置的,使策略作者能够定义可参数化并根据集群管理员的需求限定资源范围的策略。

构成策略的资源

策略通常由三个资源组成

  • ValidatingAdmissionPolicy 描述了策略的抽象逻辑(例如:“此策略确保某个特定标签设置为特定值”)。

  • 参数资源向 ValidatingAdmissionPolicy 提供信息,使其成为一个具体的语句(例如“owner 标签必须设置为以 .company.com 结尾的值”)。原生类型(如 ConfigMap)或 CRD 定义了参数资源的模式。ValidatingAdmissionPolicy 对象指定了它们期望的参数资源的 Kind。

  • ValidatingAdmissionPolicyBinding 将上述资源链接在一起并提供作用域。如果你只希望 Pods 设置 owner 标签,则可以在绑定中指定此限制。

至少必须定义一个 ValidatingAdmissionPolicy 和一个相应的 ValidatingAdmissionPolicyBinding,策略才能生效。

如果 ValidatingAdmissionPolicy 不需要通过参数配置,只需将 ValidatingAdmissionPolicy 中的 spec.paramKind 留空即可。

验证准入策略入门

验证准入策略是集群控制平面的一部分。你应该非常谨慎地编写和部署它们。下面描述了如何快速试验验证准入策略。

创建 ValidatingAdmissionPolicy

下面是 ValidatingAdmissionPolicy 的一个示例。

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
  name: "demo-policy.example.com"
spec:
  failurePolicy: Fail
  matchConstraints:
    resourceRules:
    - apiGroups:   ["apps"]
      apiVersions: ["v1"]
      operations:  ["CREATE", "UPDATE"]
      resources:   ["deployments"]
  validations:
    - expression: "object.spec.replicas <= 5"

spec.validations 包含使用 通用表达式语言 (CEL) 来验证请求的 CEL 表达式。如果表达式评估为 false,则根据 spec.failurePolicy 字段强制执行验证检查。

要配置验证准入策略以在集群中使用,需要进行绑定。下面是 ValidatingAdmissionPolicyBinding 的一个示例。

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicyBinding
metadata:
  name: "demo-binding-test.example.com"
spec:
  policyName: "demo-policy.example.com"
  validationActions: [Deny]
  matchResources:
    namespaceSelector:
      matchLabels:
        environment: test

当尝试创建一个副本数不满足验证表达式的 Deployment 时,将返回包含消息的错误

ValidatingAdmissionPolicy 'demo-policy.example.com' with binding 'demo-binding-test.example.com' denied request: failed expression: object.spec.replicas <= 5

上述提供了一个使用 ValidatingAdmissionPolicy 而未配置参数的简单示例。

验证动作

每个 ValidatingAdmissionPolicyBinding 必须指定一个或多个 validationActions 以声明如何强制执行策略的 validations

支持的 validationActions

  • Deny:验证失败会导致请求被拒绝。
  • Warn:验证失败作为警告报告给请求客户端。
  • Audit:验证失败包含在 API 请求的审计事件中。

例如,要同时向客户端发出验证失败警告并审计验证失败,请使用

validationActions: [Warn, Audit]

DenyWarn 不能同时使用,因为这种组合不必要地在 API 响应主体和 HTTP 警告头中重复了验证失败。

评估为 false 的 validation 总是根据这些动作强制执行。由 failurePolicy 定义的失败仅在 failurePolicy 设置为 Fail(或未指定)时根据这些动作强制执行,否则失败将被忽略。

有关验证失败审计注解的更多详细信息,请参阅审计注解:验证失败

参数资源

参数资源允许策略配置与其定义分离。策略可以定义 paramKind,它概述了参数资源的 GVK,然后策略绑定通过 policyName 将策略与特定的参数资源通过 paramRef 绑定在一起。

如果需要参数配置,下面是一个带参数配置的 ValidatingAdmissionPolicy 示例。

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
  name: "replicalimit-policy.example.com"
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 <= params.maxReplicas"
      reason: Invalid

ValidatingAdmissionPolicy 的 spec.paramKind 字段指定了用于参数化此策略的资源的类型。对于此示例,它由 ReplicaLimit 自定义资源配置。请注意在此示例中 CEL 表达式如何通过 CEL params 变量引用参数,例如 params.maxReplicasspec.matchConstraints 指定此策略旨在验证哪些资源。请注意,原生类型(如 ConfigMap)也可以用作参数引用。

spec.validations 字段包含 CEL 表达式。如果表达式评估为 false,则根据 spec.failurePolicy 字段强制执行验证检查。

验证准入策略作者负责提供 ReplicaLimit 参数 CRD。

要配置验证准入策略以在集群中使用,需要创建绑定和参数资源。下面是一个使用**集群范围**参数的 ValidatingAdmissionPolicyBinding 示例——同一个参数将用于验证所有与绑定匹配的资源请求

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicyBinding
metadata:
  name: "replicalimit-binding-test.example.com"
spec:
  policyName: "replicalimit-policy.example.com"
  validationActions: [Deny]
  paramRef:
    name: "replica-limit-test.example.com"
    namespace: "default"
    parameterNotFoundAction: Deny
  matchResources:
    namespaceSelector:
      matchLabels:
        environment: test

请注意,此绑定将参数应用于策略,适用于 test 环境中的所有资源。

参数资源可能如下所示

apiVersion: rules.example.com/v1
kind: ReplicaLimit
metadata:
  name: "replica-limit-test.example.com"
  namespace: "default"
maxReplicas: 3

此策略参数资源将部署限制为最多 3 个副本。

一个准入策略可以有多个绑定。要将所有其他环境绑定为 maxReplicas 限制为 100,请创建另一个 ValidatingAdmissionPolicyBinding

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicyBinding
metadata:
  name: "replicalimit-binding-nontest"
spec:
  policyName: "replicalimit-policy.example.com"
  validationActions: [Deny]
  paramRef:
    name: "replica-limit-prod.example.com"
    namespace: "default"
    parameterNotFoundAction: Deny
  matchResources:
    namespaceSelector:
      matchExpressions:
      - key: environment
        operator: NotIn
        values:
        - test

请注意,此绑定将不同的参数应用于不在 test 环境中的资源。

并具有参数资源

apiVersion: rules.example.com/v1
kind: ReplicaLimit
metadata:
  name: "replica-limit-prod.example.com"
maxReplicas: 100

对于每个准入请求,API 服务器会评估与请求匹配的每个(策略、绑定、参数)组合的 CEL 表达式。要使请求被准入,它必须通过**所有**评估。

如果多个绑定匹配请求,将对每个绑定评估策略,并且它们都必须通过评估才能认为策略通过。

如果多个参数匹配单个绑定,则将针对每个参数评估策略规则,并且它们也必须全部通过才能认为绑定通过。绑定可以具有重叠的匹配条件。策略将针对每个匹配的绑定-参数组合进行评估。如果多个绑定匹配它,或者单个绑定匹配多个参数,策略甚至可能被评估多次。

如果未绑定参数资源,则表示参数资源的 params 对象将不会设置,因此对于需要参数资源的策略,添加检查以确保已绑定一个参数资源可能很有用。如果未指定策略的 paramKind 或绑定的 paramRef,则不会绑定参数资源且 params 将为 null。

对于需要参数配置的用例,我们建议在 spec.validations[0].expression 中添加参数检查

- expression: "params != null"
  message: "params missing but required to bind to this policy"

可选参数

将可选参数作为参数资源的一部分会很方便,并且只在存在时才进行验证。CEL 提供了 has(),它检查传递给它的键是否存在。CEL 还实现了布尔短路。如果逻辑 OR 的前半部分评估为 true,则它不会评估后半部分(因为整个 OR 的结果将始终为 true)。

结合这两者,我们可以提供一种验证可选参数的方法

!has(params.optionalNumber) || (params.optionalNumber >= 5 && params.optionalNumber <= 10)

这里,我们首先使用 !has(params.optionalNumber) 检查可选参数是否存在。

  • 如果 optionalNumber 未定义,则表达式会短路,因为 !has(params.optionalNumber) 将评估为 true。
  • 如果 optionalNumber 已定义,则将评估 CEL 表达式的后半部分,并将检查 optionalNumber 以确保它包含 5 到 10(含)之间的值。

每命名空间参数

作为 ValidatingAdmissionPolicy 及其 ValidatingAdmissionPolicyBinding 的作者,你可以选择指定集群范围的参数或每命名空间的参数。如果你为绑定的 paramRef 指定了 namespace,则控制平面只在该命名空间中搜索参数。

但是,如果 ValidatingAdmissionPolicyBinding 中未指定 namespace,API 服务器可以在请求所针对的命名空间中搜索相关参数。例如,如果你请求修改 default 命名空间中的 ConfigMap,并且存在一个没有设置 namespace 的相关 ValidatingAdmissionPolicyBinding,则 API 服务器会在 default 中查找参数对象。这种设计使得策略配置可以依赖于被操作资源的命名空间,以实现更精细的控制。

参数选择器

除了通过 name 在绑定中指定参数外,你还可以选择指定标签选择器,以便策略 paramKind 的所有资源以及参数的 namespace(如果适用)中与标签选择器匹配的所有资源都将被选中进行评估。有关标签选择器如何匹配资源的更多信息,请参阅选择器

如果发现多个参数满足条件,则对找到的每个参数评估策略规则,并将结果进行 AND 运算。

如果提供了 namespace,则只有指定命名空间中 paramKind 的对象才符合选择条件。否则,当 namespace 为空且 paramKind 为命名空间范围时,将使用被准入请求中使用的 namespace

授权检查

我们引入了参数资源的授权检查。用户需要对 ValidatingAdmissionPolicyparamKindValidatingAdmissionPolicyBindingparamRef 引用的资源具有 read 访问权限。

请注意,如果 paramKind 中的资源通过 restmapper 解析失败,则需要对所有组资源具有 read 访问权限。

paramRef

paramRef 字段指定了策略使用的参数资源。它具有以下字段

  • name:参数资源的名称。

  • namespace:参数资源的命名空间。

  • selector:一个标签选择器,用于匹配多个参数资源。

  • parameterNotFoundAction:(必需)控制未找到指定参数时的行为。

    • 允许值:
      • Allow:未找到匹配参数被视为绑定成功验证。
      • Deny:未找到匹配参数受策略的 failurePolicy 约束。

nameselector 必须设置一个,但不能同时设置两者。

使用 parameterNotFoundAction 处理缺失参数

当使用带有选择器的 paramRef 时,可能没有参数与选择器匹配。parameterNotFoundAction 字段决定了在这种情况下绑定的行为。

示例

apiVersion: admissionregistration.k8s.io/v1alpha1
kind: ValidatingAdmissionPolicyBinding
metadata:
  name: example-binding
spec:
  policyName: example-policy
  paramRef:
    selector:
      matchLabels:
        environment: test
    parameterNotFoundAction: Allow
  validationActions:
  - Deny

故障策略

failurePolicy 定义了准入策略中配置错误和 CEL 表达式评估为错误时如何处理。允许的值为 IgnoreFail

  • Ignore 表示调用 ValidatingAdmissionPolicy 时的错误将被忽略,API 请求允许继续。
  • Fail 表示调用 ValidatingAdmissionPolicy 时的错误会导致准入失败,并且 API 请求被拒绝。

注意 failurePolicyValidatingAdmissionPolicy 中定义

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
spec:
...
failurePolicy: Ignore # The default is "Fail"
validations:
- expression: "object.spec.xyz == params.x"  

验证表达式

spec.validations[i].expression 表示将由 CEL 评估的表达式。要了解更多信息,请参阅 CEL 语言规范。CEL 表达式可以访问传入请求/响应的内容,这些内容组织成 CEL 变量以及一些其他有用的变量

  • 'object' - 传入请求中的对象。对于 DELETE 请求,该值为 null。
  • 'oldObject' - 现有对象。对于 CREATE 请求,该值为 null。
  • 'request' - 准入请求的属性。
  • 'params' - 正在评估的策略绑定所引用的参数资源。如果未指定 ParamKind,则该值为 null。
  • namespaceObject - 传入对象所属的命名空间,作为 Kubernetes 资源。如果传入对象是集群范围的,则该值为 null。
  • authorizer - 一个 CEL 授权器。可用于对请求的主体(已认证用户)执行授权检查。有关详细信息,请参阅 Kubernetes CEL 库文档中的 AuthzSelectorsAuthz
  • authorizer.requestResource - 用于配置有请求资源(组、资源、(子资源)、命名空间、名称)的授权检查的快捷方式。

apiVersionkindmetadata.namemetadata.generateName 始终可以从对象的根访问。其他元数据属性均不可访问。

列表类型为“set”或“map”的数组上的相等性忽略元素顺序,即 [1, 2] == [2, 1]。数组上的连接与 x-kubernetes-list-type 使用列表类型的语义

  • 'set':X + Y 执行并集,其中 X 中所有元素的数组位置保留,Y 中不相交的元素附加,保留其部分顺序。
  • 'map':X + Y 执行合并,其中 X 中所有键的数组位置保留,但当 XY 的键集相交时,值会被 Y 中的值覆盖。Y 中具有不相交键的元素附加,保留其部分顺序。

验证表达式示例

表达式目的
object.minReplicas <= object.replicas && object.replicas <= object.maxReplicas验证定义副本的三个字段是否按适当顺序排列
'Available' in object.stateCounts验证映射中是否存在带有“Available”键的条目
(size(object.list1) == 0) != (size(object.list2) == 0)验证两个列表中的一个非空,但不能都非空
!('MY_KEY' in object.map1) || object['MY_KEY'].matches('^[a-zA-Z]*$')验证映射中特定键的值(如果存在)
object.envars.filter(e, e.name == 'MY_ENV').all(e, e.value.matches('^[a-zA-Z]*$')验证键字段“name”为“MY_ENV”的 listMap 条目的“value”字段
has(object.expired) && object.created + object.ttl < object.expired验证“expired”日期是否晚于“create”日期加上“ttl”持续时间
object.health.startsWith('ok')验证“health”字符串字段是否具有前缀“ok”
object.widgets.exists(w, w.key == 'x' && w.foo < 10)验证键为“x”的 listMap 项的“foo”属性是否小于 10
type(object) == string ? object == '100%' : object == 1000验证 int-or-string 字段的整数和字符串情况
object.metadata.name.startsWith(object.prefix)验证对象的名称是否以另一个字段值作为前缀
object.set1.all(e, !(e in object.set2))验证两个 listSet 是否不相交
size(object.names) == size(object.details) && object.names.all(n, n in object.details)验证“details”映射是否由“names”listSet 中的项作为键
size(object.clusters.filter(c, c.name == object.primary)) == 1验证“primary”属性在“clusters”列表映射中只出现一次

阅读CEL 上支持的评估,了解有关 CEL 规则的更多信息。

spec.validation[i].reason 表示此验证失败原因的机器可读描述。如果这是列表中第一个失败的验证,则此原因以及相应的 HTTP 响应代码将用于 HTTP 响应客户端。目前支持的原因有:UnauthorizedForbiddenInvalidRequestEntityTooLarge。如果未设置,则在响应客户端时使用 StatusReasonInvalid

匹配请求:matchConditions

如果你需要细粒度的请求过滤,可以为 ValidatingAdmissionPolicy 定义*匹配条件*。如果发现匹配规则、objectSelectorsnamespaceSelectors 仍然无法提供所需的过滤功能,这些条件将很有用。匹配条件是 CEL 表达式。所有匹配条件都必须评估为 true 才能评估资源。

这是一个示例,说明了匹配条件的几种不同用法

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
  name: "demo-policy.example.com"
spec:
  failurePolicy: Fail
  matchConstraints:
    resourceRules:
      - apiGroups:   ["*"]
        apiVersions: ["*"]
        operations:  ["CREATE", "UPDATE"]
        resources:   ["*"]
  matchConditions:
    - name: 'exclude-leases' # Each match condition must have a unique name
      expression: '!(request.resource.group == "coordination.k8s.io" && request.resource.resource == "leases")' # Match non-lease resources.
    - name: 'exclude-kubelet-requests'
      expression: '!("system:nodes" in request.userInfo.groups)' # Match requests made by non-node users.
    - name: 'rbac' # Skip RBAC requests.
      expression: 'request.resource.group != "rbac.authorization.k8s.io"'
  validations:
    - expression: "!object.metadata.name.contains('demo') || object.metadata.namespace == 'demo'"

匹配条件可以访问与验证表达式相同的 CEL 变量。

如果评估匹配条件时发生错误,则不会评估策略。是否拒绝请求的决定如下

  1. 如果**任何**匹配条件评估为 false(无论其他错误如何),API 服务器将跳过该策略。
  2. 否则

审计注解

auditAnnotations 可用于在 API 请求的审计事件中包含审计注解。

例如,这是一个带有审计注解的准入策略

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
  name: "demo-policy.example.com"
spec:
  failurePolicy: Fail
  matchConstraints:
    resourceRules:
    - apiGroups:   ["apps"]
      apiVersions: ["v1"]
      operations:  ["CREATE", "UPDATE"]
      resources:   ["deployments"]
  validations:
    - expression: "object.spec.replicas > 50"
      messageExpression: "'Deployment spec.replicas set to ' + string(object.spec.replicas)"
  auditAnnotations:
    - key: "high-replica-count"
      valueExpression: "'Deployment spec.replicas set to ' + string(object.spec.replicas)"

当 API 请求使用此准入策略进行验证时,生成的审计事件将如下所示

# the audit event recorded
{
    "kind": "Event",
    "apiVersion": "audit.k8s.io/v1",
    "annotations": {
        "demo-policy.example.com/high-replica-count": "Deployment spec.replicas set to 128"
        # other annotations
        ...
    }
    # other fields
    ...
}

在此示例中,只有当 Deployment 的 spec.replicas 大于 50 时,才会包含注解,否则 CEL 表达式评估为 null,并且注解将不包含。

请注意,审计注解键以 ValidatingAdmissionPolicy 的名称和 / 为前缀。如果另一个准入控制器(例如准入 webhook)使用完全相同的审计注解键,则第一个准入控制器包含的审计注解值将包含在审计事件中,所有其他值将被忽略。

消息表达式

为了在策略拒绝请求时返回更友好的消息,我们可以使用 CEL 表达式通过 spec.validations[i].messageExpression 组合消息。与验证表达式类似,消息表达式可以访问 objectoldObjectrequestparamsnamespaceObject。与验证不同,消息表达式必须评估为字符串。

例如,为了更好地告知用户策略拒绝请求的原因(当策略引用参数时),我们可以有以下验证

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
  name: "deploy-replica-policy.example.com"
spec:
  paramKind:
    apiVersion: rules.example.com/v1
    kind: ReplicaLimit
  matchConstraints:
    resourceRules:
    - apiGroups:   ["apps"]
      apiVersions: ["v1"]
      operations:  ["CREATE", "UPDATE"]
      resources:   ["deployments"]
  validations:
  - expression: "object.spec.replicas <= params.maxReplicas"
    messageExpression: "'object.spec.replicas must be no greater than ' + string(params.maxReplicas)"
    reason: Invalid

创建限制副本数为 3 的参数对象并设置绑定后,当我们尝试创建 5 个副本的 Deployment 时,将收到以下消息。

$ kubectl create deploy --image=nginx nginx --replicas=5
error: failed to create deployment: deployments.apps "nginx" is forbidden: ValidatingAdmissionPolicy 'deploy-replica-policy.example.com' with binding 'demo-binding-test.example.com' denied request: object.spec.replicas must be no greater than 3

这比“副本太多”的静态消息更具信息性。

如果同时定义了消息表达式和 spec.validations[i].message 中定义的静态消息,则消息表达式优先。但是,如果消息表达式评估失败,则将改用静态消息。此外,如果消息表达式评估为多行字符串,则评估结果将被丢弃,如果存在静态消息,则将使用静态消息。请注意,静态消息是针对多行字符串进行验证的。

类型检查

当创建或更新策略定义时,验证过程会解析其中包含的表达式并报告任何语法错误,如果发现任何错误,则拒绝该定义。之后,将根据 spec.matchConstraints 的匹配类型检查引用变量是否存在类型错误,包括缺失字段和类型混淆。类型检查的结果可以从 status.typeChecking 中检索。status.typeChecking 的存在表示类型检查完成,空的 status.typeChecking 表示未检测到错误。

例如,给定以下策略定义

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
  name: "deploy-replica-policy.example.com"
spec:
  matchConstraints:
    resourceRules:
    - apiGroups:   ["apps"]
      apiVersions: ["v1"]
      operations:  ["CREATE", "UPDATE"]
      resources:   ["deployments"]
  validations:
  - expression: "object.replicas > 1" # should be "object.spec.replicas > 1"
    message: "must be replicated"
    reason: Invalid

状态将提供以下信息

status:
  typeChecking:
    expressionWarnings:
    - fieldRef: spec.validations[0].expression
      warning: |-
        apps/v1, Kind=Deployment: ERROR: <input>:1:7: undefined field 'replicas'
         | object.replicas > 1
         | ......^        

如果在 spec.matchConstraints 中匹配了多个资源,则将对所有匹配的资源进行检查。例如,以下策略定义

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
  name: "replica-policy.example.com"
spec:
  matchConstraints:
    resourceRules:
    - apiGroups:   ["apps"]
      apiVersions: ["v1"]
      operations:  ["CREATE", "UPDATE"]
      resources:   ["deployments","replicasets"]
  validations:
  - expression: "object.replicas > 1" # should be "object.spec.replicas > 1"
    message: "must be replicated"
    reason: Invalid

将在警告消息中包含多种类型和每种类型的类型检查结果。

status:
  typeChecking:
    expressionWarnings:
    - fieldRef: spec.validations[0].expression
      warning: |-
        apps/v1, Kind=Deployment: ERROR: <input>:1:7: undefined field 'replicas'
         | object.replicas > 1
         | ......^
        apps/v1, Kind=ReplicaSet: ERROR: <input>:1:7: undefined field 'replicas'
         | object.replicas > 1
         | ......^        

类型检查有以下限制

  • 不支持通配符匹配。如果 spec.matchConstraints.resourceRules 在任何 apiGroupsapiVersionsresources 中包含 "*",则不会检查 "*" 匹配的类型。
  • 匹配类型的数量限制为 10。这是为了防止策略手动指定过多类型而消耗过多的计算资源。按照组、版本然后资源的升序,第 11 个组合及以后的组合将被忽略。
  • 类型检查不会以任何方式影响策略行为。即使类型检查检测到错误,策略也会继续评估。如果在评估期间确实发生错误,故障策略将决定其结果。
  • 类型检查不适用于 CRD,包括匹配的 CRD 类型和 paramKind 的引用。对 CRD 的支持将在未来版本中提供。

变量组合

如果表达式变得过于复杂,或者表达式的某些部分是可重用且计算成本高昂的,你可以将表达式的某些部分提取到变量中。变量是一个命名表达式,可以在 variables 中在其他表达式中引用。

spec:
  variables:
    - name: foo
      expression: "'foo' in object.spec.metadata.labels ? object.spec.metadata.labels['foo'] : 'default'"
  validations:
    - expression: variables.foo == 'bar'

变量在首次引用时才进行延迟评估。评估期间发生的任何错误都将在引用表达式的评估期间报告。结果和潜在错误都会被记忆,并且只计入运行时成本一次。

变量的顺序很重要,因为一个变量可以引用在它之前定义的其他变量。这种排序可以防止循环引用。

下面是一个更复杂的示例,它强制镜像仓库名称与命名空间中定义的环境匹配。

# This policy enforces that all containers of a deployment has the image repo match the environment label of its namespace.
# Except for "exempt" deployments, or any containers that do not belong to the "example.com" organization (e.g. common sidecars).
# For example, if the namespace has a label of {"environment": "staging"}, all container images must be either staging.example.com/*
# or do not contain "example.com" at all, unless the deployment has {"exempt": "true"} label.
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
  name: "image-matches-namespace-environment.policy.example.com"
spec:
  failurePolicy: Fail
  matchConstraints:
    resourceRules:
    - apiGroups:   ["apps"]
      apiVersions: ["v1"]
      operations:  ["CREATE", "UPDATE"]
      resources:   ["deployments"]
  variables:
  - name: environment
    expression: "'environment' in namespaceObject.metadata.labels ? namespaceObject.metadata.labels['environment'] : 'prod'"
  - name: exempt
    expression: "'exempt' in object.metadata.labels && object.metadata.labels['exempt'] == 'true'"
  - name: containers
    expression: "object.spec.template.spec.containers"
  - name: containersToCheck
    expression: "variables.containers.filter(c, c.image.contains('example.com/'))"
  validations:
  - expression: "variables.exempt || variables.containersToCheck.all(c, c.image.startsWith(variables.environment + '.'))"
    messageExpression: "'only ' + variables.environment + ' images are allowed in namespace ' + namespaceObject.metadata.name"

如果策略绑定到标记为 environment: prod 的命名空间 default,则以下创建 Deployment 的尝试将被拒绝。

kubectl create deploy --image=dev.example.com/nginx invalid

错误消息类似于此。

error: failed to create deployment: deployments.apps "invalid" is forbidden: ValidatingAdmissionPolicy 'image-matches-namespace-environment.policy.example.com' with binding 'demo-binding-test.example.com' denied request: only prod images are allowed in namespace default

免于准入验证的 API 种类

某些 API 种类免于准入时间验证检查。例如,你不能创建阻止更改 ValidatingAdmissionPolicyBindings 的 ValidatingAdmissionPolicy。

免除的 API 种类列表是

上次修改时间:太平洋标准时间 2025 年 7 月 1 日下午 3:04:更新 validating-admission-policy.md (b8c28f19b8)