Pod 和容器的 Linux 内核安全约束
本页描述了 Linux 内核中一些内置的安全功能,你可以在 Kubernetes 工作负载中使用这些功能。要了解如何将这些功能应用于你的 Pod 和容器,请参阅为 Pod 或容器配置 SecurityContext。你应该已经熟悉 Linux 和 Kubernetes 工作负载的基础知识。
以非 root 权限运行工作负载
当你在 Kubernetes 中部署工作负载时,可以使用 Pod 规约来限制该工作负载作为节点的 root 用户运行。你可以使用 Pod 的 `securityContext` 来为 Pod 中的进程定义特定的 Linux 用户和组,并明确限制容器作为 root 用户运行。在 Pod 清单中设置这些值优先于容器镜像中的类似值,这在运行非你拥有的镜像时特别有用。
注意
确保你分配给工作负载的用户或组具有应用程序正常运行所需的权限。将用户或组更改为不具有正确权限的用户或组可能会导致文件访问问题或操作失败。配置本页中的内核安全功能可以对集群中进程可以采取的操作进行细粒度控制,但大规模管理这些配置可能具有挑战性。以非 root 身份运行容器,或者如果需要 root 权限,则在用户命名空间中运行容器,有助于减少需要强制执行已配置的内核安全功能的可能性。
Linux 内核中的安全功能
Kubernetes 允许你配置和使用 Linux 内核功能来改进隔离并增强容器化工作负载的安全性。常见功能包括:
- 安全计算模式 (seccomp):过滤进程可以进行的系统调用
- AppArmor:限制单个程序的访问权限
- Security Enhanced Linux (SELinux):为对象分配安全标签,以便更易于管理安全策略强制执行
要配置其中一项功能的设置,你为节点选择的操作系统必须在内核中启用该功能。例如,Ubuntu 7.10 及更高版本默认启用 AppArmor。要了解你的操作系统是否启用了特定功能,请查阅操作系统文档。
你使用 Pod 规约中的 `securityContext` 字段来定义适用于这些进程的约束。`securityContext` 字段还支持其他安全设置,例如使用 UID 和 GID 的特定 Linux 功能或文件访问权限。要了解更多信息,请参阅为 Pod 或容器配置 SecurityContext。
seccomp
你的一些工作负载可能需要特权才能在节点的宿主机上作为 root 用户执行特定操作。Linux 使用*权能(capabilities)*将可用特权划分为多个类别,以便进程可以获得执行特定操作所需的特权,而无需授予所有特权。每个权能都有一组进程可以进行的系统调用(syscalls)。seccomp 允许你限制这些单独的系统调用。它可用于沙盒化进程的特权,限制它从用户空间到内核的调用能力。
在 Kubernetes 中,你使用每个节点上的*容器运行时*来运行你的容器。示例运行时包括 CRI-O、Docker 或 containerd。每个运行时默认只允许 Linux 权能的一个子集。你可以通过使用 seccomp 配置文件进一步单独限制允许的系统调用。容器运行时通常包含一个默认的 seccomp 配置文件。Kubernetes 允许你自动将加载到节点上的 seccomp 配置文件应用于你的 Pod 和容器。
注意
Kubernetes 还为 Pod 和容器提供了 `allowPrivilegeEscalation` 设置。当设置为 `false` 时,这将阻止进程获得新的权能,并限制非特权用户将应用的 seccomp 配置文件更改为更宽松的配置文件。要了解如何在 Kubernetes 中实现 seccomp,请参阅使用 seccomp 限制容器的系统调用或Seccomp 节点参考。
要了解有关 seccomp 的更多信息,请参阅 Linux 内核文档中的Seccomp BPF。
seccomp 的注意事项
seccomp 是一种低级安全配置,只有在你需要对 Linux 系统调用进行细粒度控制时才应自行配置。大规模使用 seccomp,尤其是在以下方面存在风险:
- 配置可能在应用程序更新期间中断
- 攻击者仍然可以使用允许的系统调用来利用漏洞
- 大规模地管理单个应用程序的配置文件变得具有挑战性
建议:使用容器运行时捆绑的默认 seccomp 配置文件。如果需要更隔离的环境,请考虑使用沙盒,例如 gVisor。沙盒解决了上述使用自定义 seccomp 配置文件带来的风险,但需要节点上更多的计算资源,并且可能与 GPU 和其他专用硬件存在兼容性问题。
AppArmor 和 SELinux:基于策略的强制访问控制
你可以使用 Linux 基于策略的强制访问控制 (MAC) 机制(例如 AppArmor 和 SELinux)来增强你的 Kubernetes 工作负载。
AppArmor
AppArmor 是一个 Linux 内核安全模块,它补充了标准的基于 Linux 用户和组的权限,以将程序限制在有限的资源集内。AppArmor 可以为任何应用程序配置,以减少其潜在的攻击面并提供更深入的防御。它通过配置文件进行配置,这些配置文件经过调整以允许特定程序或容器所需的访问权限,例如 Linux 功能、网络访问和文件权限。每个配置文件可以以强制模式运行,该模式阻止对不允许的资源的访问,或者以抱怨模式运行,该模式只报告违规。
AppArmor 可以通过限制容器可以做什么和/或通过系统日志提供更好的审计来帮助你运行更安全的部署。你使用的容器运行时可能附带一个默认的 AppArmor 配置文件,或者你可以使用自定义配置文件。
要了解如何在 Kubernetes 中使用 AppArmor,请参阅使用 AppArmor 限制容器对资源的访问。
SELinux
SELinux 是一个 Linux 内核安全模块,它允许你限制特定*主体*(例如进程)对系统上文件的访问。你定义适用于具有特定 SELinux 标签的主体的安全策略。当具有 SELinux 标签的进程尝试访问文件时,SELinux 服务器会检查该进程的安全策略是否允许该访问并做出授权决定。
在 Kubernetes 中,你可以在清单的 `securityContext` 字段中设置 SELinux 标签。指定的标签将分配给这些进程。如果你已配置影响这些标签的安全策略,则宿主操作系统内核会强制执行这些策略。
要了解如何在 Kubernetes 中使用 SELinux,请参阅为容器分配 SELinux 标签。
AppArmor 和 SELinux 之间的区别
你的 Linux 节点上的操作系统通常包含 AppArmor 或 SELinux 之一。这两种机制提供类似类型的保护,但存在以下差异:
- 配置:AppArmor 使用配置文件来定义对资源的访问。SELinux 使用适用于特定标签的策略。
- 策略应用:在 AppArmor 中,你使用文件路径定义资源。SELinux 使用资源的索引节点 (inode) 来标识资源。
功能摘要
下表描述了每个安全控制的用例和范围。你可以将所有这些控制结合使用以构建更强大的系统。
安全功能 | 描述 | 如何使用 | 示例 |
---|---|---|---|
seccomp | 限制用户空间中的单个内核调用。降低利用受限系统调用的漏洞危及系统的可能性。 | 在 Pod 或容器规约中指定已加载的 seccomp 配置文件,以将其约束应用于 Pod 中的进程。 | 拒绝 `unshare` 系统调用,该系统调用曾用于 CVE-2022-0185。 |
AppArmor | 限制程序对特定资源的访问。减少程序的攻击面。改进审计日志记录。 | 在容器规约中指定已加载的 AppArmor 配置文件。 | 限制只读程序写入系统中任何文件路径。 |
SELinux | 使用标签和安全策略限制对文件、应用程序、端口和进程等资源的访问。 | 为特定标签指定访问限制。用这些标签标记进程以强制执行与标签相关的访问限制。 | 限制容器访问其自身文件系统之外的文件。 |
注意
AppArmor 和 SELinux 等机制可以提供超出容器范围的保护。例如,你可以使用 SELinux 来帮助缓解 CVE-2019-5736。管理自定义配置的注意事项
seccomp、AppArmor 和 SELinux 通常具有提供基本保护的默认配置。你还可以创建满足工作负载要求的自定义配置文件和策略。大规模管理和分发这些自定义配置可能具有挑战性,尤其是当你同时使用所有这三个功能时。为了帮助你大规模管理这些配置,请使用 Kubernetes 安全配置文件操作符 等工具。
内核级安全功能和特权容器
Kubernetes 允许你指定一些受信任的容器可以在*特权*模式下运行。Pod 中的任何容器都可以在特权模式下运行,以使用通常无法访问的操作系统管理功能。这适用于 Windows 和 Linux。
特权容器明确覆盖你可能在工作负载中使用的某些 Linux 内核约束,如下所示:
- seccomp:特权容器以 `Unconfined` seccomp 配置文件运行,覆盖你在清单中指定的任何 seccomp 配置文件。
- AppArmor:特权容器忽略任何应用的 AppArmor 配置文件。
- SELinux:特权容器以 `unconfined_t` 域运行。
特权容器
如果将容器的 `securityContext` 字段中的 `privileged: true` 字段设置为 true,则 Pod 中的任何容器都可以启用*特权模式*。特权容器会覆盖或撤销许多其他强化设置,例如应用的 seccomp 配置文件、AppArmor 配置文件或 SELinux 约束。特权容器被赋予所有 Linux 功能,包括它们不需要的功能。例如,特权容器中的 root 用户可能能够使用节点上的 `CAP_SYS_ADMIN` 和 `CAP_NET_ADMIN` 功能,从而绕过运行时 seccomp 配置和其他限制。
在大多数情况下,你应该避免使用特权容器,而应使用 `securityContext` 字段中的 `capabilities` 字段授予容器所需的特定能力。仅当你有无法通过 securityContext 授予的功能时才使用特权模式。这对于需要使用操作系统管理功能(例如操作网络堆栈或访问硬件设备)的容器非常有用。
在 Kubernetes 1.26 及更高版本中,你还可以通过在 Pod 规约的 security context 中设置 `windowsOptions.hostProcess` 标志,以类似特权模式运行 Windows 容器。有关详细信息和说明,请参阅创建 Windows HostProcess Pod。
建议和最佳实践
- 在配置内核级安全功能之前,你应该考虑实现网络级隔离。有关更多信息,请阅读安全清单。
- 除非必要,否则通过在 Pod 清单中设置特定的用户和组 ID 并指定 `runAsNonRoot: true`,将 Linux 工作负载作为非 root 用户运行。
此外,你可以通过在 Pod 清单中设置 `hostUsers: false` 来在用户命名空间中运行工作负载。这允许你作为用户命名空间中的 root 用户运行容器,但作为节点上宿主命名空间中的非 root 用户运行容器。这仍处于开发的早期阶段,可能不具备你所需的支持级别。有关说明,请参阅使用 Pod 的用户命名空间。