Hotdry.

Article

自建云中 VM 隔离的底层实现:Linux Namespace 与 Cgroup 详解

深入解析自建云场景下 VM 隔离的底层原语:Linux namespace 六种隔离类型、cgroup v2 资源配额配置,以及自定义网络拓扑的工程实践路径。

2026-04-24systems

在构建私有云或自研云平台时,虚拟机隔离是整个系统的基石。传统虚拟化依赖 Hypervisor 实现硬件级隔离,而 Linux 提供了另一条路径:通过内核原语在操作系统层面构建轻量级隔离环境。本文聚焦于 VM 隔离的两大核心机制 ——Linux namespace 与 cgroup—— 并探讨自定义网络拓扑的工程实践,为自建云提供可落地的技术方案。

Namespace:隔离的基础边界

Linux namespace 是内核提供的资源视图隔离机制,它让运行在同一个内核上的进程组看到不同的系统资源。自内核 3.8 起,namespace 已发展出六种主要类型,每种负责隔离特定的系统资源维度。

UTS 命名空间隔离主机名和域名,使每个 VM 可以拥有独立的主机名。这对于多租户环境下的服务发现和日志标识尤为重要。在实现层面,通过 unshare(CLONE_NEWUTS)setns 系统调用即可创建新的 UTS 命名空间,随后在容器内使用 sethostname() 设置独立的主机名。

PID 命名空间实现进程 ID 的隔离。在独立的 PID 命名空间中,第一个进程 ID 总是 1,这模仿了传统操作系统的 init 进程行为。嵌套的 PID 命名空间允许创建层级化的进程树,这对于管理多个 VM 实例非常有用。创建时使用 CLONE_NEWPID 标志,随后在该命名空间内启动的进程将获得从 1 开始的本地 PID。

网络命名空间是实现自定义网络拓扑的关键。每个网络命名空间拥有独立的网络栈,包括独立的网络接口(网卡、网桥)、独立的 iptables 规则、独立的路由表和独立的 /proc/net 目录。通过 ip netns 命令或 unshare(CLONE_NEWNET) 可以创建网络命名空间,随后在内部配置独立的 IP 地址、路由规则和防火墙策略。两个网络命名空间之间的通信需要通过 veth(Virtual Ethernet)pair 或网桥进行桥接。

Mount 命名空间隔离文件系统的挂载点视图。这允许每个 VM 看到不同的文件系统层次结构,是容器镜像层叠文件系统的基础。通过 CLONE_NEWNS 创建,结合 pivot_root 或 chroot 技术,可以为每个 VM 提供独立的根文件系统视图。

IPC 命名空间隔离 System V IPC 对象和 POSIX 消息队列。在默认情况下,所有进程共享主机的 IPC 命名空间,这可能导致信息泄露和安全风险。通过 CLONE_NEWIPC 创建独立的 IPC 命名空间,可以防止不同 VM 之间的进程间通信干扰。

User 命名空间是最强大的隔离机制,它实现了用户 ID 和组 ID 的映射。在用户命名空间内部可以拥有完整的 root 权限,而在宿主机的视角中,该进程只是普通用户。这为非特权容器提供了安全保障。创建时使用 CLONE_NEWUSER 标志,并通过 /proc/self/uid_map/proc/self/gid_map 文件实现 ID 映射。

Cgroup:资源配额的控制平面

如果说 namespace 解决了 “我们是谁” 的问题,那么 cgroup 解决的则是 “我们能使用多少” 的问题。cgroup(Control Groups)是内核提供的资源管理和限制机制,它将进程分组并对每组实施资源配额和优先级控制。

cgroup v2 是当前推荐使用的版本,它统一了所有资源控制器的层级结构,避免了 v1 中多层级导致的复杂性。在自建云场景中,最常用的控制器包括:

CPU 控制器通过 cpu.max 或 cpu.shares 设置 CPU 配额。cpu.max 支持绝对值设置(如 100000 100000 表示完全占用一核),而 cpu.shares 是相对权重值,适用于需要公平调度的场景。对于延迟敏感的工作负载,还可以配置 cpu.latency 来限制调度延迟。

Memory 控制器提供内存限制和统计功能。memory.max 设置内存上限,memory.current 报告当前使用量,memory.high 用于设置软限制超过时的限制节流。在 VM 场景中,合理设置这些参数可以防止单个租户耗尽宿主机内存。

IO 控制器控制块设备的 I/O 速率。通过 io.max 设置 IOPS 上限,通过 io.bfq.weight 调整权重。对于需要保证 I/O 性能的数据库 VM,IO 控制器是必不可少的隔离工具。

PIDs 控制器限制命名空间内的进程数量,防止 fork 炸弹攻击。设置 pids.max 可以有效控制单个 VM 能创建的进程总数。

需要特别强调的是,cgroup 本身并非安全边界 —— 它主要用于资源管理和防止资源耗尽,而非提供强安全隔离。真正的安全边界仍依赖于 namespace、seccomp、SELinux/AppArmor 等机制的组合。

网络拓扑的自定义实践

在自建云中,网络隔离是实现多租户的关键。Linux 网络命名空间提供了构建自定义网络拓扑的基础能力,配合 veth pair、网桥和 iptables,可以构建复杂的网络架构。

最基本的模式是为每个 VM 创建一个独立的网络命名空间,通过 veth pair 与宿主机的网桥连接。veth pair 相当于一根虚拟网线,一端连接到 VM 的网络命名空间,另一端连接到宿主机的网桥。这种模式下,VM 可以通过 DHCP 或静态配置获得 IP 地址,所有网络流量都经过网桥转发。

对于需要更强隔离的场景,可以引入 VLAN 标签。通过在网桥上配置 VLAN,每个 VM 可以属于不同的虚拟局域网,实现二层隔离。更进一步,可以使用 VXLAN 或 Geneve 协议构建 Overlay 网络,支持大规模多租户部署。

在防火墙层面,iptables 或 nftables 提供了细粒度的流量控制。可以为每个 VM 创建独立的 iptables 链,实现入站和出站流量的过滤。对于容器化部署,Calico、Cilium 等网络插件提供了基于 eBPF 的高性能网络策略实现。

工程落地的关键参数

基于上述原理,自建云中 VM 隔离的工程实践可参考以下参数配置:

在 namespace 创建流程中,建议按顺序创建 user、pid、mount、ipc、uts、net 命名空间,确保进程在正确的隔离环境中启动。cgroup 配置方面,单个 VM 的推荐内存上限为宿主机总内存的 50% 以下,CPU 份额根据业务优先级分配,网络带宽可通过 tc(traffic control)工具限制。

监控层面,需要持续采集 cgroup 统计信息(memory.current、cpu.stat、io.stat),设置告警阈值。建议将 cgroup 路径与租户 ID 关联,便于追踪资源使用。

安全加固措施包括:限制容器能力(capabilities),使用 seccomp 过滤系统调用,启用 SELinux/AppArmor 强制访问控制。这些措施与 namespace/cgroup 配合,构成多层防御体系。

资料来源

本文技术细节参考 MIT CSAIL 计算机系统安全课程关于 OS 与 VM 隔离的 lecture notes,以及 Linux 内核官方文档中关于 namespace 和 cgroup 的技术规范。


systems