博客

在Docker中实现真正的多租户隔离

Docker的共享内核模型为多租户环境带来了风险。本指南提供了具体步骤,通过用户命名空间、seccomp、AppArmor、沙盒工具和编排最佳实践来加强隔离。

摘要

Docker容器共享主机内核,这对于租户之间可能互不信任的多租户环境来说可能是一个安全问题。本文解释了默认Docker设置中的隔离缺口,并提供了使用Linux命名空间、cgroups、用户命名空间、seccomp、AppArmor和硬件虚拟化来加强隔离的具体步骤。您将学习如何配置每租户Docker守护进程,使用gVisor或Firecracker等沙盒工具实现更强的隔离,并使用Kubernetes进行多租户编排。我们还将讨论选择合适的基础设施提供商,该提供商提供基于KVM的虚拟化,以实现额外的隔离层。最后,您将获得一个使用Docker运行安全多租户工作负载的蓝图。

当在单个Docker主机上托管多个租户时,基于Linux命名空间和cgroups的默认容器隔离通常是不够的。一个租户的容器逃逸可能危及整个主机和所有其他容器。这个问题在共享托管、SaaS平台或任何不可信代码与您自己的代码一起运行的场景中尤为严重。好消息是:您可以叠加多种隔离技术来构建一个加固的多租户环境。本指南将介绍六个实用步骤,从用户命名空间等低挂果实到沙盒运行时和基础设施选择等高级措施。

理解Docker的默认隔离

Docker使用Linux命名空间来隔离进程、网络、文件系统和其他资源。Cgroups限制CPU、内存和I/O。但它们共享一个内核——内核中的漏洞可能影响所有容器。对于真正的多租户,尤其是涉及不可信租户时,您需要纵深防御。如设计多租户Docker架构:选择合适的隔离级别中所述,隔离级别从弱(仅命名空间)到强(硬件虚拟化)。让我们从最弱的开始构建。

步骤1:启用用户命名空间

默认情况下,容器内的root映射到主机上的root。容器逃逸会获得完全的主机访问权限。用户命名空间将容器root重新映射到外部的非root用户。使用dockerd --userns-remap=default全局启用,或使用--userns=host按容器启用。这个简单的步骤消除了许多特权提升攻击。测试您的应用程序:一些需要主机级权限(例如挂载文件系统)的应用程序可能会中断。对于Drupal或WordPress站点,通常是安全的。

步骤2:应用Seccomp和AppArmor配置文件

Seccomp限制容器可以进行的系统调用。Docker附带了一个默认的seccomp配置文件,阻止了像mountreboot这样的危险系统调用。对于多租户,进一步收紧——阻止逃逸工具使用的不常见系统调用。类似地,AppArmor可以限制容器进程。创建一个自定义AppArmor配置文件,拒绝写入内核接口并限制文件路径。两者都通过--security-opt标志设置。结合使用以实现分层防御。

步骤3:使用每租户Docker守护进程

为所有租户运行单个Docker守护进程是有风险的——任何容器逃逸都可能访问守护进程套接字。使用Docker-in-Docker(DinD)或远程守护进程端点来隔离每个租户的守护进程。例如,使用--privileged在容器内启动Docker守护进程(但这会削弱隔离)。更好的方法:在单独的VM上运行单独的守护进程,或使用Docker的实验性--group功能结合用户命名空间。对于编排,基于Kubernetes命名空间的隔离更实用,如防御容器逃逸:多租户托管的Docker隔离实用指南中所述。

步骤4:考虑沙盒运行时

当Linux内核本身不可信时,使用添加轻量级VM层的沙盒运行时。gVisor (runsc) 拦截系统调用并实现自己的内核,而Firecracker使用具有硬件虚拟化的微VM。两者都通过containerd运行时与Docker集成。例如,将"runtimes": {"runsc": {}}添加到Docker守护进程配置,并使用--runtime=runsc运行容器。性能开销为5-15%,但隔离性大大增强。非常适合高安全性多租户设置。

步骤5:使用Kubernetes和安全策略进行编排

Kubernetes通过命名空间、Pod安全标准和网络策略提供原生多租户支持。为每个租户定义命名空间并设置资源配额,并强制使用受限的Pod安全上下文(放弃所有功能,只读根文件系统)。使用OPA/Gatekeeper等准入控制器可以阻止错误配置。如果您管理许多租户,Kubernetes可以自动执行隔离强制。对于生产规模的编排,请参考超越Docker Compose:编排生产就绪的容器化应用程序

步骤6:选择合适的主机提供商

您的基础设施提供商的虚拟机监视器很重要。共享托管(OpenVZ)上的Docker提供弱隔离——一个租户可以看到其他进程。优先选择使用KVM或VMware的提供商,它们提供硬件级隔离。像DigitalOcean、Kamatera或AWS这样的提供商提供具有专用资源的基于KVM的VPS。对于裸机,确保BIOS级虚拟化已启用,以便嵌套容器。在虚拟机监视器层隔离租户的提供商补充了您的容器隔离。如掌握Docker隔离以实现安全和高效的Web托管中所述,主机操作系统也应通过最小化攻击面进行加固。

注意事项和权衡

每个额外的层都会增加复杂性和性能成本。用户命名空间可能会破坏主机挂载卷。Seccomp配置文件需要针对每个应用程序进行调整。像gVisor这样的沙盒运行时不支持所有系统调用——您的应用程序可能无法运行。每租户Docker守护进程增加内存开销。选择与您的威胁模型匹配的隔离级别:对于可信租户,默认命名空间可能就足够了;对于公共SaaS,投资于运行时沙盒和Kubernetes策略。在生产之前彻底测试。

结论

通过分层使用多个内核特性、运行时沙盒和编排控制,可以在Docker中实现真正的多租户隔离。从用户命名空间和seccomp开始,然后升级到每租户守护进程或沙盒运行时。对于大规模部署,Kubernetes提供基于策略的隔离。始终与来自信誉良好的提供商的虚拟机监视器级隔离主机配对。没有单一技术是万能的,但将它们结合起来可以创建强大的防御。您的租户会感谢您——您的安全审计也会。

Sources (5)