Kubernetes v1.36 [稳定版](默认启用)本页面概述了 可变准入策略 (MutatingAdmissionPolicies)。可变准入策略允许您在有人向 Kubernetes API 写入变更时修改所发生的操作。如果您只想使用声明式策略来防止对资源进行特定类型的更改(例如:防止删除平台命名空间),则 验证准入策略 (ValidatingAdmissionPolicy) 是一个更简单、更有效的替代方案。
可变准入策略为可变准入 Webhook 提供了一种声明式的进程内替代方案。
可变准入策略使用通用表达式语言 (CEL) 来声明对资源的变更。变更既可以通过使用 服务端应用合并策略 (server side apply merge strategy) 合并的 应用配置 (apply configuration) 来定义,也可以使用 JSON Patch 来定义。
可变准入策略具有高度可配置性,使策略编写者能够根据集群管理员的需要定义可参数化且作用于特定资源的策略。
一个策略通常由三种资源组成
MutatingAdmissionPolicy 描述了策略的抽象逻辑(例如:“此策略将特定标签设置为特定值”)。
参数资源 (parameter resource) 向 MutatingAdmissionPolicy 提供信息,使其成为具体的声明(例如:“将 owner 标签设置为类似 company.example.com 的值”)。参数资源引用 Kubernetes API 中可用的 Kubernetes 资源。它们可以是内置类型或扩展,例如 自定义资源定义 (CustomResourceDefinition) (CRD)。例如,您可以使用 ConfigMap 作为参数。
MutatingAdmissionPolicyBinding 将上述资源(MutatingAdmissionPolicy 和参数)链接在一起并提供作用域范围。如果您只想为 Pods 设置 owner 标签,而不涉及其他 API 类型,则可以在绑定中指定此变更。
策略要生效,至少必须定义一个 MutatingAdmissionPolicy 和一个对应的 MutatingAdmissionPolicyBinding。
.static.k8s.io 结尾的名称保留用于 基于清单的准入控制 (manifest-based admission control),不能用于基于 API 的策略或绑定。当启用 ManifestBasedAdmissionControlConfig 特性门控 (feature gate) 时,此保留规则会强制执行。如果 MutatingAdmissionPolicy 不需要通过参数进行配置,只需在 MutatingAdmissionPolicy 中不指定 spec.paramKind 即可。
可变准入策略是集群控制平面的一部分。编写和部署时应格外谨慎。以下内容描述了如何快速尝试可变准入策略。
以下是 MutatingAdmissionPolicy 的一个示例。此策略会修改新创建的 Pod,如果尚不存在 Sidecar 容器,则为其添加一个。
apiVersion: admissionregistration.k8s.io/v1
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: "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() 初始化声明)。
Apply configurations 不能修改原子结构、映射或数组,因为存在意外删除未包含在 apply configuration 中的值的风险。
CEL 表达式可以访问创建 apply configurations 所需的对象类型
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#Authzauthorizer.requestResource - 由 authorizer 构建并配置有请求资源的 CEL ResourceCheck。apiVersion、kind、metadata.name、metadata.generateName 和 metadata.labels 始终可以从对象的根访问。
无法访问其他元数据属性。
JSONPatch同样的变更可以写作 JSON Patch,如下所示
apiVersion: admissionregistration.k8s.io/v1
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 patch 中的一个操作。
例如,这个 CEL 表达式返回一个 JSON patch,用于有条件地修改一个值
[
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 patch 和对象所需的类型
JSONPatch - JSON Patch 操作的 CEL 类型。JSONPatch 具有字段 op、from、path 和 value。详见 JSON patch。value 字段可设置为:字符串、整数、数组、映射或对象。如果已设置,则 path 和 from 字段必须设置为 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#Authzauthorizer.requestResource - 由 authorizer 构建并配置有请求资源的 CEL ResourceCheck。CEL 表达式有权访问 Kubernetes CEL 函数库 以及
jsonpatch.escapeKey - 执行 JSONPatch 键转义。~ 和 / 分别转义为 ~0 和 ~1。仅 [a-zA-Z_.-/][a-zA-Z0-9_.-/]* 格式的属性名称可被访问。
某些 API 类型豁免于准入时的变更。例如,您无法创建修改 MutatingAdmissionPolicy 的 MutatingAdmissionPolicy。
豁免的 API 类型列表如下