本页面介绍 GKE Sandbox 在 Pod 中的容器执行未知或不可信代码时如何保护节点上的主机内核。例如,软件即服务 (SaaS) 提供商这样的多租户集群常常会执行其用户提交的未知代码。 GKE Sandbox 也是运行高价值容器的实用深度防御措施。
GKE Sandbox 使用开源项目 gVisor。本主题广泛讨论了 gVisor,但您可以通过阅读官方 gVisor 文档来了解详情。
如需了解如何启用和使用 GKE Sandbox,请参阅配置 GKE Sandbox。
概览
GKE Sandbox 提供了一道额外的安全保障,可防止不可信代码影响集群节点上的主机内核。在讨论 GKE Sandbox 的工作原理之前,了解它有助于缓解的潜在风险的特性非常有用。
containerd
之类的容器运行时会在容器的进程与节点上运行的内核之间提供一定程度的隔离。不过,容器运行时通常以特权用户身份在节点上运行,有权访问针对主机内核的大多数系统调用。
潜在威胁
多租户集群以及容器运行不可信工作负载的集群比其他集群更容易出现安全漏洞。相关的例子包括 SaaS 提供商、网站托管服务提供商或允许其用户上传和运行代码的其他组织。容器运行时或主机内核中的缺陷可能允许容器内运行的进程“逃离”容器并影响节点的内核,从而可能导致节点停机。
恶意租户也可能带来潜在风险,该租户通过利用此类缺陷,可以访问并窃取内存或磁盘中其他租户的数据。
最后,不可信工作负载可能会访问其他 Google Cloud 服务或集群元数据。
GKE Sandbox 如何缓解这些威胁
gVisor 是 Linux 内核 API 的用户空间重新实现,不需要提升权限。通过与 containerd
之类的容器运行时搭配使用,该用户空间内核可重新实现大多数系统调用并代表主机内核为它们提供服务。对主机内核的直接访问会受到限制。请参阅 gVisor 架构指南,详细了解其工作原理。从容器的角度来看,gVisor 几乎是透明的,并且不需要对容器化应用进行任何更改。
当您在 Autopilot 集群的 Pod 中请求 GKE Sandbox 时,GKE 会在沙盒中运行该 Pod。在 GKE Standard 中,如果您在节点上启用 GKE Sandbox,则在这些节点上运行的所有 Pod 都会在沙盒中运行。
每个沙盒都会使用自己的用户空间内核。考虑到这一点,您可以根据所需的隔离级别以及应用的特征,决定如何将容器分组到 Pod 中。
GKE Sandbox 特别适合以下类型的应用。请参阅限制,了解帮助您确定要将哪些应用放入沙盒中的详情。
- 使用 Rust、Java、Python、PHP、Node.js 或 Golang 等运行时的不可信应用或第三方应用
- Web 服务器前端、缓存或代理
- 使用 CPU 处理外部媒体或数据的应用
- 使用 CPU 的机器学习工作负载
- CPU 密集型或内存密集型应用
- GPU 密集型工作负载
其他安全建议
此外,我们建议您在使用 GKE Sandbox 时遵循以下建议:
为沙盒中运行的所有容器指定资源限制。这样可以防范有缺陷的应用或恶意应用所带来的风险。此类应用会消耗节点的资源,并对节点上运行的其他应用或系统进程产生负面影响。
如果您使用的是适用于 GKE 的工作负载身份联合,请使用网络政策阻止集群元数据访问,从而阻止访问
169.254.169.254
。这样可以防范恶意应用访问项目 ID、节点名称和可用区等可能涉及用户隐私数据信息所带来的风险。GKE Autopilot 集群中会始终启用适用于 GKE 的工作负载身份联合。
限制
GKE Sandbox 适合许多应用,但并不适合所有应用。本部分详细介绍了 GKE Sandbox 的当前限制。
GKE Sandbox 中的 GPU
在 GKE 1.29.2-gke.1108000 版及更高版本中,GKE Sandbox 支持使用 NVIDIA GPU。
GKE Sandbox 无法解决所有 NVIDIA 驱动程序漏洞,但仍然可以防范 Linux 内核漏洞。如需详细了解 gVisor 项目如何保护 GPU 工作负载,请参阅 GPU 支持指南
以下限制适用于 GKE Sandbox 中的 GPU 工作负载:
- 仅支持给定 GKE 版本上的
latest
NVIDIA 驱动程序版本。Autopilot 集群会自动安装支持 GKE Sandbox 的 NVIDIA 驱动程序版本。 - 仅支持 CUDA 工作负载。
- 支持以下 GPU 型号:nvidia-tesla-t4、nvidia-tesla-a100、nvidia-a100-80gb、nvidia-l4 和 nvidia-h100-80gb。
您可以将 GKE Sandbox 与 GPU 工作负载搭配使用,无需额外付费。
节点池配置
适用于 Standard 集群
- 您无法在 Windows Server 节点池上使用 GKE Sandbox。
- 您无法在默认节点池上启用 GKE Sandbox 来使用 GKE Sandbox 将默认节点池中运行的系统服务与不受信任的工作负载分开。
- 使用 GKE Sandbox 时,您的集群必须至少具有两个节点池。您必须始终至少有一个节点池停用 GKE Sandbox。此节点池必须至少包含一个节点,即使您的所有工作负载都已放入沙盒也是如此。
- 低于 1.24.2-gke.300 的 GKE 版本不支持 e2-micro、e2-small 和 e2-medium 机器类型。GKE 1.24.2-gke.300 及更高版本支持这些机器类型。
- 节点必须使用具有 containerd (
cos_containerd
) 的 Container-Optimized OS 节点映像。
集群元数据访问权限
适用于 Autopilot 和 Standard 集群
- 系统会阻止运行沙盒化 Pod 的节点访问节点上操作系统级别的集群元数据。
- 在 GKE Standard 中,您可以在启用了 GKE Sandbox 的节点上运行常规 Pod。不过,默认情况下,这些常规 Pod 无法访问 Google Cloud 服务或集群元数据。
- 请使用适用于 GKE 的工作负载身份联合向 Pod 授予访问 Google Cloud 服务的权限。
SMT 可能已停用
适用于 Autopilot 和 Standard 集群
并发多线程 (SMT) 设置可缓解利用共享核心状态的边信道漏洞问题,例如微架构数据抽样 (MDS) 漏洞。
在 GKE 1.25.5-gke.2500 版或更高版本以及 1.26.0-gke.2500 版或更高版本中,gVisor 配置为使用 Linux 核心调度来缓解边信道攻击。SMT 设置保留为默认值。核心调度仅用于使用 gVisor 运行的工作负载。
从 GKE 1.24.2-gke.300 版开始,系统会根据机器受 MDS 漏洞影响的程度按机器类型来配置 SMT,如下所示:
在
Scale-Out
计算类上运行的 Autopilot Pod:已停用 SMT。采用 Intel 处理器的机器类型:默认停用 SMT。
未采用 Intel 处理器的机器类型:默认启用 SMT。
每个核心只有一个线程的机器类型:不支持 SMT。请求的所有 vCPU 都可见。
对于 1.24.2-gke.300 之前的版本,所有机器类型都会停用 SMT。
启用 SMT
适用于 Standard 集群
在 GKE Standard 集群中,如果所选机器类型上停用了 SMT,您可以将其启用。无论您是启用 SMT 还是停用 SMT,您都需要为每个 vCPU 支付费用。如需了解价格信息,请参阅 Compute Engine 价格。
GKE 1.24.2-gke.300 及更高版本
创建 GKE Sandbox 节点池时,请设置 --threads-per-core
标志:
gcloud container node-pools create smt-enabled \
--cluster=CLUSTER_NAME \
--machine-type=MACHINE_TYPE \
--threads-per-core=2 \
--sandbox type=gvisor
CLUSTER_NAME
:现有集群的名称。MACHINE_TYPE
:机器类型。
如需详细了解 --threads-per-core
,请参阅设置每个核心的线程数。
1.24.2-gke.300 之前的 GKE 版本
在集群中使用节点标签
cloud.google.com/gke-smt-disabled=false
创建一个新的节点池:gcloud container node-pools create smt-enabled \ --cluster=CLUSTER_NAME \ --machine-type=MACHINE_TYPE \ --node-labels=cloud.google.com/gke-smt-disabled=false \ --image-type=cos_containerd \ --sandbox type=gvisor
将 DaemonSet 部署到该节点池。DaemonSet 只会在具有
cloud.google.com/gke-smt-disabled=false
标签的节点上运行。kubectl create -f \ https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-node-tools/master/disable-smt/gke/enable-smt.yaml
确保 DaemonSet Pod 处于运行状态。
kubectl get pods --selector=name=enable-smt -n kube-system
输出类似于以下内容:
NAME READY STATUS RESTARTS AGE enable-smt-2xnnc 1/1 Running 0 6m
检查 Pod 的日志中是否出现
SMT has been enabled
。kubectl logs enable-smt-2xnnc enable-smt -n kube-system
功能
适用于 Standard 集群
默认情况下,系统会阻止容器打开原始套接字,以降低恶意攻击的可能性。某些与网络相关的工具(例如 ping
和 tcpdump
)会在其核心功能中创建原始套接字。如需启用原始套接字,您必须向容器的安全上下文明确添加 NET_RAW
功能:
spec:
containers:
- name: my-container
securityContext:
capabilities:
add: ["NET_RAW"]
如果您使用 GKE Autopilot,由于此功能会影响安全性,Google Cloud 会阻止您向容器添加 NET_RAW
权限。
外部依赖项
适用于 Autopilot 和 Standard 集群
在沙盒内运行的不可信代码可以访问数据库服务器、API、其他容器和 CSI 驱动程序等外部服务。 这些服务在沙盒边界之外运行,需要单独进行保护。攻击者可能尝试利用这些服务中的漏洞来攻击沙盒。您必须考虑沙盒内运行的代码可以访问这些服务时所存在的风险和影响,并采取必要的措施来保护这些服务。
这包括 ext4 和 CSI 驱动程序等容器卷的文件系统实现。CSI 驱动程序在沙盒隔离机制外部运行,可能拥有访问主机和服务的特权。这些驱动程序中的漏洞会影响主机内核,并危及整个节点。我们建议您在具有最少必需权限的容器内运行 CSI 驱动程序,以降低因漏洞而引发的数据泄露风险。GKE Sandbox 支持使用 Compute Engine Persistent Disk CSI 驱动程序。
不兼容的功能
您不能将 GKE Sandbox 与以下 Kubernetes 功能搭配使用:
- 容器级的内存用量指标。不过,Pod 内存用量是受支持的。
- Hostpath 存储空间
- CPU 和内存限制仅应用于 Guaranteed Pod 和 Burstable Pod,并且仅当为 Pod 中运行的所有容器指定了 CPU 和内存限制时才会应用。
- 以特权模式运行的容器
- VolumeDevices
- Portforward
- Linux 内核安全模块,例如 Seccomp、Apparmor、Selinux、Sysctl、
NoNewPrivileges
、双向 MountPropagation 或 ProcMount。 - Traffic Director
使用 Istio CNI 的 ASM
GKE 1.22 版及更高版本支持 FSGroup。
Autopilot 集群中的 GKE Sandbox Pod 不支持 Cloud Service Mesh。
工作负载特性
适用于 Autopilot 和 Standard 集群
为访问节点内核的操作施加额外的间接处理会导致性能受到影响。GKE Sandbox 为非常需要隔离的大型多租户集群提供了最切实的好处。使用 GKE Sandbox 测试工作负载时,请牢记以下准则。
系统调用
适用于 Autopilot 和 Standard 集群
生成大量低开销系统调用的工作负载(例如大量的小型 I/O 操作)在沙盒中运行时可能需要更多的系统资源,因此您可能需要使用功能更强大的节点或向集群添加额外的节点。
直接访问硬件或虚拟化
适用于 Autopilot 和 Standard 集群
如果您的工作负载需要使用以下任一功能,则 GKE Sandbox 可能不太合适,因为它会阻止直接访问节点上的主机内核:
- 直接访问节点的硬件
- 内核级虚拟化功能
- 特权容器