Pod 安全准入控制器打算替换已弃用的 PodSecurityPolicy。(V1.25及以上)
Pod 安全性标准
Pod 安全性标准定义了三种不同的策略(Policy),以广泛覆盖安全应用场景。 这些策略是叠加式的(Cumulative),安全级别从高度宽松至高度受限。 本指南概述了每个策略的要求。
Profile | 描述 |
---|---|
Privileged | 不受限制的策略,提供最大可能范围的权限许可。此策略允许已知的特权提升。 |
Baseline | 限制性最弱的策略,禁止已知的特权提升。允许使用默认的(规定最少)Pod 配置。 |
Restricted | 限制性非常强的策略,遵循当前的保护 Pod 的最佳实践。 |
Profile 细节
Privileged
Privileged 策略是有目的地开放且完全无限制的策略。 此类策略通常针对由特权较高、受信任的用户所管理的系统级或基础设施级负载。
Privileged 策略定义中限制较少。 如果你定义应用了 Privileged 安全策略的 Pod,你所定义的这个 Pod 能够绕过典型的容器隔离机制。 例如,你可以定义有权访问节点主机网络的 Pod。
Baseline
Baseline 策略的目标是便于常见的容器化应用采用,同时禁止已知的特权提升。 此策略针对的是应用运维人员和非关键性应用的开发人员。 下面列举的控制应该被实施(禁止):
说明:
在下述表格中,通配符(*
)意味着一个列表中的所有元素。 例如 spec.containers[*].securityContext
表示所定义的所有容器的安全性上下文对象。 如果所列出的任一容器不能满足要求,整个 Pod 将无法通过校验。
控制(Control) | 策略(Policy) |
HostProcess |
Windows Pod 提供了运行 HostProcess 容器的能力, 这使得对 Windows 宿主的特权访问成为可能。Baseline 策略中禁止对宿主的特权访问。 特性状态:
Kubernetes v1.26 [stable]
限制的字段
准许的取值
|
宿主名字空间 |
必须禁止共享宿主上的名字空间。 限制的字段
准许的取值
|
特权容器 |
特权 Pod 会使大多数安全性机制失效,必须被禁止。 限制的字段
准许的取值
|
权能 |
必须禁止添加除下列字段之外的权能。 限制的字段
准许的取值
|
HostPath 卷 |
必须禁止 HostPath 卷。 限制的字段
准许的取值
|
宿主端口 |
应该完全禁止使用宿主端口(推荐)或者至少限制只能使用某确定列表中的端口。 限制的字段
准许的取值
|
AppArmor |
在受支持的主机上,默认使用 限制的字段
准许的取值<
准许的取值
|
SELinux |
设置 SELinux 类型的操作是被限制的,设置自定义的 SELinux 用户或角色选项是被禁止的。 限制的字段
准许的取值
限制的字段
准许的取值
|
/proc 挂载类型 |
要求使用默认的 限制的字段
准许的取值
|
Seccomp |
Seccomp 配置必须不能显式设置为 限制的字段
准许的取值
|
Sysctls |
sysctl 可以禁用安全机制或影响宿主上所有容器,因此除了若干“安全”的允许子集之外,其他都应该被禁止。 如果某 sysctl 是受容器或 Pod 的名字空间限制,且与节点上其他 Pod 或进程相隔离,可认为是安全的。 限制的字段
准许的取值
|
Restricted
Restricted 策略旨在实施当前保护 Pod 的最佳实践,尽管这样作可能会牺牲一些兼容性。 该类策略主要针对运维人员和安全性很重要的应用的开发人员,以及不太被信任的用户。 下面列举的控制需要被实施(禁止):
说明:
在下述表格中,通配符(*
)意味着一个列表中的所有元素。 例如 spec.containers[*].securityContext
表示所定义的所有容器的安全性上下文对象。 如果所列出的任一容器不能满足要求,整个 Pod 将无法通过校验。
控制 | 策略 |
Baseline 策略的所有要求 | |
卷类型 |
Restricted 策略仅允许以下卷类型。 限制的字段
准许的取值 spec.volumes[*] 列表中的每个条目必须将下面字段之一设置为非空值:
|
特权提升(v1.8+) |
禁止(通过 SetUID 或 SetGID 文件模式)获得特权提升。这是 v1.25+ 中仅针对 Linux 的策略 限制的字段
准许的取值
|
以非 root 账号运行 |
容器必须以非 root 账号运行。 限制的字段
准许的取值
spec.securityContext.runAsNonRoot 设置为 true ,则允许容器组的安全上下文字段设置为 未定义/nil 。 |
非 root 用户(v1.23+) |
容器不可以将 runAsUser 设置为 0 限制的字段
准许的取值
|
Seccomp (v1.19+) |
Seccomp Profile 必须被显式设置成一个允许的值。禁止使用 限制的字段
准许的取值
spec.securityContext.seccompProfile.type 已设置得当,容器级别的安全上下文字段可以为未定义/nil 。 反之如果 所有的 容器级别的安全上下文字段已设置, 则 Pod 级别的字段可为 未定义/nil 。 |
权能(v1.22+) |
容器必须弃用 限制的字段
准许的取值
限制的字段
准许的取值
|
策略实例化
将策略定义从策略实例中解耦出来有助于形成跨集群的策略理解和语言陈述, 以免绑定到特定的下层实施机制。
随着相关机制的成熟,这些机制会按策略分别定义在下面。特定策略的实施方法不在这里定义。
Pod 安全性准入控制器
- Privileged 名字空间
- Baseline 名字空间
- Restricted 名字空间
替代方案
在 Kubernetes 生态系统中还在开发一些其他的替代方案,例如:
- Kubewarden
- Kyverno
- OPA Gatekeeper
Pod OS 字段
Kubernetes 允许你使用运行 Linux 或 Windows 的节点。你可以在一个集群中混用两种类型的节点。 Kubernetes 中的 Windows 与基于 Linux 的工作负载相比有一些限制和差异。 具体而言,许多 Pod securityContext
字段在 Windows 上不起作用。
说明:
v1.24 之前的 kubelet 不强制处理 Pod OS 字段,如果集群中有些节点运行早于 v1.24 的版本, 则应将 Restricted 策略锁定到 v1.25 之前的版本。
限制性的 Pod Security Standard 变更
Kubernetes v1.25 中的另一个重要变化是 Restricted 策略已更新, 能够处理 pod.spec.os.name
字段。根据 OS 名称,专用于特定 OS 的某些策略对其他 OS 可以放宽限制。
OS 特定的策略控制
仅当 .spec.os.name
不是 windows
时,才需要对以下控制进行限制:
- 特权提升
- Seccomp
- Linux 权能
用户命名空间
用户命名空间是 Linux 特有的功能,可在运行工作负载时提高隔离度。 关于用户命名空间如何与 PodSecurityStandard 协同工作, 请参阅文档了解 Pod 如何使用用户命名空间。
常见问题
为什么不存在介于 Privileged 和 Baseline 之间的策略类型
这里定义的三种策略框架有一个明晰的线性递进关系,从最安全(Restricted)到最不安全(Privileged), 并且覆盖了很大范围的工作负载。特权要求超出 Baseline 策略,这通常是特定于应用的需求, 所以我们没有在这个范围内提供标准框架。这并不意味着在这样的情形下仍然只能使用 Privileged 框架, 只是说处于这个范围的策略需要因地制宜地定义。
SIG Auth 可能会在将来考虑这个范围的框架,前提是有对其他框架的需求。
安全配置与安全上下文的区别是什么?
安全上下文在运行时配置 Pod 和容器。安全上下文是在 Pod 清单中作为 Pod 和容器规约的一部分来定义的, 所代表的是传递给容器运行时的参数。
安全策略则是控制面用来对安全上下文以及安全性上下文之外的参数实施某种设置的机制。 在 2021 年 7 月, Pod 安全性策略已被废弃, 取而代之的是内置的 Pod 安全性准入控制器。
沙箱(Sandboxed)Pod 怎么处理?
现在还没有 API 标准来控制 Pod 是否被视作沙箱化 Pod。 沙箱 Pod 可以通过其是否使用沙箱化运行时(如 gVisor 或 Kata Container)来辨别, 不过目前还没有关于什么是沙箱化运行时的标准定义。
沙箱化负载所需要的保护可能彼此各不相同。例如,当负载与下层内核直接隔离开来时, 限制特权化操作的许可就不那么重要。这使得那些需要更多许可权限的负载仍能被有效隔离。
此外,沙箱化负载的保护高度依赖于沙箱化的实现方法。 因此,现在还没有针对所有沙箱化负载的建议配置。
Pod 安全性准入
Kubernetes v1.25 [stable]
Kubernetes Pod 安全性标准(Security Standard) 为 Pod 定义不同的隔离级别。这些标准能够让你以一种清晰、一致的方式定义如何限制 Pod 行为。
Kubernetes 提供了一个内置的 Pod Security 准入控制器来执行 Pod 安全标准 (Pod Security Standard)。 创建 Pod 时在名字空间级别应用这些 Pod 安全限制。
内置 Pod 安全准入强制执行
本页面是 Kubernetes v1.32 文档的一部分。 如果你运行的是其他版本的 Kubernetes,请查阅该版本的文档。
Pod 安全性级别
Pod 安全性准入插件对 Pod 的安全性上下文有一定的要求, 并且依据 Pod 安全性标准所定义的三个级别 (privileged
、baseline
和 restricted
)对其他字段也有要求。 关于这些需求的更进一步讨论,请参阅 Pod 安全性标准页面。
为名字空间设置 Pod 安全性准入控制标签
一旦特性被启用或者安装了 Webhook,你可以配置名字空间以定义每个名字空间中 Pod 安全性准入控制模式。 Kubernetes 定义了一组标签, 你可以设置这些标签来定义某个名字空间上要使用的预定义的 Pod 安全性标准级别。 你所选择的标签定义了检测到潜在违例时, 控制面要采取什么样的动作。
模式 | 描述 |
---|---|
enforce | 策略违例会导致 Pod 被拒绝 |
audit | 策略违例会触发审计日志中记录新事件时添加审计注解;但是 Pod 仍是被接受的。 |
warn | 策略违例会触发用户可见的警告信息,但是 Pod 仍是被接受的。 |
名字空间可以配置任何一种或者所有模式,或者甚至为不同的模式设置不同的级别。
对于每种模式,决定所使用策略的标签有两个:
# 模式的级别标签用来标示对应模式所应用的策略级别
#
# MODE 必须是 `enforce`、`audit` 或 `warn` 之一
# LEVEL 必须是 `privileged`、baseline` 或 `restricted` 之一
pod-security.kubernetes.io/<MODE>: <LEVEL># 可选:针对每个模式版本的版本标签可以将策略锁定到
# 给定 Kubernetes 小版本号所附带的版本(例如 v1.32)
#
# MODE 必须是 `enforce`、`audit` 或 `warn` 之一
# VERSION 必须是一个合法的 Kubernetes 小版本号或者 `latest`
pod-security.kubernetes.io/<MODE>-version: <VERSION>
关于用法示例,可参阅使用名字空间标签来强制实施 Pod 安全标准。
负载资源和 Pod 模板
Pod 通常是通过创建 Deployment 或 Job 这类工作负载对象来间接创建的。 工作负载对象为工作负载资源定义一个 Pod 模板和一个对应的负责基于该模板来创建 Pod 的控制器。 为了尽早地捕获违例状况,audit
和 warn
模式都应用到负载资源。 不过,enforce
模式并不应用到工作负载资源,仅应用到所生成的 Pod 对象上。
豁免
你可以为 Pod 安全性的实施设置豁免(Exemptions) 规则, 从而允许创建一些本来会被与给定名字空间相关的策略所禁止的 Pod。 豁免规则可以在准入控制器配置 中静态配置。
豁免规则必须显式枚举。满足豁免标准的请求会被准入控制器忽略 (所有 enforce
、audit
和 warn
行为都会被略过)。 豁免的维度包括:
- Username: 来自用户名已被豁免的、已认证的(或伪装的)的用户的请求会被忽略。
- RuntimeClassName: 指定了已豁免的运行时类名称的 Pod 和负载资源会被忽略。
- Namespace: 位于被豁免的名字空间中的 Pod 和负载资源会被忽略。
注意:
大多数 Pod 是作为对工作负载资源的响应, 由控制器所创建的,这意味着为某最终用户提供豁免时,只会当该用户直接创建 Pod 时对其实施安全策略的豁免。用户创建工作负载资源时不会被豁免。 控制器服务账号(例如:system:serviceaccount:kube-system:replicaset-controller
) 通常不应该被豁免,因为豁免这类服务账号隐含着对所有能够创建对应工作负载资源的用户豁免。
策略检查时会对以下 Pod 字段的更新操作予以豁免,这意味着如果 Pod 更新请求仅改变这些字段时,即使 Pod 违反了当前的策略级别,请求也不会被拒绝。
- 除了对 seccomp 或 AppArmor 注解之外的所有元数据(Metadata)更新操作:
seccomp.security.alpha.kubernetes.io/pod
(已弃用)container.seccomp.security.alpha.kubernetes.io/*
(已弃用)container.apparmor.security.beta.kubernetes.io/*
(已弃用)
- 对
.spec.activeDeadlineSeconds
的合法更新 - 对
.spec.tolerations
的合法更新
指标
以下是 kube-apiserver 公开的 Prometheus 指标:
pod_security_errors_total
:此指标表示妨碍正常评估的错误数量。 如果错误是非致命的,kube-apiserver 可能会强制实施最新的受限配置。pod_security_evaluations_total
:此指标表示已发生的策略评估的数量, 不包括导出期间被忽略或豁免的请求。pod_security_exemptions_total
:该指标表示豁免请求的数量, 不包括被忽略或超出范围的请求。
强制实施 Pod 安全性标准
本页提供实施 Pod 安全标准(Pod Security Standards) 时的一些最佳实践。
使用内置的 Pod 安全性准入控制器
Kubernetes v1.25 [stable]
Pod 安全性准入控制器 尝试替换已被废弃的 PodSecurityPolicies。
配置所有集群名字空间
完全未经配置的名字空间应该被视为集群安全模型中的重大缺陷。 我们建议花一些时间来分析在每个名字空间中执行的负载的类型, 并通过引用 Pod 安全性标准来确定每个负载的合适级别。 未设置标签的名字空间应该视为尚未被评估。
针对所有名字空间中的所有负载都具有相同的安全性需求的场景, 我们提供了一个示例 用来展示如何批量应用 Pod 安全性标签。
拥抱最小特权原则
在一个理想环境中,每个名字空间中的每个 Pod 都会满足 restricted
策略的需求。 不过,这既不可能也不现实,某些负载会因为合理的原因而需要特权上的提升。
- 允许
privileged
负载的名字空间需要建立并实施适当的访问控制机制。 - 对于运行在特权宽松的名字空间中的负载,需要维护其独特安全性需求的文档。 如果可能的话,要考虑如何进一步约束这些需求。
采用多种模式的策略
Pod 安全性标准准入控制器的 audit
和 warn
模式(mode) 能够在不影响现有负载的前提下,让该控制器更方便地收集关于 Pod 的重要的安全信息。
针对所有名字空间启用这些模式是一种好的实践,将它们设置为你最终打算 enforce
的 期望的 级别和版本。这一阶段中所生成的警告和审计注解信息可以帮助你到达这一状态。 如果你期望负载的作者能够作出变更以便适应期望的级别,可以启用 warn
模式。 如果你希望使用审计日志了监控和驱动变更,以便负载能够适应期望的级别,可以启用 audit
模式。
当你将 enforce
模式设置为期望的取值时,这些模式在不同的场合下仍然是有用的:
- 通过将
warn
设置为enforce
相同的级别,客户可以在尝试创建无法通过合法检查的 Pod (或者包含 Pod 模板的资源)时收到警告信息。这些信息会帮助于更新资源使其合规。 - 在将
enforce
锁定到特定的非最新版本的名字空间中,将audit
和warn
模式设置为enforce
一样的级别而非latest
版本, 这样可以方便看到之前版本所允许但当前最佳实践中被禁止的设置。
第三方替代方案
Kubernetes 生态系统中也有一些其他强制实施安全设置的替代方案处于开发状态中:
- Kubewarden.
- Kyverno.
- OPA Gatekeeper.
采用 内置的 方案(例如 PodSecurity 准入控制器)还是第三方工具, 这一决策完全取决于你
自己的情况。在评估任何解决方案时,对供应链的信任都是至关重要的。 最终,使用前述方案中的 任何 一种都好过放任自流。
本页面中的条目引用了第三方产品或项目,这些产品(项目)提供了 Kubernetes 所需的功能。Kubernetes 项目的开发人员不对这些第三方产品(项目)负责。请参阅CNCF 网站指南了解更多细节。在提交更改建议,向本页添加新的第三方链接之前,你应该先阅读内容指南。
COPY自:https://kubernetes.io/zh-cn/docs/setup/best-practices/enforcing-pod-security-standards/