Leo

你所依赖的每一个准入 Webhook 都存在逃逸口。这并不耸人听闻,只是 Kubernetes 的布线方式。CNCF 于 7 月 30 日发表的一篇文章提出了一种解决方案:把签名与声明校验从 API Server 移入容器运行时本身,借助 Node Resource Interface 插件实现。

一句话概括:Supply Chain NRI Plugin 在运行时(CRI-O 或 containerd)钩住 CreateContainer 事件,从运行时注解中取出镜像引用与摘要,从 OCI Registry 获取声明,再根据命名空间级策略进行验证,之后才允许容器启动。它会检查三类产物:SLSA 溯源、VEX 文档及 VSA。若验证失败,容器不会启动。该钩子在创建时触发,而非镜像拉取时,因此即使镜像已在节点上停留数小时,实际运行前仍会再次校验。

为什么准入并非全部

你已经了解其失效场景。CNCF 文章列出四种:由 kubelet 直接管理的静态 Pod 完全绕过准入(镜像 Pod 可失效,容器仍会运行);任何拥有 kubelet 直接访问权限的人都能绕过 API Server;命名空间选择器配置错误会静默放行整个命名空间;准入 Webhook 宕机时只能二选一:集群锁死或静默绕过。

Kyverno、OPA Gatekeeper 以及 Sigstore Policy Controller 都运行在 API 层,因此都继承了这些逃逸口。问题在于这一层,而非这些项目。把校验下沉到运行时即可闭环:无论容器通过何种路径被调度,都必须经过运行时。

代价

运行时级验证并非免费午餐。你现在依赖每个节点上都健康运行的插件,且每个 CreateContainer 调用都需要凭证与网络路径访问 OCI Registry。失败开放即合规作秀,失败关闭则一次 Registry 抖动就可能导致全集群启动停滞。文章并未说明当 Registry 不可达时插件如何处理,也未说明策略更新如何在节点间滚动生效。在你把这项功能用于关键业务前,需要先回答这两个问题。

结论:信任边界确实向正确方向移动,且四条逃逸路径真实存在。请自行准备当 Registry 出现糟糕状况时的运维手册。