突变准入策略

功能状态: Kubernetes v1.32 [alpha]

本页概述了MutatingAdmissionPolicies

什么是 MutatingAdmissionPolicies?

变更准入策略为变更准入 Webhook 提供了一种声明式、进程内的替代方案。

变更准入策略使用通用表达式语言 (CEL) 来声明对资源的变更。可以使用 服务器端应用合并策略合并的应用配置JSON Patch 定义变更。

变更准入策略是高度可配置的,使策略作者能够定义可以参数化并根据集群管理员的需求将范围限定为资源的策略。

什么资源构成策略

一个策略通常由三个资源组成

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

  • 参数资源向 MutatingAdmissionPolicy 提供信息,使其成为一个具体的语句(例如,“将 owner 标签设置为类似 company.example.com 的值”)。 参数资源引用 Kubernetes 资源,这些资源在 Kubernetes API 中可用。 它们可以是内置类型或扩展类型,例如 CustomResourceDefinition (CRD)。 例如,你可以使用 ConfigMap 作为参数。

  • MutatingAdmissionPolicyBinding 将上述(MutatingAdmissionPolicy 和参数)资源链接在一起并提供范围限定。 如果你只想为 Pods 设置一个 owner 标签,而不是其他 API 类型,则绑定是指定此变更的位置。

要使策略生效,必须至少定义一个 MutatingAdmissionPolicy 和一个对应的 MutatingAdmissionPolicyBinding。

如果 MutatingAdmissionPolicy 不需要通过参数配置,只需将 MutatingAdmissionPolicy 中的 spec.paramKind 保留为未指定。

开始使用 MutatingAdmissionPolicies

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

创建 MutatingAdmissionPolicy

以下是 MutatingAdmissionPolicy 的示例。 此策略会变更新创建的 Pod,使其在不存在时具有 sidecar 容器。

apiVersion: admissionregistration.k8s.io/v1alpha1
kind: MutatingAdmissionPolicy
metadata:
  name: "sidecar-policy.example.com"
spec:
  paramKind:
    kind: Sidecar
    apiVersion: mutations.example.com/v1
  matchConstraints:
    resourceRules:
    - apiGroups:   ["apps"]
      apiVersions: ["v1"]
      operations:  ["CREATE"]
      resources:   ["pods"]
  matchConditions:
    - name: does-not-already-have-sidecar
      expression: "!object.spec.initContainers.exists(ic, ic.name == \"mesh-proxy\")"
  failurePolicy: Fail
  reinvocationPolicy: IfNeeded
  mutations:
    - patchType: "ApplyConfiguration"
      applyConfiguration:
        expression: >
          Object{
            spec: Object.spec{
              initContainers: [
                Object.spec.initContainers{
                  name: "mesh-proxy",
                  image: "mesh/proxy:v1.0.0",
                  args: ["proxy", "sidecar"],
                  restartPolicy: "Always"
                }
              ]
            }
          }          

.spec.mutations 字段包含一个表达式列表,这些表达式会评估为资源补丁。 发出的补丁可以是 应用配置JSON Patch 补丁。 你不能指定一个空的变更列表。 在评估所有表达式后,API 服务器会将这些更改应用于正在通过准入的资源。

要配置变更准入策略以在集群中使用,需要一个绑定。 仅当存在具有引用的 spec.policyName 与策略的 spec.name 匹配的相应绑定时,MutatingAdmissionPolicy 才会处于活动状态。

创建绑定和策略后,任何与策略的 spec.matchConditions 匹配的资源请求都将触发定义的变更集。

在上面的示例中,创建 Pod 将添加 mesh-proxy initContainer 变更

apiVersion: v1
kind: Pod
metadata:
  name: myapp
  namespace: default
spec:
  ...
  initContainers:
  - name: mesh-proxy
    image: mesh/proxy:v1.0.0
    args: ["proxy", "sidecar"]
    restartPolicy: Always
  - name: myapp-initializer
    image: example/initializer:v1.0.0
  ...

参数资源

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

请参阅 参数资源 了解更多信息。

ApplyConfiguration

MutatingAdmissionPolicy 表达式始终为 CEL。 每个应用配置 expression 必须评估为 CEL 对象(使用 Object() 初始化声明)。

由于意外删除应用配置中未包含的值的风险,应用配置可能不会修改原子结构、映射或数组。

CEL 表达式可以访问创建应用配置所需的对象类型

  • Object - 资源对象的 CEL 类型。
  • Object.<fieldName> - 对象字段的 CEL 类型(例如 Object.spec
  • Object.<fieldName1>.<fieldName2>...<fieldNameN> - 嵌套字段的 CEL 类型(例如 Object.spec.containers

CEL 表达式可以访问 API 请求的内容,这些内容组织为 CEL 变量以及其他一些有用的变量

  • object - 来自传入请求的对象。 对于 DELETE 请求,该值为 null。
  • oldObject - 现有对象。 对于 CREATE 请求,该值为 null。
  • request - API 请求的属性。
  • params - 由正在评估的策略绑定引用的参数资源。 仅当策略具有 ParamKind 时才填充。
  • namespaceObject - 传入对象所属的命名空间对象。 对于集群范围的资源,该值为 null。
  • variables - 从其名称到其延迟评估的值的组合变量映射。 例如,名为 foo 的变量可以作为 variables.foo 访问。
  • authorizer - CEL 授权器。 可用于对请求的主体(用户或服务帐户)执行授权检查。 请参阅 https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz
  • authorizer.requestResource - 从 authorizer 构建并使用请求资源配置的 CEL ResourceCheck。

apiVersionkindmetadata.namemetadata.generateNamemetadata.labels 始终可以从根目录访问
对象。无法访问其他元数据属性。

JSONPatch

相同的变更可以写成如下的 JSON Patch

apiVersion: admissionregistration.k8s.io/v1alpha1
kind: MutatingAdmissionPolicy
metadata:
  name: "sidecar-policy.example.com"
spec:
  paramKind:
    kind: Sidecar
    apiVersion: mutations.example.com/v1
  matchConstraints:
    resourceRules:
    - apiGroups:   [""]
      apiVersions: ["v1"]
      operations:  ["CREATE"]
      resources:   ["pods"]
  matchConditions:
    - name: does-not-already-have-sidecar
      expression: "!object.spec.initContainers.exists(ic, ic.name == \"mesh-proxy\")"
  failurePolicy: Fail
  reinvocationPolicy: IfNeeded
  mutations:
    - patchType: "JSONPatch"
      jsonPatch:
        expression: >
          [
            JSONPatch{
              op: "add", path: "/spec/initContainers/-",
              value: Object.spec.initContainers{
                name: "mesh-proxy",
                image: "mesh-proxy/v1.0.0",
                restartPolicy: "Always"
              }
            }
          ]          

该表达式将由 CEL 评估以创建 JSON Patch。 参考:https://github.com/google/cel-spec

每个评估的 expression 必须返回 JSONPatch 值的数组。
JSONPatch 类型表示来自 JSON 补丁的一个操作。

例如,此 CEL 表达式返回一个 JSON 补丁以有条件地修改值

  [
    JSONPatch{op: "test", path: "/spec/example", value: "Red"},
    JSONPatch{op: "replace", path: "/spec/example", value: "Green"}
  ]

要为补丁操作 value 定义一个 JSON 对象,请使用 CEL Object 类型。 例如

  [
    JSONPatch{
      op: "add",
      path: "/spec/selector",
      value: Object.spec.selector{matchLabels: {"environment": "test"}}
    }
  ]

要使用包含 '/' 和 '~' 作为 JSONPatch 路径键的字符串,请使用 jsonpatch.escapeKey()。 例如

  [
    JSONPatch{
      op: "add",
      path: "/metadata/labels/" + jsonpatch.escapeKey("example.com/environment"),
      value: "test"
    },
  ]

CEL 表达式可以访问创建 JSON 补丁和对象所需的类型

  • JSONPatch - JSON Patch 操作的 CEL 类型。JSONPatch 具有 opfrompathvalue 字段。有关更多详细信息,请参阅 JSON patchvalue 字段可以设置为以下任意类型:字符串、整数、数组、映射或对象。如果设置了 value,则 pathfrom 字段必须设置为 JSON 指针 字符串,其中 jsonpatch.escapeKey() CEL 函数可用于转义包含 /~ 的路径键。
  • Object - 资源对象的 CEL 类型。
  • Object.<fieldName> - 对象字段的 CEL 类型(例如 Object.spec
  • Object.<fieldName1>.<fieldName2>...<fieldNameN> - 嵌套字段的 CEL 类型(例如 Object.spec.containers

CEL 表达式可以访问 API 请求的内容,这些内容组织为 CEL 变量以及其他一些有用的变量

  • object - 来自传入请求的对象。 对于 DELETE 请求,该值为 null。
  • oldObject - 现有对象。 对于 CREATE 请求,该值为 null。
  • request - API 请求的属性。
  • params - 由正在评估的策略绑定引用的参数资源。 仅当策略具有 ParamKind 时才填充。
  • namespaceObject - 传入对象所属的命名空间对象。 对于集群范围的资源,该值为 null。
  • variables - 从其名称到其延迟评估的值的组合变量映射。 例如,名为 foo 的变量可以作为 variables.foo 访问。
  • authorizer - CEL 授权器。 可用于对请求的主体(用户或服务帐户)执行授权检查。 请参阅 https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz
  • authorizer.requestResource - 从 authorizer 构建并使用请求资源配置的 CEL ResourceCheck。

CEL 表达式可以访问 Kubernetes CEL 函数库,以及

  • jsonpatch.escapeKey - 执行 JSONPatch 键转义。~/ 分别转义为 ~0~1

只有 [a-zA-Z_.-/][a-zA-Z0-9_.-/]* 形式的属性名称可以访问。

上次修改时间:2024 年 11 月 26 日下午 1:20 PST:KEP-3962:修改准入策略文档 (#48646) (cb8e5a7ce5)