基于清单的准入控制
Kubernetes v1.36 [alpha](默认禁用)本页面概述了基于清单的准入控制配置。 基于清单的准入控制允许你从磁盘上的静态文件而非 Kubernetes API 加载准入 Webhook 和基于 CEL 的准入策略。这些策略从 API 服务器启动时就处于活跃状态, 独立于 etcd 运行, 并且可以保护基于 API 的准入资源免受修改。
要使用此功能,请在 kube-apiserver 上启用
ManifestBasedAdmissionControlConfig
特性门控,
并在通过 --admission-control-config-file 传递给 kube-apiserver 的
AdmissionConfiguration
文件中配置 staticManifestsDir 字段。
为什么要使用基于清单的准入控制?
通过 Kubernetes API 注册的准入策略和 Webhook(如 ValidatingAdmissionPolicy、 MutatingAdmissionPolicy、ValidatingWebhookConfiguration 和 MutatingWebhookConfiguration)有几个固有局限性:
- 引导间隙:基于 REST 的策略执行需要由动态准入控制器创建和加载 API 对象。在此之前,策略不会被执行。
- 自我保护间隙:准入配置资源(如 ValidatingWebhookConfiguration) 本身不受 Webhook 准入控制,以防止循环依赖。 具有足够权限的用户可以删除或修改关键准入策略。
- etcd 依赖:基于 REST 的准入配置依赖于 etcd 的可用性。 如果 etcd 不可用或损坏,准入策略可能无法正确加载。
基于清单的准入控制通过从磁盘上的文件加载配置来解决这些局限性。 这些配置具有以下特点:
- 从 API 服务器准备好提供请求服务的那一刻起就处于活跃状态
- 通过 Kubernetes API 无法查看或更改
- 不依赖于 etcd 的可用性
- 能够拦截对基于 API 的准入资源本身的操作
支持的资源类型
你可以在清单文件中包含以下资源类型。仅支持
admissionregistration.k8s.io/v1 API 版本。
| 插件名称 | 支持的资源类型 |
|---|---|
ValidatingAdmissionWebhook | ValidatingWebhookConfiguration |
MutatingAdmissionWebhook | MutatingWebhookConfiguration |
ValidatingAdmissionPolicy | ValidatingAdmissionPolicy、ValidatingAdmissionPolicyBinding |
MutatingAdmissionPolicy | MutatingAdmissionPolicy、MutatingAdmissionPolicyBinding |
你也可以使用 v1.List 将同一插件类型的多个资源包装在单个文档中。
每个准入插件的 staticManifestsDir 只能包含该插件允许的资源类型。
例如,为 ValidatingAdmissionPolicy 插件配置的目录只能包含
ValidatingAdmissionPolicy 和 ValidatingAdmissionPolicyBinding 资源。
配置基于清单的准入控制
要启用基于清单的准入控制,你需要:
- 在 kube-apiserver 上启用
ManifestBasedAdmissionControlConfig特性门控。 - 一个
AdmissionConfiguration文件,其staticManifestsDir字段指向包含清单文件的目录。 - 清单文件本身在磁盘上,且 kube-apiserver 进程可以访问。
AdmissionConfiguration
为每个需要从磁盘加载清单的准入插件在插件配置中添加 staticManifestsDir。
每个插件都需要自己的目录。
staticManifestsDir 字段接受目录的绝对路径。目录中所有带 .yaml、.yml
或 .json 扩展名的直接子文件都会被加载。子目录和其他扩展名的文件会被忽略。
不支持 Glob 模式和相对路径。
使用 --admission-control-config-file 标志将此文件传递给 kube-apiserver。
配置类型
每个准入插件使用特定配置类型:
| 插件 | apiVersion | kind |
|---|---|---|
ValidatingAdmissionWebhook | apiserver.config.k8s.io/v1 | WebhookAdmissionConfiguration |
MutatingAdmissionWebhook | apiserver.config.k8s.io/v1 | WebhookAdmissionConfiguration |
ValidatingAdmissionPolicy | apiserver.config.k8s.io/v1 | ValidatingAdmissionPolicyConfiguration |
MutatingAdmissionPolicy | apiserver.config.k8s.io/v1 | MutatingAdmissionPolicyConfiguration |
编写清单文件
清单文件包含标准的 Kubernetes 资源定义。你可以使用 YAML 文档分隔符(---)
在单个文件中包含多个资源。
命名约定
清单文件中的所有对象名称必须以 .static.k8s.io 后缀结尾。
例如:deny-privileged.static.k8s.io。
当 ManifestBasedAdmissionControlConfig 特性门控被启用时,
阻止创建名称以 .static.k8s.io 结尾的基于 API 的准入对象。
当特性门控被禁用时,则返回一个警告。
说明:
如果两个清单文件定义了相同类型的对象,且对象名称相同,则 API 服务器启动失败,显示描述性错误。
限制
基于清单的准入配置独立存在,不能引用 API 资源。适用以下限制:
- Webhook:必须使用
clientConfig.url。不允许使用clientConfig.service字段,因为服务网络可能在 API 服务器启动时不可用。 - 策略:不允许使用
spec.paramKind字段。策略不能引用 ConfigMap 或其他集群对象作为参数。 - 绑定:不允许使用
spec.paramRef字段。spec.policyName必须引用在同一清单文件集中定义的策略,且必须以.static.k8s.io结尾。
清单文件使用严格解码器进行解码,该解码器会拒绝包含重复字段或未知字段的文件。 每个对象都会经历与 REST API 相同的默认设置和验证。
示例
保护基于 API 的准入资源
基于清单的准入控制的一个关键能力是能够拦截对准入配置资源本身的操作 (ValidatingAdmissionPolicy、MutatingAdmissionPolicy、 ValidatingWebhookConfiguration、MutatingWebhookConfiguration 及其绑定)。 基于 REST 的准入 Webhook 和策略不会对这些资源类型调用,以防止循环依赖, 但基于清单的策略可以对其执行规则,因为它们没有这种循环依赖。
以下示例防止删除或修改带有 platform.example.com/protected: "true" 标签的准入资源:
从磁盘强制执行 ValidatingAdmissionPolicy
以下示例定义了一个策略,除 kube-system 外拒绝所有名字空间中的特权容器:
将此文件放入为 ValidatingAdmissionPolicy 插件配置的
staticManifestsDir 目录中。策略及其绑定会被一起原子性地加载。
从磁盘配置 ValidatingWebhookConfiguration
以下示例配置了一个调用外部 URL 的验证 Webhook:
说明:
Webhook URL 必须在启动时从 kube-apiserver 可达。仅支持基于 URL 的端点; 在基于清单的 Webhook 配置中不允许使用服务引用。
使用 List 格式
你可以使用 v1.List 将相关资源分组在单个文档中:
评估顺序
基于清单的配置在基于 API 的配置之前被评估。 这确保了通过静态配置强制执行的平台级策略优先于基于 API 的策略。
对于准入配置资源本身(ValidatingAdmissionPolicy、 MutatingAdmissionPolicy、ValidatingAdmissionPolicyBinding、 MutatingAdmissionPolicyBinding、ValidatingWebhookConfiguration、 MutatingWebhookConfiguration),只评估基于清单的准入钩子。 为防止循环依赖,这些资源类型会跳过基于 API 的钩子。
文件监视和动态重新加载
kube-apiserver 监视配置的目录以获取变更:
- 初始加载:在启动时,所有配置的路径都会被读取和验证。 在所有清单成功加载之前,API 服务器不会变为就绪状态。 无效的清单会导致启动失败。
- 运行时重新加载:对清单文件的更改会触发重新加载周期:
- 使用 fsnotify 检测文件修改, 并有轮询回退机制(默认间隔 1 分钟),类似于 kube-apiserver 中的其他配置文件重新加载。
- 每次检查时计算所有清单文件的内容哈希。如果哈希未更改,则不会重新加载。
- 新配置在应用之前会被验证。
- 如果验证失败,错误会被记录,指标会被更新,并保留之前的有效配置。
- 成功的重新加载会原子性地替换之前的配置。
- 原子性文件更新:为避免在文件写入期间进行部分读取, 请原子性地进行更改(例如,先写入临时文件然后重命名)。 这在更新容器化环境中挂载的 ConfigMap 或 Secret 时尤为重要。
注意:
如果启动时存在无效的清单文件,API 服务器不会启动。 如果在运行时重新加载失败,会保留之前的有效配置并记录错误。
可观测性
指标
基于清单的准入控制提供以下指标用于监控重新加载健康状态:
| 类型 | 描述 | 指标 |
|---|---|---|
| Counter | 重新加载尝试总数,带有 status(success 或 failure)、plugin 和 apiserver_id_hash 标签。 | apiserver_manifest_admission_config_controller_automatic_reloads_total |
| Gauge | 最后一次重新加载尝试的时间戳,带有 status、plugin 和 apiserver_id_hash 标签。 | apiserver_manifest_admission_config_controller_automatic_reload_last_timestamp_seconds |
| Gauge | 当前配置信息(值始终为 1),带有 plugin、apiserver_id_hash 和 hash 标签。使用 hash 标签可以检测跨 API 服务器的配置漂移。 | apiserver_manifest_admission_config_controller_last_config_info |
plugin 标签标识指标适用的准入插件:
ValidatingAdmissionWebhook、MutatingAdmissionWebhook、
ValidatingAdmissionPolicy 或 MutatingAdmissionPolicy。
由于基于清单的对象名称以 .static.k8s.io 结尾,
现有的准入指标(如 apiserver_admission_webhook_rejection_count)
可以通过过滤 name 标签来识别基于清单的决策。
审计注解
现有审计注解(如 validation.policy.admission.k8s.io/validation_failure
和 mutation.webhook.admission.k8s.io/round_0_index_0)包含对象名称。
你可以通过过滤以 .static.k8s.io 结尾的名称来识别基于清单的准入决策。
高可用性注意事项
每个 kube-apiserver 实例独立加载自己的清单文件。 在具有多个 API 服务器实例的高可用性设置中:
- 每个 API 服务器必须单独配置。基于清单的配置没有跨 API 服务器同步。
- 使用外部配置管理工具(如 Ansible、Puppet 或共享存储挂载) 来保持清单文件在各个实例之间一致。
apiserver_manifest_admission_config_controller_last_config_info指标暴露了一个hash标签,你可以使用它来检测跨 API 服务器实例的配置漂移。
此行为类似于其他基于文件的 kube-apiserver 配置, 如静态加密 和身份验证。
升级和降级
升级:启用此功能并提供清单配置是可选的。 没有清单配置的现有集群不会看到行为变化。
降级:在降级到没有此功能的版本之前:
- 从
AdmissionConfiguration文件中移除staticManifestsDir条目。 - 如果依赖基于清单的策略,请尽可能将它们重新创建为 API 对象。
- 重启 kube-apiserver。
警告:
降级时,如果不移除 staticManifestsDir 配置,API 服务器会启动失败,
因为存在未知的配置字段。
故障排除
| 症状 | 可能原因 | 解决方法 |
|---|---|---|
| API 服务器启动失败 | 启动时存在无效的清单文件 | 检查 API 服务器日志中的验证错误。修复清单文件并重启。 |
| API 服务器启动失败 | 清单文件之间存在重复的对象名称 | 确保插件的 staticManifestsDir 内的所有对象名称唯一。 |
| 文件更新后策略未执行 | 重新加载验证失败 | 检查 automatic_reloads_total{status="failure"} 指标和 API 服务器日志。修复清单并等待下一个重新加载周期。 |
| Webhook 请求失败 | Webhook URL 不可达 | 验证 clientConfig.url 中指定的 URL 从 kube-apiserver 可访问。 |
无法创建带有 .static.k8s.io 后缀的 API 对象 | 名称后缀被特性门控保留 | 当特性门控启用时,.static.k8s.io 后缀保留用于基于清单的配置。为基于 API 的对象使用其他名称。 |
接下来
- 了解 ValidatingAdmissionPolicy 以获取基于 CEL 的验证策略。
- 了解 MutatingAdmissionPolicy 以获取基于 CEL 的变更策略。
- 了解动态准入控制 以获取基于 Webhook 的准入控制。
- 阅读 KEP-5793 设计文档。