KVM vs OpenVZ vs LXC——为什么虚拟化类型很重要

自己的内核、独占内存、真正的 swap、Windows 或 BSD 镜像——完全虚拟化决定了 VPS 能跑什么。Core 套餐 $6/月,年付折合 $4.80。
自己的内核、独占内存、真正的 swap、Windows 或 BSD 镜像——完全虚拟化决定了 VPS 能跑什么。Core 套餐 $6/月,年付折合 $4.80。
你在购买前跑的跑分,到了生产环境会骗人
每一张对比图表都会让容器领先几个百分点,而每一张这样的图表都是在空载主机、没有任何其他负载的情况下测出来的。合成跑分衡量的是你“能感知到”的虚拟化边界;它衡量不了你第三个月才会遇到的“吵闹邻居”——当别人的备份任务重写你数据库所依赖的内存池时。请按第二个数字购买,而不是第一个。
KVM 为每台服务器呈现虚拟硬件,并在其上启动你自选的真实内核。代价是一层很薄的翻译层——用 KVM 项目自己的说法,在配备 ECC 内存的当前 EPYC 和 Ryzen 主机上,微基准测试的损耗只有几个百分点。回报则是一堵硬墙:独占内存、自己的页表、自己的调度器,以及一块邻居突发负载时宿主机也无法收回的 swap 设备。在两种型号上各自空载时运行 fio --name=t --size=1g --rw=randread --bs=4k,容器会赢;而在邻居正在编译时跑同样的测试,结果就会反转。
原因在于记账方式,而不是什么魔法。容器是一组带突发额度的进程;KVM 虚拟机是一台有内存映射的机器。当宿主机承压时,容器的内存池会在无声无息中缩小,而虚拟机的不会——所以那个在负载下不可信的跑分,从一开始就在测量错误的东西。在编译期间对比两种型号的 vmstat 1 输出,一两分钟内差异就不再是理论问题。
常见的错误是从比价网站的表格里选套餐,迁移完才发现架构不对。数据落地之前先检查:在共享内核的机器上,uname -r 显示的是服务商的构建字符串,ls /dev/kvm 会失败。在 KVM 切片上该设备存在,内核字符串属于你,一两条命令就能分辨。现在是十秒钟的检查,还是日后负载超出这个假象时的整体迁移,任你选。
完全虚拟化不是更快;它是可预测的,而生产环境真正购买的就是可预测性。容器套餐无法承诺的一切,都源自这同一堵墙:诚实的内存、可选择的内核、真正的 swap,以及 Linux 家族之外的镜像。下面的章节逐一展开这些承诺,并附上替代方案的失效方式——因为只有当双方都诚实地失败时,对比才有意义。
VPS $4.80* 起(年付期限),存储 1–5 TB NVMe 年付折合 $24/月起,带 IPMI 的独立服务器 $39.20/月起。加密货币账单,免 KYC。
立即启动共享内核意味着宿主机可以收回面板上写着“属于你”的东西
容器套餐上面板里的数字描述的是一个峰值,而不是一份所有权。OpenVZ 和 LXC 把内存记作一个突发池,邻居一突发,宿主机随时收回——这意味着套餐宣传的 2 GB 是一个你可能碰到、但留不住的下限之上的天花板。完全虚拟化把这一点反过来:独占的页面始终属于你,其他租户的压力止步于虚拟化边界,而不是侵入你的数据库内部。
这种回收有可辨认的签名。在承压的共享内核主机上,突发额度最先消失,然后内核开始扫描“受害者”,OOM killer 按它自己的评分做选择——所以倒下的往往是你的数据库,而不是那个吵闹的邻居。在 KVM 虚拟机上,同样的压力只有在你的真实用量确实超过你自己的限额时,才会产生 dmesg | grep -i oom 的输出,而且内核的 overcommit 行为遵循你自己设定的规则,正如内核的 overcommit 文档为“你真正管理的那台机器”所描述的那样。
诚实的内存也会改变调优方式。一台独占 4 GB 的虚拟机可以让 InnoDB 按合适的尺寸配置缓冲池,把 vm.swappiness 调到自己喜欢的值,并且相信明天早上这些数字依然成立。在突发池上,同样的设置只描述一场实验室实验,因为分母会在你不知情的情况下改变。容器上的容量规划是对别人行为的预测;KVM 上则是只关于你自己的算术。这就是全部差别,用一条容量规则的形式陈述出来。
错误在于相信面板的曲线图,而不是内核自己的证词。面板会“礼貌地”采样;内存压力却会留下收据。容器套餐上出现任何性能谜团之后,去读 /proc/user_beancounters(如果存在)以及 OOM 历史(如果不存在),故事通常自己会写出来:额度耗尽、受害者选定、数据库凌晨四点被杀。KVM 消灭的是这一整类事故,而不只是其中一例——这也是为什么本目录里每一个套餐都是完全虚拟化。
独占内存是第一个结构性承诺;第二个是内核本身。跑什么版本、加载哪些模块、存在哪些 sysctl,是容器撞上的下一堵墙。下一节顺着版本字符串往下讲,说明为什么这个差别在服务器生命周期中不断累积,而不是逐渐消失。
你拿到的内核版本,就是你保住的内核版本
在容器套餐上,服务器上最重要的那个版本号并不属于你。服务商的宿主机内核决定哪些 cgroup 特性存在、哪些 BPF 辅助函数可用、哪些 iptables 模块已加载、你被允许碰哪些 sysctl——提交多少工单也改变不了这个由其他租户共享的内核。版本字符串是服务商(可能几年前)出于与你技术栈毫无关系的原因做出的决定。
KVM 虚拟机启动的是你安装的任何东西:发行版内核、自编译内核、通过 DKMS 编译的树外模块。WireGuard 用 modprobe wireguard 就能起来,正如项目快速入门所假设的那样;BPF 工具链与你的用户态保持同步,因为 bpftool version 和运行中的内核来自同一条发布线;安全补丁在你应用时生效,而不是等宿主机的维护窗口。内核的 BPF 文档发布了这些接口,而在你自己的内核上,你终于同时握有这份契约的两端。
这在兼容性矩阵的边缘最为关键。需要较新 nftables 特性的技术栈、eBPF 探针、或者服务商从未启用的某个模块,在共享内核上就是部署不上去,故障会以日志里一个缺失符号的形式在最糟糕的时刻浮现。在你自己的内核上,同样的技术栈只是一次包安装,因为 ABI 不再是别人的路线图,而成了你自己的发布计划。
经典错误是把应用迁到容器套餐上,然后在事故进行到一半时撞墙:netfilter 模块缺失、cgroup 控制器只读、内核太老装不上厂商昨天发布的补丁。迁移之前先用 uname -r 对照应用的文档要求检查版本,并在赌注还只是一台实验机的时候用 modprobe 加载好需要的模块——而不是在用户都在围观上线日的时候。
拥有内核,你也就拥有了内存压力下调度器的行为——这正是真正 swap 登场的地方。“体面地降级”与“轰然倒地”之间的差别,是容器撞上的下一堵墙,下一节将用凌晨三点真实发生的运维语言来讲清楚它。
swap 把内存尖峰变成延迟,而不是一场葬礼
容器套餐很少给你真正的 swap,而销售文案把这说成一项特性。它不是。在突发池上,内存耗尽意味着内核的 OOM killer 到场并挑选一个进程开枪——通常是那个握着活跃连接的进程,也就是用户正在用的那个。配有真实 swap 设备的 KVM 虚拟机会先降级为延迟,越过那条线才会死,这改变了每个糟糕夜晚的形状。
机制并不光鲜,但起决定作用。swap 以最冷页面的访问延迟为代价扩展虚拟机的可用内存,于是本该是一次硬性击杀的尖峰,变成一段你来得及应对的缓慢期。用 swapon --show 和 vmstat 1 观察它的发生:si 和 so 列上升,响应时间攀升,你得到的是几分钟的处置时间,而不是一具需要复活的尸体。在希望内存优先于 swap、稳定优先于一切的数据库机器上,用 sysctl vm.swappiness=10 调节这个权衡。
真正的 swap 还让内存从另一个方向变得诚实:内核可以把被你遗忘的应用的闲置缓存换出,让你关心的那个应用的工作集留在内存里。没有 swap 的容器没有这样的阀门——压力直接转化为击杀,内核选中的受害者反映的是它自己的评分,而不是你的优先级。正是这种不对称,让超售的容器在深夜批量任务堆积、无人盯图的时候倒下。
错误在于因为论坛说现代磁盘让 swap 毫无意义,就在 KVM 机器上关掉 swap,然后在一次缩略图生成风暴或备份恢复峰值面前毫无缓冲可言。通用服务器按内存的一半到等量来配置 swap,把 swapon --show 写进运维手册,并按换入速率而非原始 swap 占用来告警——占用是静静待命的储备,活动才是“今天就有事需要处理”的症状。
内存和内核是运行时的承诺。接下来的承诺关乎到底能启动什么:Linux 家族之外的镜像,以及虚拟机内部的硬件虚拟化。两者都是虚拟化类型的结构属性,而不是可以申请的功能;两者都决定了一块租来的切片在其生命周期中允许变成什么。
启动自己的镜像是结构能力,不是一张支持工单
VPS 上跑 Windows、防火墙上跑 FreeBSD、一个只有两个用户的冷门发行版——容器系服务商一样都卖不了,出什么价都不行,因为共享内核只能运行一个操作系统,而它早在几年前就被服务商定死了。完全虚拟化把机器交到引导程序手里,镜像问题于是变成一个有着无聊答案的支持问题:只要它能在虚拟硬件上启动,它就能在这里启动。
实际可达的范围比 Linux 家族宽得多。BSD 镜像原生运行自己的内核;Windows 在 KVM 的虚拟机接口下配合KVM 项目所记载的驱动运行;救援 ISO、硬件厂商的诊断工具、自定义安装器,全都以同样的方式挂载。上传之前用 md5sum 对照发布方的校验和验证完整性,挂上 ISO,你早已熟悉的安装器就出现在你掌控的控制台上。不需要上游任何人点头,也没有任何工单流转。
自定义 ISO 支持还改变了灾难恢复。一台能启动你的救援镜像的机器,让你可以在没有支持工程师介入的情况下完成挂载、fsck 和文件系统修复——故障在什么钟点找上门都行。容器上没有可以劫持的启动环节——恢复意味着服务商的工具箱和他们的队列、他们的节奏。平均修复时间的差距,就是“拥有一台机器”与“租用一个流程”的差距,而且恰恰在你最需要它的时候显现。
错误在于以为容器服务商可以按需添加冷门镜像——结构上不可能,你得到的那句礼貌拒绝是对架构的准确描述,而不是政策选择。在为某个不常见的操作系统定下套餐之前,先问清楚你购买的这一档能启动哪些镜像,并用 ls -l /dev/kvm 确认设备文件存在。一条命令永远地解决架构问题,在任何数据开始流动之前。
同一套虚拟硬件,在这里的 VPS 档位上,还能在第一个虚拟机里再启动第二个——嵌套虚拟化。下一节把这块切片当作实验台而不是单一用途的服务器来对待,这是开发者最先问起、却直到需要时才意识到其价值的属性。
嵌套虚拟化把 VPS 变成一张实验台
KVM VPS 的奇妙属性是它也能伪装成一台虚拟机管理器。嵌套虚拟化让虚拟机运行自己的 VM:三节点 Kubernetes 实验环境、Windows 测试机、路由器镜像——全都装在梯子最底部的一片切片里。容器套餐在任何档位都提供不了这个,因为共享内核没有可以透传给任何人的虚拟化扩展。
围绕它做规划之前先检查能力:grep -cE 'vmx|svm' /proc/cpuinfo 统计暴露给你虚拟机的虚拟化标志,lsmod | grep kvm 显示你的内核上已加载的模块。嵌套 KVM 可用时,在里面装上第二层虚拟机管理器,像在裸机上一样启动虚拟机镜像——内核的 nested-VMX 文档维护着哪些能干净嵌套、哪些不能的矩阵。诚实的提醒是性能:嵌套 I/O 要支付双重虚拟化成本,所以从第一个实验起就把磁盘和预期都放大一号。
实验场景是它立刻回本的地方。每次运行需要三台干净机器的 CI 矩阵、一堂集群演示课、一套生产拓扑的镜像环境——每一个都只差一个配置文件,而不是一张硬件订单。给实验虚拟机打快照、从代码重建,环境就不再是需要供着的宠物机。在容器套餐上,同样的实验从给销售写邮件开始,通常也就到此为止——这就是实验室最终都住在完全虚拟化上的原因。
错误在于把嵌套虚拟机当成生产容量。它是实验台:跑构建、测试、演示没问题,任何需要你以自己的名义担保 SLA 的东西都别放。把嵌套层留给可丢弃的工作,给外层切片留足余量,并记住你 VPS 里的 qemu-system-x86_64 是和你自己的服务在争同一批独占核心。纸面上你有权把预留花两次;核心本身不行。
内核、swap 设备、可启动镜像、可嵌套的虚拟机管理器——在这四样东西之间,一片 KVM 切片是完整意义上的“一台小机器”。下一个问题是开发者实践中最先问的:那容器本身呢,用最普通的方式跑,就像在笔记本上那样?
完整虚拟机里的 Docker,表现和裸机上一样
基于容器的 VPS 里跑 Docker,是容器套容器,接缝处处可见:cgroup 版本交叠、被屏蔽的 sysctl、没人能解释第二遍的半吊子网络把戏。KVM 虚拟机里跑 Docker,就是你自己内核上的 Docker——不受限制、不被屏蔽,和你的笔记本别无二致。这个区别听起来很学术,直到第一个 Compose 栈因为报错信息根本说不清的原因拒绝启动。
一切常规操作都正常:引擎按官方文档安装,docker compose up -d 拉起整个栈,bind mount 表现如常,桥接网络拥有自己的命名空间、底下是真正的 netfilter。唯一要盯着的预算项是容器存储——镜像和卷落在你的 NVMe 上,而 docker system df 就是那条能说出实话的命令:入门档 80 GB 里有多少这个星期正被构建缓存悄悄扣押。
KVM 模型还移除了某些容器宿主机强加的权限层。特权容器、自定义网络、技术栈想先加载的内核模块——都不存在“先问服务商”这一步:modprobe 一下,然后 docker run,模块就在那里,为之后的每一个容器服务。正是这一个属性,让需要 eBPF 的 CI runner、VPN 镜像和监控代理在这里直接可用,而在别处静默、神秘地失败——内核只对你负责,容器只和内核对话。
经典错误是放任镜像不断堆积,直到磁盘占满、数据库开始拒绝写入——Docker 的垃圾在响之前一直安静,一旦响了就非常响。把 docker system prune 排进计划任务,数据放命名卷而不是匿名卷,每次大版本升级前先检查 overlay。当负载真正超出任何切片时,上 $49/月(年付折合 $39.20/月)的独立服务器 Forge,在 2 x 1 TB 独享 NVMe 和 IPMI 之上运行同样的技术栈。
容器是负载本身;虚拟化类型决定它们是像客人一样运行,还是像囚徒一样运行。最后一笔账是价格:完全虚拟化在标价上花多少,又从风险栏里划掉多少——因为这两栏从来不会像对比表格暗示的那样对齐,而这个差额就是整个决策。
完全虚拟化花多少钱,又免掉什么
KVM 诚实的成本栏写着:微基准测试上几个百分点、给虚拟机内核留出的几十兆字节、以秒计的启动时间。诚实的收益栏写着:你自己的内核、独占的 ECC 内存、真正的 swap、任何可启动镜像、嵌套虚拟化,以及没有权限层的 Docker。目录给这整包东西定价时,仿佛虚拟机管理器是白送的——因为在运维上它几乎就是。
三级 VPS 阶梯从 2 vCPU / 4 GB 入门档,经 8 GB,到 8 vCPU / 32 GB 的旗舰,每一级都是 KVM,端口不限流量 1/2.5/10 Gbps,年付直减 20%。以 $6/月(年付折合 $4.80/月)订购 Core,内核、swap 设备和内存映射就从结构上属于你,而不是靠政策恩赐。这个类型从不出现在加购推荐里,因为没有更便宜的容器版可以从那里“升级”;这堵墙是标配。
这个类型免掉的是一整类事故,而这一类才是贵的部分。没有在邻居 cron 时辰消失的突发额度,没有把你的数据库和别人的页缓存放在一起打分的 OOM killer,没有服务商从未编译的模块,没有平台无法启动的操作系统。这些是共享内核的架构性结果,不是某家服务商的坏毛病——而同样的隔离逻辑在网络边缘同样成立,详见DDoS 防护与滥用处理指南。
另一个方向的错误,是为用不上的隔离付钱:静态网站或 cron 机器跑在几乎任何东西上都行,随便什么的最便宜一档都够用。让类型匹配你承受不起的那次失败。数据库、邮件、CI、一切有状态的东西——这才是前几节讲的容器失效模式集中爆发的地方,也是这堵墙每个月都挣回它那几个百分点、却从不出现在任何账单上的地方。
在数据落地之前,把类型这件事一次定死,因为之后跨越这条边界的迁移意味着全新安装加一次拷贝,连同随之而来的全部规划。最后一节把整个决策压缩成一套执行顺序——从空机器上的第一条命令,到负载赢得你信任的那一刻。
虚拟化检查清单,按执行顺序排列
下单之前先做检查,先在纸面上做。列出必须能启动的东西:操作系统镜像、内核模块、嵌套虚拟机、带特权容器的 Compose 栈。清单上任何一样共享内核在结构上给不了的东西——BSD、Windows、自定义内核、随心所欲的 modprobe——都会在价格入场之前终结类型之争,这是唯一经得起真实负载检验的顺序。
新机器上的前十分钟用来验证这笔购买。uname -r 应显示一个你认识、而且能更换的内核字符串;ls -l /dev/kvm 应显示虚拟化设备,存在且归属清晰;swapon --show 应列出一个真实的 swap 设备;free -m 应显示套餐承诺的内存,独占且足额。四条命令,每条十秒,架构就是被验证过的,而不是从对比表格里想当然的。
然后按生产环境的用法给机器上负载,因为类型之间的差别只在压力下显现。用 fio 跑存储测试,用 vmstat 1 观察内存行为,同时编译一个大东西。你要找的是“没有意外”:没有内存池被收回,没有看不见的邻居,没有你自己用量解释不了的 dmesg | grep -i oom 输出。空载时诚实、满载时也诚实的机器,就是诚实的,句号。
接下来搭运行时:按官方文档装 Docker,装技术栈需要的模块,配置数据库想要的 sysctl,每配一项就写进运维手册。这也是把前一节的 swap 容量和 swappiness 一次性定死的时机——此刻没有数据要迁移,没有用户会被打扰。数据落地之前你配置的一切都是决策;落地之后的一切都是风险。
只有现在数据才开始移动,而且是在第一次恢复演练通过之后。按常规顺序迁移——文件、数据库、配置、DNS 最后——并保留旧环境,直到新环境完整熬过包括首个备份周期在内的一整周。这套流程里任何一步让你感到意外,你都是在赌注还只是一台实验机时意外的;这正是这套流程存在的意义,也是类型问题永远排在第一位的原因。
这里所有套餐都是 KVM 吗,还是有容器降级档位?
全目录 KVM,VPS 和独立服务器一视同仁。完全虚拟化、你可掌控的内核、自定义 ISO 支持以及 VPS 线上的嵌套虚拟化,随每一个档位提供,价格表底部也没有藏着任何基于容器的特价货架。每个档位的架构都一样;变的只是墙后面的资源。
KVM 可以测量地比 OpenVZ 慢吗?
微基准测试会让容器占一点便宜,因为它们跳过了虚拟化边界,而合成跑分正是这种优势止步的地方。在配备 ECC 内存的当前 EPYC 和 Ryzen 主机上,KVM 的开销在生产环境中只是舍入误差,而隔离换来的,是整类邻居效应的消失。一份在负载下不可信的跑分,构不成一个方案。
可以在 KVM VPS 上运行 Docker 和 Compose 吗?
可以,毫无限制:完整版 Docker、多服务 Compose 栈,以及构建矩阵或实验环境需要的嵌套虚拟化。你的容器和你自己的内核之间不存在权限层。如果负载最终超出任何切片,独立服务器产品线在独享裸金属和 IPMI 之上给你同样的 root 权限。
虚拟化类型会体现在价格里吗?
它不是计费项。三级 VPS 阶梯每一级都是 KVM,年付对你选中的任何档位直减 20%。你付费购买的是 CPU 核心、ECC 内存和 NVMe,不是某个虚拟机管理器版本,也没有更便宜的容器版被扣着当加购卖点。
可以启动自己的内核或自定义 ISO 吗?
这正是完全虚拟化的意义所在。自定义内核构建、树外模块、DKMS 驱动、BSD 或 Windows 镜像、嵌套 KVM——全部可用,因为虚拟机管理器呈现虚拟硬件,让你的引导程序决定上面跑什么。共享内核容器在结构上一样都给不了,这就是为什么类型的选择比任何单一功能清单都重要。