ReadyOn 是一家 AWS 合作伙伴,为财富 100 强企业提供智能劳动力编排平台,其在 Amazon Elastic Kubernetes(容器编排平台) Service (Amazon EKS) 上运行多租户平台,处理企业 IT 中一些最敏感的数据。Kubernetes 是该平台的核心,同时也是最复杂的安全防护面之一。默认的 Kubernetes 部署并非开箱即安全:上游 Kubernetes 历来允许匿名请求到达 API(应用程序编程接口) 服务器,仅由 RBAC 拒绝;Pod 默认以 root 身份运行;网络策略在有人编写之前并不存在。
对于单租户集群,加固是一项已有充分文档记录的挑战。但当加入多租户后,威胁模型发生了根本性变化。关注点从未授权用户能否访问集群,转变为租户 A 能否访问租户 B 的数据。大多数多租户 Kubernetes 平台依赖单一隔离机制:命名空间。Kubernetes 的设计者从未打算将命名空间作为安全边界。
ReadyOn 的 Harmony 平台为财富 100 强企业提供劳动力智能支持。它处理薪资数据、组织层级结构以及覆盖数十万名员工的运营分析。跨租户访问将触发多个司法管辖区的监管义务,并损害企业客户对其技术合作伙伴的信任。这样的风险要求比单一防护墙更好的方案。
本文介绍 ReadyOn 在 Amazon EKS 上四层独立隔离的架构。其四重墙模型结合了 Kubernetes 命名空间、Karpenter 管理的专用节点池、Amazon Virtual Private Cloud (Amazon VPC) 安全组以及每租户独立的 Amazon Aurora 数据库。它们共同构建了复合防御:要跨越租户边界,未授权用户需要同时突破 Kubernetes API、节点调度器、AWS 软件定义网络和数据层。
ReadyOn 的架构在租户之间设置了四道独立屏障,每道屏障运行在堆栈的不同层级,需要根本不同的技术才能跨越:
第一道墙 – 命名空间隔离:每个租户在专用的 Kubernetes 命名空间中运行,具有严格的 RBAC 策略、资源配额和准入控制。Argo CD ApplicationSet 生成这些资源,因此每个租户在构建时即获得相同的安全态势。
第二道墙 – 计算隔离:Karpenter 使用双重污点策略为每个租户配置专用的自动扩缩节点池。每个节点同时携带租户标识污点和负载类型污点。Pod 必须同时容忍两者才能被调度。此配置可防止跨租户 Pod 放置。
第三道墙 – 网络隔离:每租户的 Amazon VPC 安全组将数据库访问限制为仅该租户的节点池。Kubernetes 网络策略在命名空间之间强制执行默认拒绝。集群 API 服务器为私有,仅可通过 VPN 配合 OpenID Connect (OIDC) 和 MFA 访问。
第四道墙 – 数据隔离:每个租户拥有专用的 Amazon Aurora 数据库集群和 AWS Secrets Manager 中租户范围的密钥。工作负载通过 IAM Roles for Service Accounts (IRSA) 使用短期凭证,每个租户拥有各自的每租户可观测性实例。不存在带行级过滤的共享数据库。
此模型的力量在于分层。未授权用户需要同时跨越所有四道墙才能到达租户边界。这些是分层、重叠的控制措施:未授权用户必须组合突破它们,而非逐一攻破。由于某些层共享控制平面(准入控制、GitOps、EKS 控制平面和 IAM),ReadyOn 将其视为纵深防御,而非完全独立的概率。
命名空间是 Kubernetes 中最可见的租户边界。虽然 ReadyOn 对命名空间隔离作为安全机制的局限性持现实态度,但命名空间仍然构成了其他隔离层所构建的逻辑基础。
每个租户命名空间都通过 Argo CD ApplicationSet 进行配置。当 ReadyOn 接入新租户时,他们只需在 Git 中的配置清单中添加一条记录。自动化流程会生成所有必需的资源:命名空间、网络策略、RBAC 绑定、资源配额和密钥配置。不存在策略较弱的“遗留”租户。每个租户在构建时都会获得完全相同的安全态势。
每个命名空间都带有角色绑定,将 API 访问限制为仅能访问该租户的资源。任何租户主体都无法列出、获取或修改其他命名空间中的资源。准入控制框架会根据一套策略集验证所有资源,该策略集强制执行安全上下文、阻止特权配置,并防止创建租户不应拥有的资源类型(DaemonSet、ClusterRole、准入 Webhook)。
生成的 RoleBinding 将租户组的作用域限定为其自身的命名空间。Argo CD 根据 Git 中的租户条目渲染此绑定,因此每个命名空间都会获得完全相同的绑定:
apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: tenant-a-developers namespace: tenant-a subjects: - kind: Group name: tenant-a-developers apiGroup: rbac.authorization.k8s.io roleRef: kind: Role name: tenant-namespace-editor apiGroup: rbac.authorization.k8s.io
GitOps 控制器持续将集群实时状态与 Git 中声明的状态进行协调。任何手动修改(无论是由于配置错误,还是获得有限 API 访问权限的未授权用户所为)都会在几秒钟内自动回滚。人工操作员永远不会对生产集群运行 kubectl apply。
命名空间隔离在 Kubernetes API 层运行。第二道墙则下沉到计算层:即租户代码实际执行的物理机器。在 Harmony 中,租户不共享计算节点。
ReadyOn 的 Karpenter provisioner 创建节点时会添加两个污点:一个租户标识污点(例如 tenant=acme-corp)和一个工作负载类型污点(例如 workload=frontend)。Pod 必须容忍这两个污点才能被调度。租户 A 的前端节点与租户 A 的批处理节点是不同的,并且两者都与租户 B 的基础设施完全隔离。
即使使用伪造的容忍度创建了 Pod,准入控制器也会验证容忍度声明是否与命名空间的租户身份匹配。调度器无法被引导进行跨租户放置。
所有应用程序节点强制执行 IMDSv2 并降低跳数限制,防止 Pod 访问实例元数据端点。附加到每个节点的 IAM 角色被限定为单个租户的资源,从而限制了容器逃逸的影响范围。平台节点运行在托管节点组上,并带有租户工作负载无法容忍的独立污点。
墙 1 和墙 2 在 Kubernetes 抽象层内运作。墙 3 完全下沉到 Kubernetes 之下,在 Amazon VPC 和安全组级别实施隔离:这是 Kubernetes 控制平面不管理的基础设施,具有有限访问权限的 Pod 无法操纵。
每个租户的 Amazon Aurora 集群由安全组保护,该安全组仅允许来自附加到该租户应用程序节点的安全组的入站连接。租户 A 的节点无法与租户 B 的数据库建立 TCP 连接。这是由 AWS 软件定义网络强制执行的 Amazon VPC 安全组规则。要跨越它,需要克服网络层本身。
VPC 分为四层:公共外围层(仅负载均衡器)、应用层(私有子网中的 EKS 工作节点)、数据库层(无互联网访问的 Aurora 集群)和控制平面层(私有 EKS API 端点,仅限 VPN 访问,使用 OIDC 和 MFA)。
Kubernetes 网络策略对命名空间间流量强制执行默认拒绝。租户 Pod 仅与其自身命名空间中的 Pod 以及明确允许的平台服务通信。所有其他流量被拒绝并记录日志。Amazon VPC Flow Logs 捕获所有网络流量以进行异常检测。
最后一道墙针对的是终极目标:数据本身。第 1 到第 3 道墙阻止未授权用户访问其他租户的数据。第 4 道墙即使在其他所有层都失效的情况下,仍能维持数据隔离。
共享数据库将隔离的全部负担都放在应用层查询逻辑上,只要漏掉一个 WHERE tenant_id = ? 子句,就可能导致意外泄露。ReadyOn 选择为每个租户使用专用的 Amazon Aurora 集群。这样就不存在会忘记添加的行级过滤器。租户 A 的代码无法构建到租户 B 数据库的连接:它缺少端点、凭证和网络路径。
专用 Aurora 集群还支持为每个租户使用唯一的 AWS Key Management Service (AWS KMS) 加密密钥。每个租户的静态数据都使用不同的 KMS 密钥加密,这意味着即使原始存储被意外访问,一个租户的密钥也无法解密另一个租户的数据。在共享数据库中实现等效的按租户密钥隔离非常复杂,因为每个租户的行共享同一存储,隔离依赖于正确实现的行级安全。
每个工作负载都通过 AWS Security Token Service (AWS STS) 颁发的短期凭证向 AWS API 进行身份验证,这些凭证通过 EKS 集群与 IAM 之间的 OIDC 联合获取。每个租户的工作负载承担一个唯一的 IAM 角色,该角色仅限访问该租户的资源。凭证在几分钟内过期。应用工作负载不持有长期访问密钥。
每个租户的指标、日志和追踪通过 OpenTelemetry 路由到专用的可观测性后端。即使是错误率的激增(可能泄露敏感运营情报)对其他租户也是不可见的。
ReadyOn 将其防御措施映射到自己的 10 阶段多租户威胁模型,每个阶段都映射到相关的 MITRE ATT&CK 技术。关键转折点是其横向移动阶段(第 8 阶段),此时租户 A Pod 中具有有限访问权限的未授权用户试图跨越边界访问租户 B 的资源。图 1 展示了这一转折点,显示租户 A Pod 内的未授权进程试图访问租户 B,并在四道墙的每一道处被阻止。

图 1:第 8 阶段横向移动,其中被攻陷的租户 A 工作负载可能尝试的六条跨租户路径,每一条都在阻止它的编号墙处终止
图 1 描绘了左侧的租户 A Pod 和右侧的租户 B 资源。它们之间有四个标记的垂直屏障,编号为 1 到 4,按顺序代表四道墙:(1) 命名空间隔离,(2) 计算隔离,(3) 网络隔离,(4) 数据隔离。未授权用户可能尝试的六条跨租户路径中的每一条都画成从租户 A 出发的箭头,并在阻止它的编号墙处终止:创建进入另一个命名空间的路由止于墙 1。在其他租户的节点上调度 Pod 止于墙 2。打开数据库连接和发送跨命名空间流量止于墙 3。而检索密钥和查询监控数据止于墙 4。没有箭头到达租户 B。
在第 8 阶段,四道墙同时生效。ReadyOn 系统性地验证每一条跨租户路径均被阻断:
在其他租户的节点上调度工作负载被双重污点策略加上准入控制器验证所阻断。
访问其他租户的数据库被 Amazon VPC 层的每租户安全组所阻断。
读取其他租户的密钥被 IRSA 作用域加上租户作用域密钥路径所阻断。
查询其他租户的监控数据被每租户专用可观测性实例所阻断。
与其他命名空间中的 Pod 通信被默认拒绝网络策略所阻断。
创建将流量导向其他租户命名空间的路由被策略所阻断:租户无法创建或修改入口资源,平台入口层在每次请求时重新验证租户上下文。
ReadyOn 通过定期对抗性演练验证这些边界,模拟具有完全访问权限的租户 Pod 并尝试每一条穿越路径。迄今为止的这些演练中,没有任何测试产生成功的跨租户路径。
Harmony 中的每个容器都以 Pod Security Standards 的“restricted”级别运行:
securityContext: runAsNonRoot: true allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: drop: [ALL] seccompProfile: type: RuntimeDefault
容器无法安装工具、修改二进制文件或使用容器逃逸技术所依赖的内核接口。结合 IMDSv2 限制和 IRSA,即使发生容器逃逸也无法获得有用的节点级凭证。
对集群状态的每一次变更都始于一个需要审查和自动化策略检查的拉取请求。Git 仓库是唯一事实来源。集群是 Git 的反映。Git 中不存储任何密钥:External Secrets Operator 在部署时解析对 AWS Secrets Manager 的引用。即使未经授权访问 Git 仓库,也无法获得任何可用的凭证。
ReadyOn 的四墙架构带来了可衡量的安全与运营优势:
防御 10 个威胁模型阶段,每个阶段映射到 MITRE ATT&CK 技术,所有六条跨租户路径在横向移动阶段均被阻断。
应用工作负载中无长期凭证:所有工作负载身份验证均使用短期的 OIDC 联合令牌。
通过 GitOps 模板化在所有租户间强制执行一致的安全态势,无遗留例外。
自愈漂移纠正可在数秒内还原未经授权的集群变更。
多区域主动-被动架构,通过 Amazon Route 53 实现自动化故障转移。
多租户 Kubernetes 安全并非单一问题、单一解决方案。命名空间隔离是一个强大的逻辑边界,Kubernetes 文档建议将其与额外的防护层配合使用,而不是仅依赖它作为安全边界。ReadyOn 构建了这些额外的防护层。
ReadyOn 的 Four Walls 模型表明,通过在独立的抽象层上叠加原生服务,可以在 AWS 上实现纵深防御:API 层的 Kubernetes RBAC、调度器层的 Karpenter、网络层的 Amazon VPC 安全组,以及数据访问层的 IAM。每一道墙都独立提高了跨租户尝试的成本,它们共同提供了纵深防御:未授权用户必须组合突破这些墙,而非逐一攻破。
对于在 Amazon EKS 上运行敏感多租户工作负载的组织,Four Walls 模型提供了一种零信任租户隔离的参考架构,同时不牺牲多租户带来的经济效益和运营速度。
转载声明:本文为转载整理,原文版权归原作者及原站点所有。
原创地址:https://aws.amazon.com/blogs/architecture/readyons-four-walls-of-tenant-isolation-on-amazon-eks/
原文作者:Roshan Daneshvaran;如有侵权,请联系管理员删除。