PodSecurityPolicy:历史背景

自 Kubernetes v1.25 起,PodSecurityPolicy (PSP) 准入控制器已被移除。其弃用消息已在 Kubernetes v1.21 版本的博文 PodSecurityPolicy 弃用:过去、现在和未来 中宣布和详细说明。

本文旨在提供有关 PSP 诞生和演变的背景,解释该功能为何从未进入稳定阶段,并说明为何它被移除并由 Pod Security 准入控制所取代。

PodSecurityPolicy 与其他专门的准入控制插件一样,作为内置的策略 API,为有关 Pod 安全设置的特定字段提供了细粒度的权限。它承认集群管理员和集群用户通常不是同一拨人,并且以 Pod 或任何将创建 Pod 的资源形式创建工作负载不应等同于“集群上的 root”。它还可以通过突变配置更安全的默认值,并将底层 Linux 安全决策与部署过程解耦,从而鼓励最佳实践。

PodSecurityPolicy 的诞生

PodSecurityPolicy 源于 OpenShift 的 SecurityContextConstraints (SCC),它存在于 Red Hat OpenShift 容器平台的最初版本中,甚至早于 Kubernetes 1.0。PSP 是 SCC 的精简版本。

PodSecurityPolicy 的创建起源很难追溯,特别是因为它主要是在 Kubernetes 增强提案 (KEP) 流程之前添加的,当时设计提案仍然存在。实际上,最终的 设计提案 存档仍然可用。尽管如此,在第一个拉取请求合并后,创建了一个 KEP issue 编号为 5 的问题。

在添加创建 PSP 的第一段代码之前,Kubernetes 合并了两个主要的拉取请求,一个是定义了 Pod 容器新字段的 SecurityContext 子资源,以及 ServiceAccount API 的首次迭代。

Kubernetes 1.0 于 2015 年 7 月 10 日发布,没有任何机制来限制工作负载的安全上下文和敏感选项,除了一个 alpha 质量的 SecurityContextDeny 准入插件(当时称为 scdeny)。SecurityContextDeny 插件 至今仍在 Kubernetes 中(作为 alpha 功能),它创建了一个准入控制器,防止在安全上下文中使用某些字段。

PodSecurityPolicy 的根源是通过 关于安全策略的第一个拉取请求 添加的,该请求基于 SCC(安全上下文约束)添加了带有新 PSP 对象的设计提案。这是一个长达九个月的讨论,期间在 OpenShift 的 SCC 基础上反复修改,多次 rebase,并最终更名为 PodSecurityPolicy,于 2016 年 2 月进入上游 Kubernetes。既然 PSP 对象已经创建,下一步就是添加一个可以强制执行这些策略的准入控制器。第一步是添加 不考虑用户或组 的准入机制。为了跟踪进展,创建了一个特定的 使 PodSecurityPolicy 进入可用状态的问题,并且准入控制器的第一个版本在 2016 年 5 月名为 PSP 准入 的拉取请求中合并。然后大约两个月后,Kubernetes 1.3 发布了。

以下是回顾 PodSecurityPolicy 及其准入控制器诞生过程中的主要拉取请求的时间线,以 1.0 和 1.3 版本为参考点。

Timeline of the PodSecurityPolicy creation pull requests

之后,PSP 准入控制器通过添加最初被搁置的内容得到了增强。于 2016 年 11 月初合并的 授权机制 允许管理员在集群中使用多个策略,为不同类型的用户授予不同级别的访问权限。后来,于 2017 年 10 月合并的 一个拉取请求 修复了 一个关于 PodSecurityPolicies 在变更和字母顺序之间排序的设计问题,并继续构建我们所知的 PSP 准入。之后,许多改进和修复接踵而至,构建了近期 Kubernetes 版本中的 PodSecurityPolicy 功能。

Pod Security Admission 的兴起

尽管它试图解决一个关键问题,但 PodSecurityPolicy 存在一些主要缺陷:

  • 有缺陷的授权模型 - 用户可以在对允许该 Pod 的 PSP 拥有 use 动词权限,或者 Pod 的服务账号对允许的 PSP 拥有 use 权限时创建 Pod。
  • 难以推出 - PSP 是“默认拒绝”的。也就是说,在没有策略的情况下,所有 Pod 都会被拒绝。这基本上意味着它不能默认启用,用户必须在启用该功能之前为所有工作负载添加 PSP,因此没有审计模式来发现哪些 Pod 会被新策略所不允许。这种选择加入的模型也导致了测试覆盖率不足和由于跨功能不兼容而频繁出现故障。与 RBAC 不同,没有形成在项目中附带 PSP 清单的浓厚文化。
  • 不一致且无边界的 API - API 在发展过程中出现了许多不一致性,主要是因为许多针对小众用例的请求:例如标签、调度、细粒度的卷控制等。它的可组合性很差,优先级模型很弱,导致意外的变更优先级。这使得将 PSP 与其他第三方准入控制器结合起来非常困难。
  • 需要安全知识 - 有效使用仍然需要了解 Linux 安全原语。例如 MustRunAsNonRoot + AllowPrivilegeEscalation。

PodSecurityPolicy 的经验总结出,大多数用户关心的是两到三种策略,这导致了 Pod 安全标准 的创建,该标准定义了三种策略:

  • Privileged - 不受限制的策略。
  • Baseline - 限制最少的策略,允许默认的 Pod 配置。
  • Restricted - 安全最佳实践策略。

PSP 的替代品,新的 Pod Security Admission 是一个内置的、在 Kubernetes v1.25 中稳定的准入插件,用于在命名空间级别强制执行这些标准。它使得在没有深厚安全知识的情况下更容易实施基本的 Pod 安全。对于更复杂的用例,您可能需要一个可以轻松与 Pod Security Admission 结合的第三方解决方案。

接下来

有关 SIG Auth 流程的更多细节,涵盖 PodSecurityPolicy 移除和 Pod Security Admission 的创建,可以观看 KubeCon NA 2019 上的 SIG auth 更新 和 KubeCon NA 2021 上的 PodSecurityPolicy 替代方案:过去、现在和未来 演讲录像。

特别是在 PSP 移除方面,PodSecurityPolicy 弃用:过去、现在和未来 这篇博文仍然是准确的。

对于新的 Pod Security Admission,已有相关文档。此外,博文 Kubernetes 1.23: Pod Security 升级至 Beta 以及 KubeCon EU 2022 的演讲 Pod 安全漫游指南 提供了很好的实践教程供学习。