PVE 中的 CT 和 VM 是两种截然不同的虚拟化方案,但很多新手容易混淆概念。本文从基础概念切入,逐步深入到资源占用规则和容易忽略的细节差异,帮你彻底理清两者的区别。

1. 基础概念

1.1 CT(容器 / LXC)

CT 基于操作系统级虚拟化,核心是 Linux 内核的 cgroups 和 namespace 机制。多个 CT 共享宿主机同一个内核,各自拥有独立的文件系统、进程空间、网络栈和用户管理。CT 不模拟硬件,没有虚拟化层,本质上是一个隔离的进程组。

PVE 中 CT 的运行载体是 LXC(Linux Containers),模板是一个完整的 Linux 根文件系统(不含内核)。

1.2 VM(虚拟机 / KVM)

VM 基于硬件级虚拟化,通过 KVM(Kernel-based Virtual Machine)配合 QEMU 模拟完整的硬件设备(CPU、内存、磁盘控制器、网卡等)。每个 VM 拥有完全独立的内核,可以运行任意操作系统,彼此之间没有任何共享。

VM 的镜像文件可以是 qcow2、raw 或直接使用 LVM/ZFS 卷。

2. 核心差异对比

2.1 虚拟化方式

维度 CT VM
方式 操作系统级(cgroups + namespace) 硬件级(KVM + QEMU)
内核 共享宿主机内核 独立内核
硬件模拟 完整模拟 CPU、内存、磁盘、网卡等
嵌套虚拟化 不支持 支持

2.2 内核与操作系统

CT 能跑不同的 Linux 发行版(Ubuntu、Debian、CentOS、Alpine 等),但不能跑不同的操作系统。所有 CT 底层都使用宿主机内核,即使 CT 内装的是 CentOS 7,uname -r 看到的也是宿主机内核版本。

VM 则完全独立,每个 VM 启动自己的内核。宿主机是 Ubuntu,VM 里可以跑 Windows、FreeBSD、OpenBSD 或任何其他操作系统。

2.3 资源隔离与安全

隔离性是 CT 和 VM 最大的取舍点。CT 的隔离靠 Linux namespace,理论上存在逃逸风险(如果宿主机内核被攻破,所有 CT 可能受影响)。VM 的隔离是硬件级的,逃逸难度大得多,适合多租户场景。

2.4 性能开销

CT 几乎无性能损耗,磁盘和网络 I/O 接近裸机。VM 有虚拟化层,CPU 约 1-5% 损耗,磁盘和网络受 virtio 驱动影响,现代硬件上差距已经很小,但仍有差距。

3. 资源占用规则详解

这部分是实际使用中最容易踩坑的地方,值得单独展开。

3.1 内存

CT 设置 4G 内存,只是 cgroup 上限(硬限制),不是预分配。CT 内进程实际用了多少,宿主机就记多少。如果 CT 里只跑一个 Nginx,宿主机上只看到几十 MB 占用。

VM 设置 4G 内存,QEMU 进程会立即分配 4G 物理内存(或从 swap 里扣)。除非开启 ballooning,否则这 4G 对宿主机来说就是"已占用"状态。

3.2 CPU

CT 设置 4 核,只是一个 CPU 资源上限,不额外创建线程。CT 内的进程直接用宿主机调度器调度,几乎没有额外开销。

VM 设置 4 核,会生成 4 个 vCPU 线程,由宿主机调度器统一调度,但比 CT 多一层 KVM 的虚拟化调度开销。

3.3 磁盘

CT 的磁盘就是一个目录(通常是 /var/lib/vz/images/<CTID>/),设置 100G 配额只是限制 CT 内文件的总大小,实际只占用 CT 内文件真实使用的空间。

VM 的磁盘取决于存储格式:

  • qcow2:设 100G 但只用了 10G,镜像文件可能只有 10G 出头(稀疏模式),但写入性能略差,因为需要维护 COW 映射表
  • raw:设 100G 立即占 100G,除非用 ZFS 等支持稀疏的底层存储
  • LVM/ZFS 卷:取决于底层存储的分配策略(厚置备或精简置备)

3.4 网络

CT 通过 veth pair 接入宿主网络栈,延迟极低,性能接近原生。VM 通过 virtio 网卡接入,同样使用桥接/NAT 模式,但多一层 virtio 驱动开销,延迟略高。

两者都支持 VLAN、OVS、防火墙、带宽限制,配置方式基本一致。

3.5 GPU 与设备直通

CT 不支持 PCIe 设备直通,但可以通过 bind mount 共享宿主的 GPU 驱动(如 nvidia-container-runtime),实现多个 CT 共享同一张 GPU。

VM 支持完整的 PCIe passthrough,需要硬件支持 IOMMU,一张 GPU 一般只能直通给一个 VM。

4. 容易混淆的概念

4.1 "CT 能跑不同系统" — 用户空间 vs 内核

这是最常见的误解。"CT 可以跑 Ubuntu、Debian、CentOS" 这句话不假,但跑的是这些发行版的用户空间(/bin、/lib、/usr 等),内核始终是宿主机那个。CT 里 uname -r 永远返回宿主机内核版本,跟模板是什么发行版没关系。

打个比方:CT 像合租,共享水电(内核),各人住各屋(文件系统)。VM 像独栋,每栋都有自己的水电燃气。

4.2 "CT 模板就是系统" — 根文件系统 ≠ 操作系统

PVE 提供的 CT 模板(如 ubuntu-24.04-standard_24.04-1_amd64.tar.zst)是一个完整的 Linux 根文件系统,但它不包含内核。所以它不是"操作系统"——只是操作系统的躯壳,内核借宿主的。只要模板是 Linux 且架构(amd64)匹配,就都能跑。

4.3 "设置 4G 内存 = 占用 4G" — 上限 vs 硬分配

这个区别在实际资源规划上影响很大:

宿主机 16G 内存,跑 5 个 CT 各设 4G 上限(共 20G)
→ 正常运行,每个 CT 实际只占自己进程用的部分

宿主机 16G 内存,跑 5 个 VM 各设 4G(共 20G)
→ 启动即 OOM,宿主机直接崩

CT 天然适合超卖(overcommit),VM 超卖需要非常小心。

4.4 CT 超卖可以,VM 超卖要小心

CT 的超卖是安全的,因为资源是软限制——用多少占多少,总体实际使用不超过物理资源就能跑。VM 的超卖意味着你允许 QEMU 进程申请的物理内存超过宿主机实际内存,一旦所有 VM 同时跑满,宿主机 OOM Killer 会随机杀掉进程,可能导致不可预测的故障。

4.5 VM 的 qcow2 也不一定立即占满磁盘

很多人在 VM 上用 qcow2,以为设 100G 就占 100G。不是的。qcow2 是稀疏文件,写入多少数据才增长多少。但 qcow2 的写入性能不如 raw 或 CT 的目录模式,因为需要维护 COW 映射表。如果对磁盘性能要求高,可以考虑 raw 格式或直通 LVM/ZFS 卷。

5. 选型建议

5.1 优先选 CT 的场景

  • 跑 Linux 应用:Nginx、MySQL、Redis、各种 Web 服务
  • 资源有限,需要最大化利用硬件
  • 需要快速批量部署、弹性伸缩
  • 个人或小团队使用,隔离要求不高

5.2 必须选 VM 的场景

  • 需要跑 Windows 或其他非 Linux 系统
  • 需要自定义内核模块或不同内核版本
  • 多租户场景,安全隔离要求高
  • 需要 PCIe 直通(GPU、NVMe 网卡等)
  • 需要嵌套虚拟化(在 VM 里再跑 PVE 或 Docker)

5.3 混合使用

生产环境常见做法:关键服务用 VM 跑(保障隔离和稳定性),普通应用用 CT 跑(提高资源利用率)。两者配合使用,比单一方案更灵活、更高效。