virt-report虚拟化社区动态

热插拔:资源上线、客户机协作与安全回收

本文由 OpenAI Codex (GPT-6-Astra) 辅助编写。

一、热插拔的资源范围与协作过程

热插拔允许虚拟机运行期间增加或移除设备、CPU 与内存。管理程序表达变更目标,QEMU 修改虚拟硬件,客户机驱动完成发现、上线或停用。资源是否已经可用或可以回收,取决于这些阶段是否全部完成。

客户机操作系统维护着自己的设备清单、驱动绑定与资源分配。在线变更需要通过它能识别的硬件协议通知变化:增加时发现并配置新资源,移除时先停止使用并交还资源。由此,热插拔同时改变虚拟硬件和客户机的软件状态,需要双方完成交接。

下面以 Q35 虚拟机在线添加、移除网卡为主线,再比较 vCPU 与内存调整。热添加先准备资源,再交给客户机使用;热移除先让客户机停止使用,再回收资源。两条流程都需要管理程序、虚拟硬件和客户机协调,通知协议与完成条件随资源类型而变。

源码版本:QEMU 10.2.0、Linux 6.18。

二、配置变更、硬件通知与客户机资源状态

冷启动时,客户机可以从头枚举所有硬件。运行中增加网卡,操作系统却不会因管理程序改了一个配置字段就自动发现它。QEMU 要模拟插槽状态变化并发出通知,客户机的总线驱动重新枚举设备,分配地址与中断,再把设备交给具体驱动。

移除更困难:网卡可能仍持有发送缓冲区,内存可能还装着进程页或内核对象。先删掉宿主资源,会让后续访问落到无效对象上。因此热移除要先发出请求,等客户机停止使用资源,再解除后端引用。这是增加与移除不能简单互为反向操作的原因。

状态所在位置增加网卡时发生的变化完成条件
管理层:宿主用户态Libvirt 等管理程序记录目标配置,准备网络后端目标配置已记录,运行变更已发起;仍需跟踪下面两层
机器模型:QEMU 进程在可热插拔端口下创建 PCIe 设备设备已实例化并发布插槽变化;客户机仍需完成资源分配
客户机内核与驱动枚举、绑定驱动并启用接口驱动和网络配置生效,业务能够使用

三份视图有传播顺序,短时间不一致并不罕见。持久配置中的网卡也可能只在下次启动时出现;一次在线添加成功,不代表重启后仍会保留。管理工具需要分别说明变更范围和当前进度。

三、增加与移除的交接顺序

资源热增与热移除的完成边界
热增先准备宿主资源与虚拟设备,再由客户机识别并使用;热移除需先通知客户机停用,确认完成后回收相应设备资源。QMP 接受请求与客户机完成操作处于不同阶段。
热增先准备宿主资源与虚拟设备,再由客户机识别并使用;热移除需先通知客户机停用,确认完成后回收相应设备资源。QMP 接受请求与客户机完成操作处于不同阶段。 打开原图
Mermaid 源码
flowchart TB
  accTitle: 资源热增与热移除的完成边界
  accDescr: 增加资源先准备后端与虚拟设备,再通知客户机识别使用;移除资源先通知客户机停止访问,再确认移除并回收资源。
  subgraph ADD["增加资源"]
    A["管理程序:准备后端与容量"] --> B["QEMU:提供设备或内存块"]
    B --> C["客户机:识别、上线并使用"]
  end
  subgraph REMOVE["移除资源"]
    D["管理程序:请求移除或缩容"] --> E["客户机:停止访问或迁移页面"]
    E --> F["确认完成:移除设备或内存块"]
    F --> G["回收已无使用者的宿主资源"]
  end
  C -. "后续调整" .-> D
  classDef management fill:#eaf0f6,stroke:#8198ac,color:#263c4c;
  classDef handoff fill:#e4f1ec,stroke:#438575,color:#173e34;
  classDef guest fill:#fff4db,stroke:#b89a55,color:#59491e;
  class A,D,G management;
  class B,F handoff;
  class C,E guest;

1. 热增:准备空间,再通知客户机

本例先为网卡预留可热插拔的 PCIe 端口、总线号与 BAR 窗口。运行中,管理程序创建宿主网络后端,再由 QEMU 创建并连接网卡 net1;端口报告插槽变化,客户机重新枚举设备、分配资源并绑定驱动。至此虚拟硬件与驱动已经建立,客户机还需配置接口和业务通路,才能真正使用新增网卡。

2. 热移除:先停止使用,再归还资源

移除同一块 net1 时,管理程序发起请求,QEMU 通过插槽通知客户机。客户机停止网卡队列和驱动访问,交还设备后,QEMU 才完成虚拟网卡的拆除。独立创建的网络后端还要等网卡不再引用它时清理。客户机可能延迟响应或无法完成,因此从请求受理到资源回收之间需要保留待处理状态。

四、移除 net1,缩减一段内存

向 QMP 发送 {"execute":"device_del","arguments":{"id":"net1"}} 后,成功响应只表示删除请求已受理。对于需要客户机配合的设备,管理程序继续等待对应 DEVICE_DELETED,再清理已无引用的网络后端。未收到完成事件时,要查看客户机驱动、插槽状态与错误事件,不能直接复用设备 ID。

DEVICE_DELETED 标识 QEMU 设备已移除;它并不证明应用已把流量切换到另一块网卡。若 net1 承载管理连接,应先让业务转用另一条通路,再发起移除,否则热插拔协议即使正确完成,业务仍会断连。

内存缩容沿用“先停止使用,再交还资源”的原则,交还对象变成了内存块。以 virtio-mem 为例,目标容量 requested-size 从 4 GiB 改为 2 GiB 后,实际已提供的 size 可能暂时仍为 4 GiB。客户机需要迁走被回收块中的页面,再发送 UNPLUG 请求;长期固定的页面可能阻止回收。这里等待的是内存块交还,前面网卡例子等待的是设备删除,不能用同一种完成事件判断两者。

下表把网卡、vCPU 与内存放回相同的交接顺序。各类资源都先通知客户机,但客户机的停用工作和管理层应核对的结果不同;内存还应分别观察设备提供容量、客户机在线容量和宿主 RSS。

资源通知与交接机制移除前客户机的工作需要分别确认的结果
PCIe 网卡端口原生热插拔或 ACPI 通知,取决于机器配置停用驱动、停止队列和设备访问QEMU 设备删除、独立后端清理、业务通路切换
x86 vCPUACPI CPU 通知与 eject迁移任务、中断和定时器,再下线处理器客户机 offline、QEMU 对象移除;仅 offline 不等于拔出
virtio-mem 容量配置通知与队列中的 PLUG/UNPLUG 请求迁走页面并停止使用选定块requested-size、实际 size 和客户机在线容量逐步收敛

五、从整设备增删到细粒度资源调整

设备与内存沿着各自的协议发展。前者侧重插槽发现、地址空间与驱动生命周期,后者侧重可调整容量、页面迁移与回收粒度。

传统 PCI 热插拔可以借助 ACPI 事件通知操作系统;PCIe 原生热插拔使用 Root Port 等端口的插槽寄存器与事件机制,客户机在获得相应控制权后由 PCIe 热插拔驱动处理。两者对应不同的机器配置与控制方式,不能假定所有虚拟机都走相同通知路径。资源预留帮助新增设备获得地址空间,但端口、总线号和 BAR 窗口仍有边界。

virtio-mem 用较小粒度的块调整容量,减少反复添加大块 DIMM 的需要,同时引入块状态与回收协议。更细粒度不保证任意页面都可迁移。评价热插拔要记录操作完成时间、客户机停顿与失败原因,而非只看管理命令是否成功返回。

内存调整方式宿主资源回收方式主要限制
DIMM 热插拔按内存设备增删,由客户机上线或下线相应区域插槽、地址空间、移除范围及可迁移页面
传统 virtio-balloon驱动占用客户机页面并通知宿主回收后备存储改变可用资源,不等同于移除一条 DIMM;需要客户机合作
virtio-mem在设备区域内按块提供或收回内存目标容量与已提供容量可能暂时不同,页面固定仍会阻碍缩容

六、用完成状态和业务影响判断操作结果

热插拔的收益是避免为资源调整重启客户机,代价是引入拓扑预留、驱动协作和异步失败处理。增加设备时分别检查命令、枚举、驱动与业务;移除设备时分别检查请求、客户机停用、设备删除与资源回收。超时后先查询实际状态,避免重复创建或删除已经变化的对象。

内存缩容还应观察页面迁移耗时、不可迁移页和客户机延迟。更细的回收粒度能避开部分忙页,代价是维护更多块状态;更大的地址空间预留方便后续扩容,也会占用有限的桥窗口或拓扑资源。方案选择应结合实际扩容上限和可接受的回收等待。

七、按资源类型继续阅读

八、参考资料