修改型准入策略

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

本页面提供了 MutatingAdmissionPolicies 的概览。

什么是 MutatingAdmissionPolicies?

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

修改准入策略使用 Common Expression Language (CEL) 声明对资源的修改。修改可以通过使用服务器端应用合并策略合并的 apply configuration 定义,或者通过JSON 补丁定义。

修改准入策略具有高度可配置性,使得策略作者能够根据集群管理员的需求定义可以参数化和限定作用域的策略。

构成策略的资源

策略通常由三种资源构成

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

  • 参数资源为 MutatingAdmissionPolicy 提供信息,使其成为一个具体的声明(思考:“将 owner 标签设置为 company.example.com 等内容”)。参数资源引用 Kubernetes API 中可用的 Kubernetes 资源。它们可以是内置类型或扩展类型,例如 CustomResourceDefinition (CRD)。例如,你可以使用 ConfigMap 作为参数。

  • MutatingAdmissionPolicyBinding 将上述资源(MutatingAdmissionPolicy 和参数)链接在一起并提供作用域。如果你只想为 Pods 设置 owner 标签,而不是其他 API Kind,则在绑定中指定此修改。

策略生效至少需要定义一个 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 补丁。你不能指定一个空的修改列表。评估完所有表达式后,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 引用的特定参数资源关联起来。

有关更多信息,请参阅参数资源

应用配置

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 - 复合变量的映射,从其名称到其延迟评估的值。例如,可以通过 variables.foo 访问名为 foo 的变量。
  • authorizer - CEL Authorizer。可用于对请求主体(用户或 ServiceAccount)执行授权检查。参见 https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz
  • authorizer.requestResource - 根据 authorizer 构建并使用请求资源配置的 CEL ResourceCheck。

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

JSON 补丁

相同的修改可以写成如下所示的 JSON 补丁

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 补丁。参考: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 补丁操作的 CEL 类型。JSONPatch 包含 opfrompathvalue 字段。详情请参阅 JSON 补丁value 字段可以设置为以下任意类型:string、integer、array、map 或 object。如果设置了 value,则 pathfrom 字段必须设置为 JSON pointer 字符串,其中可以使用 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 - 复合变量的映射,从其名称到其延迟评估的值。例如,可以通过 variables.foo 访问名为 foo 的变量。
  • authorizer - CEL Authorizer。可用于对请求主体(用户或 ServiceAccount)执行授权检查。参见 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_.-/]* 的属性名称才可访问。

免于修改准入的 API Kind

某些 API Kind 免于准入时修改。例如,你不能创建一个更改 MutatingAdmissionPolicy 的 MutatingAdmissionPolicy。

免于准入的 API Kind 列表为:

上次修改时间:2025年1月22日 太平洋标准时间 下午6:31:在修改准入策略文档中添加豁免的 API Kind (0338db1b94)