C23

KVM 与 QEMU

点击正文段落选定收藏或划线位置;未选定时使用屏幕内第一段。

课内目录

1 KVM 与 QEMU 要回答什么

部署订单 API 时,团队希望得到 4 个 vCPU、8 GiB 内存、可启动的系统盘和能接入业务网络的网卡。申请页面上的这些字段看起来像在购买服务器,实际交付的却通常是虚拟机。虚拟机中的操作系统认为自己正在使用处理器、内存和设备,背后则有宿主机的软件与硬件共同提供这些能力。本课要解释的,是这层转换如何成立,以及它给计算方案留下哪些边界。

先把场景具体化:订单 API 接收请求,校验调用者身份,把订单写入数据库,并把请求耗时送到监控系统。API 可以运行在虚拟机中,但数据库、身份系统和监控平台可能位于其他机器。虚拟化主要决定 API 所在计算环境如何获得资源、如何隔离以及如何维护;它不会自动替应用完成身份校验、数据库备份或告警响应。明确职责范围,才能判断性能问题究竟应该向哪层寻找证据。

KVM 是 Linux 内核提供的虚拟化能力,借助处理器的硬件虚拟化支持,让客户机代码能够受控地运行。QEMU 是用户空间程序,可以构造虚拟机器、提供设备模型,也能在其他使用方式下模拟处理器。常见的 Linux 虚拟机组合是 QEMU 使用 KVM 加速:KVM 负责关键的执行支持,QEMU 负责组织机器及其设备。它们是合作关系,不能把任何 1 个名字直接等同于完整云平台。

云平台还要完成镜像分发、身份授权、主机选择、网络配置、磁盘挂接、生命周期管理和计量。这些能力通常通过管理服务调用虚拟化组件。用户提交“创建实例”,并不意味着请求直接进入 KVM;管理服务要先判断调用者能否创建、资源放在哪里、镜像是否可用,再启动相应进程。把控制请求和运行中的数据流分开,有助于解释为什么控制台暂时不可用时,已经运行的 API 仍可能继续服务。

本课使用“宿主机”表示承载虚拟机的物理服务器及其操作系统,使用“客户机”表示虚拟机及其中的操作系统。讨论数量时,还要区分“已配置”“正在使用”“能够保证”。配置 4 个 vCPU 表示客户机看见 4 个虚拟处理器,不等于任何时刻都能独占 4 个物理核心。配置 8 GiB 内存也不能直接推导宿主机已经为全部客户机准备了互不争用的物理容量。后面的观察与取舍都围绕这些区别展开。

KVM、QEMU 与云管理面的职责关系
KVM、QEMU 与云管理面的职责关系

2 虚拟机监控器、客户机与设备模型

虚拟机监控器通常译自 hypervisor,也称 VMM。它的核心任务是控制客户机对物理资源的访问,使多个客户机可以共享机器,并保留必要的隔离与管理能力。在 KVM 与 QEMU 的组合中,这些责任分布在内核、用户空间程序和硬件之间。入门阶段不必争论某个组件应该归入哪种分类,更有用的问题是:谁执行客户机代码,谁响应设备请求,谁掌握创建和停止虚拟机的权限。

客户机运行自己的内核和应用。它能够调度自己的进程、管理自己的文件系统,却看不到宿主机上全部租户的资源竞争。宿主机则把客户机的执行活动纳入自己的资源管理。常见实现中,客户机的 vCPU 对应宿主机上的执行线程,需要获得宿主机 CPU 时间。客户机内部认为某个业务线程已经可以运行,并不保证承载它的 vCPU 此刻已经获得物理处理器。这是理解虚拟化延迟的重要起点。

设备模型解决“客户机以为自己连接了什么”的问题。启动操作系统需要磁盘、网卡、时钟等设备接口,QEMU 可以为这些接口提供实现。客户机访问虚拟磁盘时,后端可能连接宿主机文件、块设备或远端存储;客户机发送网络包时,后端可能经过虚拟网络接口、宿主机网络处理和物理网卡。客户机看到的设备名称与真实物理路径并不是同 1 件事,因此排查时必须把前端设备和后端资源对应起来。

硬件辅助虚拟化让大量客户机指令直接在处理器上执行,遇到需要更高层处理的事件时才切换到相应处理路径。不能据此认为“所有工作都由硬件完成”,也不能反过来想象“每条指令都由 QEMU 翻译”。具体事件如何触发切换属于后续深入主题。现在只需掌握:普通计算、特权操作和设备访问可能经过不同路径,路径上的排队、切换和后端负载都会影响完成时间。

以订单 API 写日志为例,应用调用文件写入接口,客户机内核处理文件系统请求,经虚拟设备把 I/O 交给后端,后端再访问实际存储。应用看到写入成功的含义还与缓存和持久化设置有关,不能仅凭“使用了虚拟磁盘”判断数据已经落到可靠介质。计算虚拟化提供机器接口,数据可靠性仍需要存储配置、应用写入方式和备份策略共同支撑。

隔离也有范围。客户机之间不应随意访问彼此内存,但它们仍可能竞争宿主机 CPU、内存带宽、磁盘和网络。管理接口拥有创建、关闭和挂接设备等强权限,需要身份认证、最小权限和操作审计。业务安全组限制业务网络流量,不能替代宿主机管理权限控制。把“资源隔离”“性能保证”“权限隔离”分别写清楚,比笼统承诺“虚拟机彼此完全独立”更准确。

订单请求经过客户机与宿主机的执行路径
订单请求经过客户机与宿主机的执行路径

3 CPU、内存与 virtio 的能力边界

vCPU 是客户机可调度的处理器单位。宿主机可以给虚拟机设置 CPU 时间份额、上限或其他约束,但具体语义取决于平台实现。假设宿主机有 16 个可供业务使用的物理核心,创建 8 台各配 4 个 vCPU 的虚拟机,就形成了 32 个 vCPU 对 16 个核心的配置关系。这种比较必须采用统一口径:逻辑处理器数、物理核心数以及为宿主机预留的容量都应明确,不能把不同口径混在同 1 个比例中。

32 个 vCPU 不一定立即造成问题,因为业务可能错峰使用 CPU。问题出现在多个客户机同时需要运行时:可运行的 vCPU 要等待调度,API 内部的线程即使没有增加计算量,也可能更晚得到执行机会。CPU 利用率是观察线索,不能单独代表请求响应能力。某个时间段平均利用率只有 50%,仍可能包含短暂的集中竞争,或者某台虚拟机受到限额而无法使用其他空闲容量。

内存需要同时观察客户机配置量、客户机实际压力和宿主机可用容量。客户机中的缓存通常可以被回收,应用长期持有的数据则未必能及时释放。宿主机上也存在页缓存、虚拟化进程开销和内核开销。把全部“看起来可回收”的内存算成随时可承诺资源,会忽略回收所需的时间和业务代价。对订单 API,回收引起的延迟即使持续时间不长,也可能让客户端超时并发起重试。

部分环境支持内存气球等机制,用客户机与宿主机的协作调整内存使用。它需要相应驱动、平台配置和可回收空间,不能凭空增加物理内存。宿主机交换也不能等价替代 RAM:当活跃内存被频繁换入换出时,应用可能从偶发抖动进入持续停顿。入门方案应优先说明保留容量、压力告警与扩容动作,不应把复杂回收机制作为必然可兑现的容量来源。

virtio 是面向虚拟化环境的标准化设备接口体系。客户机使用理解这种接口的驱动,与后端协作传递请求,减少兼容某些传统硬件接口带来的额外工作。它常用于虚拟网卡和虚拟块设备,但“使用 virtio”只说明路径中的接口选择,不能推出磁盘延迟、网络带宽或 CPU 开销必然达到某个值。后端存储、宿主机负载、队列配置及驱动状态仍然影响结果。

例如 API 发出 1 次数据库请求,virtio 网络接口可以参与数据传送,但无法缩短数据库锁等待。磁盘采用 virtio,也无法抵消远端存储的拥塞。比较方案时,应在相同请求规模、相近宿主机竞争程度和相同持久化要求下测量。把驱动类型作为配置证据,把吞吐量和分位延迟作为运行证据,才能避免把某个技术名词当成绩效保证。

本课不展开地址转换细节、处理器缓存一致性或具体队列实现。先保留足够准确的边界:KVM 帮助受控执行,QEMU 组织虚拟机器,virtio 改善设备协作接口;CPU 时间、物理内存和 I/O 后端仍然是有限资源。任何优化都应说明改善了哪段路径,以及哪些资源竞争仍然存在。

4 动手:从宿主机观测一台客户机资源

这个观察练习适用于你有管理权限的 Linux 实验宿主机,并假定虚拟机由 libvirt 管理、相关工具已经安装。libvirt 是常见的虚拟机管理接口与工具体系,这里用它把虚拟机名称和运行指标对应起来。如果使用托管云而看不到宿主机,就通过平台提供的实例指标和工单获取对应证据,不应尝试进入不属于自己的宿主机。练习只观察已有虚拟机,不创建负载,也不修改配置。

先选定实验虚拟机,例如 order-api,并确认它确实是目标环境。执行下面命令时,将示例名称替换为实际名称;不同权限与版本可能导致字段有所差异。记录观察时间、虚拟机标识、宿主机标识和业务请求量,后续每个指标才能归入相同时间窗口。只有名称而没有稳定标识,在迁移或重建后可能把不同运行实例误认为同 1 台机器。

virsh list --all
virsh dominfo order-api
virsh domstats order-api --vcpu --balloon --block --interface
virsh domblklist order-api
virsh domiflist order-api

列表和基本信息用于确认状态及配置,统计用于查看 vCPU、内存和设备活动,磁盘与网卡列表用于建立前后端对应关系。部分统计字段需要额外支持才能出现,内存气球统计还可能受客户机驱动和采集周期影响。字段缺失应该记作“未获得”,不能记成 0。累计计数也不能直接当成每秒速率,应在相隔已知时长的采样间计算差值,并注意计数是否因重启而重置。

再观察宿主机整体状态。下面的工具分别提供 CPU 与内存活动、内存概况和设备 I/O 线索,其中 iostat 通常来自 sysstat 软件包。不要为了完成练习临时改动生产机的软件和采样配置;工具不可用时可采用已有监控中的对应指标。命令结束后保留采样时间,避免拿宿主机上午的数据解释客户机下午的抖动。

vmstat 1 5
free -h
iostat -xz 1 5

观察 vmstat 时,把可运行任务、CPU 等待相关指标和交换活动联系起来。free 的 available 比单看 free 更接近可供新负载使用的估计,但它仍不是业务容量承诺。iostat 可以帮助发现设备延迟和队列变化;复杂存储、并行设备或远端后端不能仅靠某个利用率字段判断是否饱和。部分工具的首份报告可能反映启动以来的平均值,应结合工具说明识别,并重点比较后续采样。

最后进入客户机,观察 API 的 CPU、内存、错误率及请求分位延迟。若系统提供 steal time,它表示虚拟 CPU 等待宿主机提供执行时间的相关线索;该指标的可见性和解释受环境影响,较低数值也不能排除全部调度或限额问题。将客户机结果与宿主机结果并排记录:客户机忙、宿主机忙,可能是总体容量不足;客户机慢、宿主机看似不忙,则还需检查配额、局部竞争与应用等待。

练习的产物应是可复核的观察记录,例如“14:00 至 14:05,order-api 配置 4 个 vCPU,业务请求量稳定,宿主机可运行任务增加,客户机 p99 同时上升”。这支持进一步调查,却还不能证明因果关系。若后续需要调整规格或迁移,必须在相似负载下比较变化,并同时看数据库和网络依赖,防止把相关性写成结论。

把客户机、宿主机和业务指标对齐到相同时间窗口
把客户机、宿主机和业务指标对齐到相同时间窗口

5 热迁移、快照与停机窗口取舍

热迁移的目标是在虚拟机保持服务的过程中,把运行位置从源宿主机转移到目标宿主机。常见方式会先复制内存,在客户机继续运行时追踪并补传变化,最后短暂停顿,完成剩余状态转移和目标端接管。具体实现可能采用其他方式,本课只用这个过程解释成本。热迁移追求缩短停顿,并不承诺请求完全无感,最后的切换仍可能影响连接、计时和短请求的尾延迟。

迁移需要条件配合。目标机要有足够资源和兼容的运行能力,网络连接要能延续,磁盘后端也要可访问或被正确搬移。如果源端内存变化很快,而迁移网络传输能力有限,待复制状态可能难以减少。此时可能需要限速业务、改变迁移策略、接受更长停顿,或者改用计划停机。设备直通等配置也可能限制迁移能力,因此迁移是否可用必须在设计阶段验证。

快照保存的是某个时点的状态,但“状态”要写清楚。仅磁盘快照通常不包含运行中的内存,包含内存的快照又会增加保存量和恢复条件。即使抓到了磁盘时点,也不等于数据库已经完成应用层一致性处理。可以把它理解为突然断电后可能需要恢复的状态,而不能默认等价于正常停库后的数据副本。需要应用一致性时,应采用数据库和平台明确支持的协调流程。

快照也不是独立备份的同义词。某些快照依赖原始磁盘或同 1 个存储系统,基础存储故障、误删除及权限失陷仍可能同时影响它们。订单系统需要明确恢复点目标和恢复时间目标:前者表达最多能接受丢失多久的数据,后者表达多久恢复服务。虚拟机快照可以帮助某些回退操作,但订单数据恢复仍要结合数据库备份、日志与实际恢复演练。

维护窗口应围绕用户请求决定。假设计划迁移前将 API 从负载均衡中摘除,等待已有请求结束,再执行维护并验证健康,这会减少用户遇到长暂停的机会,却要求剩余实例承担流量。如果数据库只允许单点写入,还需遵守它的切换流程。可用性来自多实例、容量余量和依赖协调,不能只押在“支持热迁移”这个能力标签上。

评价方案时,把准备时间、业务停顿、恢复验证和失败回退都计入窗口。复制状态用了 10 分钟而最终停顿只有 1 秒,两者分别影响维护进度和请求体验;不能只报告其中更好看的数字。对入门部署,宁可先设计可演练的短暂停机流程,再在明确收益时引入热迁移,也不要承诺未经验证的连续服务。

迁移与快照分别保留哪些状态
迁移与快照分别保留哪些状态

6 常见坑:把宿主机空闲当客户机可承诺

最常见的误判,是看到宿主机某次采样还有空闲,就立刻增加客户机承诺。空闲是一段时间内的观察,可承诺容量则要覆盖约定负载、故障和维护条件。订单 API 平时请求不多,但促销开始时可能与其他租户同时升高。如果容量模型只采用日均值,多个看似互补的负载可能在关键时刻一起争用资源。超售可以提高利用率,但必须建立在可观察、可限制和可退让的条件上。

另 1 个误判是把客户机规格相加,当作已经得到物理容量保证。vCPU 配置量通常允许大于物理执行容量,内存配置也可能配合特定回收策略。相反,有些平台提供明确的资源保留或独占能力。不能从通用技术名称推导某个平台的承诺,应直接查清资源保障、限制和竞争时的处理规则。方案应写出“配置多少”和“最低可获得多少”,不能用含糊的高性能描述替代。

监控也容易制造错觉。平均 CPU 利用率会抹平突发,宿主机总量会遮住局部热点,客户机看到的可用内存无法解释宿主机是否正在交换。只看 p50 延迟则会错过少量但严重的慢请求。对 API,至少联合观察请求量、错误率、p95 或 p99、客户机资源压力及宿主机竞争指标,并把采样间隔与请求变化速度相匹配。指标越多并不自动越清楚,关键是它们能否回答同 1 个时间窗口的问题。

处置时也不能只会增加 vCPU。若瓶颈是存储后端排队,增加 CPU 很可能没有收益;若宿主机 CPU 已经紧张,增加虚拟处理器还可能加重竞争。若应用单个串行环节限制吞吐,更多可调度单元也不保证利用起来。先判断请求耗时主要花在执行、等待资源还是等待依赖,再选择限制并发、迁移、扩容或优化应用,才能让动作与原因对应。

容量保留要能解释。为宿主机管理活动保留空间,为业务突发保留余量,为维护和故障保留接管能力,它们解决的是不同情形。不能简单把所有百分比相加,也不能用某个统一比例覆盖所有服务。团队应通过压测和历史曲线确定起始值,写出达到阈值后的动作,并随着部署密度变化复测。没有动作的告警和没有验证的余量,都不足以支撑承诺。

7 案例:过量超售导致尾延迟飙升

某实验集群把订单 API 与批处理任务放在同 1 台宿主机上。宿主机为业务预留 16 个物理核心,客户机共配置 48 个 vCPU,配置比为 3:1。平时 API 用量低,批处理也常等待远端数据,日均监控看起来宽裕。团队于是继续沿用这个配置,却没有验证两类任务同时进入高峰时的表现。这里的数字是教学情境,不能当成某个超售比例普遍安全或危险的结论。

促销开始后,API 请求量上升,批处理恰好进入集中计算阶段。示例监控中,API 的 p50 从 30 毫秒变为 40 毫秒,p99 却从 120 毫秒升至 900 毫秒,客户端开始超时重试。重试又增加请求量,使排队进一步延长。客户机内存没有明显增长,数据库响应也相对稳定;宿主机可运行任务增多,API 客户机出现执行等待线索。这些现象把调查方向指向 CPU 竞争,但仍需要排除限额与其他依赖变化。

团队先对齐促销、批处理启动和延迟上升的时间,再检查虚拟机配额及后端指标。随后在受控窗口降低批处理并发,保持 API 流量大致相同,观察到宿主机执行等待和 API 的 p99 同时回落。把 API 迁到有余量的宿主机后,相似请求规模下也得到改善。这些相互支持的证据,比单独看到 CPU 曲线变高更有说服力;但记录仍需注明负载差异,避免把实验结果推广到所有场景。

短期措施是限制批处理并发、抑制无界重试,并给 API 留出可执行的容量。增加 API 实例只有在它们得到额外物理资源时才可能帮助;若所有新增实例仍挤在原宿主机上,虚拟机数量增加并不等于容量增加。必要时通过准入限制让部分请求快速失败,配合客户端退避,防止排队不断扩散。具体阈值要依据业务可接受的错误与延迟确定。

长期修正包括把交互服务与吞吐型任务的峰值关系纳入放置策略,为重要服务设置适合的资源保障,并验证维护期间剩余主机能否承载流量。恢复后还要在近似促销条件下复测 p99 和错误率,而不只是确认 CPU 利用率下降。事故结论应是“现有配置未覆盖同时高峰”,而不是“虚拟化必然很慢”;同样也不能因为某次迁移有效,就跳过对容量和重试策略的修正。

从尾延迟上升到容量竞争验证的排查路径
从尾延迟上升到容量竞争验证的排查路径

8 把虚拟化边界写进计算方案

计算方案首先要描述可交付的机器接口:客户机系统与驱动要求、vCPU 和内存配置、磁盘与网卡接口,以及这些接口连接的实际服务。订单 API 的数据写到远端数据库,就应把数据库依赖画在虚拟机之外;运行日志需要可靠留存,就应说明日志采集和保存位置。不能因为应用运行在虚拟机里,就默认系统盘承担全部业务数据保护责任。

随后写明资源承诺与放置条件。若使用共享 CPU,应说明允许的竞争、可用指标和触发扩容或迁移的条件;若要求资源保留,应确认平台实际支持且配置生效。内存预算要包含应用、客户机系统和必要缓存,宿主机预算还要考虑虚拟化开销。生产容量数字应来自相应负载下的测量,文档中的示例规格只能作为起点。

运行责任也要可执行。应用团队负责请求指标、并发与重试策略,基础设施团队负责宿主机与虚拟化层观测,存储和网络责任人提供后端证据。出现 p99 升高时,交接材料至少包含实例标识、时间窗口、请求量、客户机压力和相关变更。它让接手者能够继续调查,而不必从“机器好像变慢了”重新开始。

维护部分应注明迁移前提、可接受停顿、摘流方式、健康验证和失败回退。恢复部分要区分快照回退与数据恢复,写明应用一致性的获得方式及演练范围。管理权限则通过独立身份、最小授权与审计控制,避免业务账号同时拥有宿主机管理能力。这样,性能、可用性和安全的边界都能落到动作与负责人。

最后安排验收:在代表性的请求规模下验证延迟和错误率,在合理的同机竞争下观察余量,再演练 1 次维护或恢复路径。验收不必覆盖所有底层机制,但必须覆盖方案所作的承诺。任何尚未测量的能力都应标为待验证条件,避免把可选功能写成已经交付的保障。

9 从KVM 与 QEMU走向I/O 虚拟化(C24)

理解 KVM 与 QEMU 后,可以把计算路径和 I/O 路径分开提问。前者关心客户机何时获得处理器、内存容量如何支撑运行;后者关心请求如何从客户机设备到达实际网卡或存储。订单 API 的业务线程已经得到 CPU,却仍可能等待网络发送或磁盘完成。因此,确认 CPU 有余量以后,调查并没有结束,而是转向设备接口、后端队列和共享链路。

virtio 提供了面向虚拟化的协作接口,设备模拟重视兼容性,其他设备访问方式又可能把更多工作交给不同组件。选择会影响 CPU 消耗、吞吐量、延迟、隔离和迁移条件。不能仅用“经过的软件更少”判断方案更好,因为运维需要的观测、限速和迁移能力同样有价值。性能收益必须与设备约束和维护成本共同比较。

进入 C24 前,先能画出简化路径:应用、客户机内核、虚拟设备接口、宿主机后端、物理设备或远端服务。遇到延迟时,逐段寻找队列与时间证据,而不是直接把全部等待归给 QEMU。接下来再学习 I/O 虚拟化如何改变这条路径,以及为什么更直接的访问方式也会带来新的资源和生命周期边界。

放进方案里

为订单 API 编写计算方案时,可先采用这样的表述:服务以多台 Linux 客户机运行,虚拟化执行由 KVM 支持,QEMU 提供机器与设备组织,客户机安装兼容的 virtio 驱动。每台初始配置 4 个 vCPU、8 GiB 内存,规格仅为压测起点;最终数量按目标请求量、p99 和错误率确定。数据库与日志保存服务单独定义容量和恢复目标,避免把客户机系统盘当作完整的数据保护方案。

资源条款应分别记录配置量、保障方式与共享条件。宿主机预留管理开销和维护余量,交互服务与批处理共同部署前验证同时高峰。监控对齐请求量、p99、客户机 CPU 与内存、宿主机执行等待和后端 I/O;字段不可见时写明证据获取渠道。出现持续延迟时,先确认应用依赖和资源竞争,再按预案限并发、限制批任务、迁移或扩容,新增实例必须获得实际可用容量。

维护条款写明目标宿主机兼容性、存储与网络连续性、摘流等待及健康验证。热迁移是否采用,以演练得到的停顿和失败处置结果为准;不满足条件时使用约定停机窗口。快照注明是否包含内存、是否具备应用一致性,以及是否依赖原存储。数据库另有独立备份、日志恢复和恢复演练,业务负责人确认可接受的数据损失与恢复时间。

权限条款将业务身份与宿主机管理身份分离,创建、迁移、快照和删除操作保留审计。验收交付相同负载下的性能记录、竞争场景结果和维护演练记录,并明确应用、基础设施及存储网络责任人。尚未验证的资源保障或迁移能力列为上线前条件,使方案中的每项承诺都有证据和执行入口。

10 小结:下一步I/O 虚拟化(C24)

KVM 与 QEMU 共同支撑常见的 Linux 虚拟机:前者提供内核中的硬件辅助虚拟化能力,后者组织机器并提供设备相关实现。客户机获得可使用的机器接口,实际性能仍受宿主机调度、物理内存和 I/O 后端约束。配置资源、观察用量和承诺容量必须分别表达。

复习时可以自问:4 个 vCPU 为什么不能直接视为 4 个独占物理核心?客户机 p99 升高时,需要哪些宿主机与业务证据?磁盘快照为什么不能自动替代数据库备份?能用执行等待、共享竞争和一致性边界解释这些问题,就已经具备进入 C24 的基础。下一课将沿着虚拟设备到物理设备的路径,继续理解 I/O 虚拟化的取舍。

同阶段相关课

AI 答疑

默认关闭。启用后,只发送本课标题、最近阅读的屏幕内正文摘录(最多 6000 字)与本次问题。

配置自己的服务