本页面介绍 Google Kubernetes Engine (GKE) 上的集群多租户。这包括由单个组织的不同用户共享的集群,以及由软件即服务 (SaaS) 应用的客户专用实例共享的集群。集群多租户是管理许多单租户集群的替代方案。
本页面还总结了可用于管理多租户集群的 Kubernetes 和 GKE 功能。
什么是多租户?
多租户集群由多个用户和/或工作负载共享,这些用户和/或工作负载被称为“租户”。多租户集群的运营方必须将租户彼此隔离,以最大限度地减少被盗用的租户或恶意租户可能对集群和其他租户造成的损害。此外,必须在租户之间公平地分配集群资源。
在规划多租户架构时,您应该考虑 Kubernetes 中的资源隔离层:集群、命名空间、节点、Pod 和容器。您还应该考虑在租户之间共享不同类型资源的安全隐患。例如,将来自不同租户的 Pod 调度到同一节点上可以减少集群中所需的机器数量。另一方面,您可能需要阻止某些工作负载共置。 例如,您可能不允许来自组织外部的不受信任的代码与处理敏感信息的容器在同一节点上运行。
虽然 Kubernetes 不能保证租户之间完全安全地隔离,但它为特定使用场景提供了足够的相关功能。 您可以将每个租户及其 Kubernetes 资源分隔到各自的命名空间中。 然后,您可以使用政策来强制执行租户隔离。政策通常按命名空间划分,可用于限制 API 访问、资源使用以及允许容器执行的操作。
多租户集群的租户共享以下资源:
与运营多个单租户集群相比,运营多租户集群有几个优点:
- 减少管理开销
- 减少资源碎片
- 新租户无需等待集群创建
多租户使用场景
本部分介绍如何为各种多租户使用用例配置集群。
企业多租户
在企业环境中,集群的租户是组织内的不同团队。通常,每个租户对应一个命名空间, 这是因为每个租户对应一个集群或每个租户对应一个Google Cloud 项目的多租户替代模型更难管理。同一个命名空间内的网络流量不受限制,必须明确允许命名空间之间的网络流量。可以使用 Kubernetes 网络政策强制实施这些政策。
集群的用户根据其权限分为三种不同的角色:
- 集群管理员
- 此角色适用于在整个集群中管理所有租户的管理员。集群管理员可以创建、读取、更新和删除任何政策对象。他们可以创建命名空间并将其分配给命名空间管理员。
- 命名空间管理员
- 此角色适用于特定单一租户的管理员。命名空间管理员可以管理其命名空间中的用户。
- 开发者
- 拥有此角色的成员可以创建、读取、更新和删除命名空间内的非政策对象,如 Pod、Job 和 Ingress。开发者只在他们有权访问的命名空间中拥有这些权限。
如需了解如何为企业组织设置多个多租户集群,请参阅企业多租户最佳做法。
SaaS 提供商多租户
SaaS 提供商集群的租户是应用的各个客户专用实例,以及 SaaS 的控制平面。要充分利用按命名空间划分的政策,应将各个应用实例安排到其各自的命名空间中,SaaS 控制平面的组件也应如此。最终用户无法直接与 Kubernetes 控制平面交互,而是使用 SaaS 的界面,由后者与 Kubernetes 控制平面进行交互。
例如,博客平台可以在多租户集群上运行。在这种情况下,租户是每个客户的博客实例和平台自己的控制平面。平台的控制平面和每个托管博客都将在不同的命名空间中运行。客户将通过平台的界面来创建和删除博客、更新博客软件版本,但无法了解集群的运作方式。
多租户政策实施
GKE 和 Kubernetes 提供了几项可用于管理多租户集群的功能。以下部分概述了这些功能。
访问权限控制
GKE 有两个访问权限控制系统:Identity and Access Management (Cloud IAM) 和基于角色的访问权限控制 (RBAC)。IAM 是 Google Cloud的访问权限控制系统,用于管理 Google Cloud资源的身份验证和授权。您可以使用 IAM 授予用户访问 GKE 和 Kubernetes 资源的权限。RBAC 内置于 Kubernetes 中,并为集群中的特定资源和操作授予细化的权限。
如需详细了解这些选项以及何时使用每个选项,请参阅访问权限控制概览。
如需了解如何使用这些访问权限控制系统,请参阅 RBAC 方法指南和 IAM 方法指南。
您可以将 IAM 和 RBAC 权限与命名空间结合使用,以限制用户与 Google Cloud 控制台上的集群资源的互动。如需了解详情,请参阅按命名空间启用访问权限和查看集群资源。网络政策
通过集群网络政策,您可以控制集群的 Pod 之间的通信。政策指定 Pod 可以与哪些命名空间、标签和 IP 地址范围进行通信。
如需查看在 GKE 上启用网络政策强制执行的说明,请参阅网络政策方法指南。
要学习如何编写网络政策,请参考网络政策教程。
资源配额
资源配额用于管理命名空间中对象使用的资源量。您可以按 CPU 和内存用量或对象数量来设置配额。通过资源配额,您可以确保租户不会使用超过其分配份额的集群资源。
如需了解详情,请参阅资源配额文档。
基于政策的 Pod 准入控制
如需阻止违反安全边界的 Pod 在集群中运行,请使用准入控制器。准入控制器可以根据您定义的政策检查 Pod 规范,并且可以阻止违反这些政策的 Pod 在集群中运行。
GKE 支持以下类型的准入控制:
- Policy Controller:声明预定义政策或自定义政策,并使用舰队在集群中大规模强制执行政策。Policy Controller 是开源 Gatekeeper Open Policy Agent 的实现,是 GKE Enterprise 的一项功能。
- PodSecurity 准入控制器:强制执行与各个集群或特定命名空间中的 Pod 安全标准对应的预定义政策。
Pod 反亲和性
您可以利用 Pod 反亲和性来防止不同租户的 Pod 被调度到同一节点上。反亲和性限制以 Pod 标签为基础。例如,下面的 Pod 规范描述了一个标签为 "team":
"billing" 的 Pod,以及一个阻止该 Pod 与没有该标签的 Pod 调度到一起的反亲和性规则。
apiVersion: v1
kind: Pod
metadata:
name: bar
labels:
team: "billing"
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- topologyKey: "kubernetes.io/hostname"
labelSelector:
matchExpressions:
- key: "team"
operator: NotIn
values: ["billing"]
这种做法的缺点是恶意用户可以通过将 team: billing 标签添加到任意 Pod 来规避规则。仅使用 Pod 反亲和性机制不足以在具有不受信任的租户的集群上安全地强制执行政策。
如需了解详情,请参阅 Pod 反亲和性文档。
使用污点和容忍机制来实现专用节点
节点污点是控制工作负载调度的另一种方法。您可以使用节点污点来将专用节点留给某些租户使用。例如,您可以将配备 GPU 的节点专门留给那些工作负载需要 GPU 的特定租户。对于 Autopilot 集群,仅支持工作负载分离支持节点容忍设置。根据需要,节点自动预配功能会自动添加节点污点。
如需将某个节点池专门留给某个租户,请将具有 effect: "NoSchedule" 的污点应用于该节点池。然后,只有具备相应容忍设置的 Pod 可以被调度到该节点池中的节点。
这种做法的缺点是恶意用户可以通过为其 Pod 添加相应容忍设置来访问专用节点池。仅使用节点污点和容忍机制不足以在具有不受信任的租户的集群上安全地强制执行政策。
如需了解详情,请参阅 Kubernetes 文档 中的污点和容忍。
GKE Sandbox
GKE Sandbox 通过将不受信任的工作负载与集群节点上的主机内核隔离,为多租户集群提供了一道额外的安全保障。GKE Sandbox 使用 gVisor(一种开源容器 沙盒技术)为每个 Pod 提供单独的用户空间内核。
GKE Sandbox 对于 SaaS 提供商或运行不受信任的代码的组织尤其有用,因为它有助于防止恶意租户逃离其容器或影响主机内核。如需了解详情,请参阅GKE Sandbox。
多租户内存管理
Linux 内核可确保在分配时,分配给新进程的内存页会进行零填充(清理)。此过程也适用于容器创建,并可防止新容器读取先前容器留在内存中的残留数据。不过,这是由主机操作系统管理的逻辑边界。从容器中逃脱的攻击者或对节点虚拟机具有 root 权限的用户可以绕过这些保护措施来访问其他容器的原始内存内容。
如需强化此边界,请使用 GKE Sandbox 来防范容器逃脱,使用准入政策来限制 Pod 访问主机,并限制对节点的直接访问。
标准 GPU 和 TPU 资源在 Pod 分配之间 不会 自动清理其高带宽内存 (HBM)、静态 RAM (SRAM) 或控制寄存器。先前工作负载的残留数据可能会保留在加速器的内存中。如果虚拟机在工作负载之间未重启,则该配置仅适用于受信任的多租户,其中在同一加速器上调度的所有工作负载共享相同的安全敏感度。
对于没有相互信任的工作负载,需要重启虚拟机才能清除每个已调度工作负载之间的加速器内存。删除虚拟机也会导致在将加速器重新连接到新虚拟机之前清除内存。如需详细了解加速器配置和共享,请参阅 GKE TPU 和 GPU 文档。
共享 GPU 和 TPU 等加速器
在 Pod 之间共享 GPU 或 TPU 加速器会带来额外的风险。GPU 和 TPU 可能会或可能不会提供针对共享访问的保护。这些保护措施可能取决于硬件版本、驱动程序版本和运行时系统配置。下表重点介绍了不同的方法以及与每种方法相关的风险。
相互信任的 Pod 可以决定接受各种风险。 该表指出了每个隔离级别的风险级别。
| 架构 | 主要攻击面 | 安全摘要 |
|---|---|---|
| 同一节点上的 Pod 直接共享加速器,包括 GPU 分时和 NVIDIA MPS。 | GPU 内存和全局状态 | Pod 彼此容易受到攻击,并且必须相互信任。 |
| 同一节点上的 Pod 直接共享加速器并使用 GKE Sandbox,包括 GPU 分时和 NVIDIA MPS。 | GPU 内存和主机驱动程序 | GKE Sandbox 将工作负载内核与主机内核隔离。虽然 gVisor 减少了暴露给应用的 GPU 攻击面,但它不会在 GPU 环境内提供分离,该环境仍处于共享状态。如需了解详情,请参阅:GPU 支持 - 安全。 |
| 同一节点上的 Pod 具有专用加速器,包括 NVIDIA MIG。 | 主机内核(通过驱动程序) | Pod 仍可能因加速器或驱动程序漏洞而受到攻击,这些漏洞可能会升级到主机内核。 |
| 同一节点上的 Pod 具有专用加速器(包括 NVIDIA MIG)并使用 GKE Sandbox。 | 主机驱动程序接口 (nvproxy) | GKE Sandbox 会隔离内核,但主机 GPU 驱动程序接口 (nvproxy) 仍然是共享的攻击面。驱动程序漏洞可能会导致主机内核逃脱。MIG 实例之间也可能存在侧信道泄漏。 |
| 每个 Pod 都在具有专用加速器的专用节点上运行。 | 虚拟机边界 / 虚拟机监控程序 | 建议用于不受信任的工作负载。任何攻击都仅限于一个虚拟机。 |
后续步骤
- 了解企业级多租户最佳实践。
- 详细了解舰队管理。
- 了解如何按命名空间启用访问权限和查看集群资源。
- 了解如何使用网络政策控制 Pod 与服务之间的通信。
- 了解如何设置多租户日志记录。
- 了解如何配置 GKE Sandbox。