OFFSET偏移
← 文章目录OFFSET / FIELD NOTESNO. 137

用 virsh 管理域、存储、网络与恢复

保留命令分类和 XML 参数,并明确持久定义、运行实例、快照与离线备份的区别。

所在专题KVM 宿主与管理基础 ↗
约 55 分钟阅读开始阅读

命令与 XML 使用通用示例,需按宿主版本和实际资源调整。网络地址采用文档地址段,实际部署应选择不冲突的私网;镜像修改与设备直通的适用条件见对应章节。

libvirt 是 KVM 虚拟化栈的管理抽象层,virsh 是与它对话的命令行。这一篇聚焦 libvirt 守护进程的架构演进、virsh 全命令分类、XML domain 配置精要,以及日常运维中最常用的命令行工作流。


1. libvirt 守护进程架构#

1.1 什么是 libvirt

libvirt 是一套虚拟化管理 API,它为各种 hypervisor(KVM、QEMU、Xen、LXC、VMware ESX 等)提供统一的 XML 配置接口和远程管理协议。在 KVM 栈中,libvirt 的位置如下:

User (virsh / virt-manager / Cockpit)
       |
       v
  libvirt API (libvirtd / modular daemons)
       |
       v
  QEMU (userspace device emulation)
       |
       v
  KVM (kernel module, CPU/memory virtualization)

libvirt 的核心职责:

  • Domain 生命周期管理:start、stop、pause、resume、migrate
  • 资源抽象:将 CPU、内存、磁盘、网络抽象为统一 XML 模型
  • 远程管理:通过 SSH、TLS、TCP 等方式远程控制 hypervisor
  • 安全隔离:支持 sVirt(SELinux)、AppArmor、cgroups 资源限制

1.2 单体架构 vs 模块化架构

graph LR
    subgraph "Traditional Monolithic"
        V1["virsh / virt-manager"] --> L1["libvirtd / (All-in-One)"]
        L1 --> Q1["QEMU"]
        L1 --> N1["Network"]
        L1 --> S1["Storage"]
    end

    subgraph "Modern Modular"
        V2["virsh / virt-manager"] --> P2["virtproxyd / (Proxy)"]
        P2 --> QD["virtqemud / (QEMU VMs)"]
        P2 --> ND["virtnetworkd / (Networks)"]
        P2 --> SD["virtstoraged / (Storage Pools)"]
        P2 --> DD["virtnodedevd / (Host Devices)"]
        P2 --> SEC["virtsecretd / (Secrets)"]
        QD --> Q2["QEMU"]
        ND --> N2["dnsmasq"]
        SD --> S2["Storage Backend"]
    end

传统单体 libvirtd(仍由部分发行版采用):

  • 一个守护进程处理所有功能:VM 管理、网络、存储、设备、密钥
  • 优点:简单,一个服务一个 socket
  • 缺点:任何功能崩溃影响全体;权限粒度粗,不易做最小权限

现代模块化守护进程(是否启用取决于发行版与安装配置):

守护进程 职责 socket
virtqemud QEMU/KVM 虚拟机生命周期 virtqemud.socket
virtnetworkd 虚拟网络(NAT/bridge 网络) virtnetworkd.socket
virtstoraged 存储池和卷管理 virtstoraged.socket
virtnodedevd 主机设备(PCI/USB)枚举 virtnodedevd.socket
virtproxyd 远程连接代理(TLS/SSH 转发) virtproxyd.socket
virtsecretd 密钥和凭证管理 virtsecretd.socket
virtinterfaced 主机网络接口管理 virtinterfaced.socket
virtnwfilterd 网络过滤规则 virtnwfilterd.socket
virtlxcd LXC 容器(若启用) virtlxcd.socket

模块化架构的优势:

  • 故障隔离:管理进程分开可降低部分故障传播;网络故障仍会影响 VM 联网
  • 权限粒度:可以仅为用户授予 VM 管理权,不给网络/存储管理权
  • 按需启动:通过 socket activation,减少空闲 daemon 进程开销
  • 独立升级:各模块可独立重启

部署选择:先检查宿主实际服务和 socket,再按官方迁移步骤选择架构。本次核对的 nixos-unstable libvirtd 模块仍使用单体 libvirtd;不能据版本号宣称 NixOS 24.05+ 一律模块化。以下服务命令只适用于采用该架构的普通 systemd 发行版;不要与仍启用的单体 socket 混用。NixOS 使用模块定义服务。

启用模块化守护进程(适用于 systemd 系统):

# 为 QEMU 驱动启用所有模块化守护进程
for drv in qemu interface network nodedev nwfilter secret storage
do
  sudo systemctl unmask virt${drv}d.service
  sudo systemctl unmask virt${drv}d{,-ro,-admin}.socket
  sudo systemctl enable virt${drv}d.service
  sudo systemctl enable virt${drv}d{,-ro,-admin}.socket
  sudo systemctl start virt${drv}d.socket
done

1.3 连接 URI 全解

libvirt 的连接 URI 使用统一模式:

driver[+transport]://[username@]hostname[:port]/[path]

本地连接:

URI 说明
qemu:///system 系统级管理实例,QEMU 身份由配置决定;主机重启会终止进程,autostart 或状态恢复会另行启动 VM
qemu:///session 用户级实例,QEMU 以用户身份运行;注销后的进程处理取决于用户服务与登录策略
qemu+unix:///system 同 qemu:///system,显式指定 Unix socket

system vs session 的实质性差异:

维度 qemu:///system qemu:///session
运行用户 daemon 特权与 QEMU 身份分开;后者由宿主配置决定 当前普通用户
VM 存活范围 跨登录会话;不跨宿主重启存活 由用户服务和注销策略决定;不跨宿主重启存活
网络 可用 NAT/bridge/routed 通常仅 user-mode (SLIRP)
存储池 /var/lib/libvirt/images ~/.local/share/libvirt/images
配置文件 /etc/libvirt/qemu/ ~/.config/libvirt/qemu/
PCI 直通 支持 不支持(需 root)
使用场景 服务器、长期运行 VM 开发测试、桌面虚拟化

经验法则:服务器用 system,桌面开发用 session。想 GPU 直通必须 system。

远程连接:

URI 传输方式 说明
qemu+ssh://user@host/system SSH 隧道 最常用,利用 SSH key 免密
qemu+ssh://user@host/session SSH 隧道 连接到远程主机的 session 实例
qemu+tls://host/system TLS 证书 企业部署,需 CA 签发证书
qemu+tcp://host:16509/system 明文 TCP 不安全,仅测试用(需改配置开启)
qemu+libssh2://user@host/system libssh2 替代 openssh,性能更好但需额外编译

在 virsh 中指定连接 URI:

# 临时指定
virsh -c qemu:///system list --all
virsh -c qemu+ssh://root@198.51.100.100/system list --all

# 设置默认 URI(shell 环境变量)
export LIBVIRT_DEFAULT_URI="qemu:///system"
virsh list --all  # 此后不再需要 -c

1.4 关键配置文件

文件 用途
/etc/libvirt/libvirtd.conf 单体 libvirtd 主配置(日志、TLS、连接控制)
/etc/libvirt/qemu.conf QEMU 驱动的全局配置(user/group、VNC/SPICE、安全)
/etc/libvirt/qemu/<domain>.xml 每个 VM 的 domain XML(单一事实来源)
/etc/libvirt/storage/<pool>.xml 存储池 XML 定义
/etc/libvirt/network/<net>.xml 虚拟网络 XML 定义
/var/log/libvirt/qemu/<domain>.log 每个 VM 的 QEMU 日志

修改配置后重启对应守护进程:

# 单体架构
sudo systemctl restart libvirtd

# 模块化架构
sudo systemctl restart virtqemud

2. virsh 命令全集#

virsh 是 libvirt 的主 CLI 工具。它是一个 shell-wrapper,每次调用通过 libvirt RPC 协议与守护进程通信。所有命令返回语义化退出码,适合脚本化。

2.1 Domain 生命周期管理

命令 说明 实用示例
virsh list 列出运行中的 VM virsh list --all(包含已停止的)
virsh list --title 列出 VM 并显示标题 virsh list --all --title
virsh list --autostart 列出已标记 autostart 的 VM virsh list --all --autostart
virsh start <domain> 启动已定义的 VM virsh start win11
virsh start --console <domain> 启动并立即连接控制台 virsh start --console archlinux
virsh start --paused <domain> 以 paused 状态启动 VM virsh start --paused win11
virsh shutdown <domain> 优雅关机(发送 ACPI 信号) virsh shutdown win11
virsh shutdown --mode agent <domain> 通过 QEMU Guest Agent 关机 virsh shutdown --mode agent ubuntu22
virsh reboot <domain> 优雅重启(发送 ACPI 信号) virsh reboot win11
virsh reset <domain> 硬重启(等同于按 reset 键) virsh reset stuck-vm
virsh destroy <domain> 强制断电(拔电源线) virsh destroy win11
virsh suspend <domain> 暂停 VM(CPU 冻结) virsh suspend win11
virsh resume <domain> 从暂停恢复 virsh resume win11
virsh save <domain> <file> 保存 VM 状态到文件(hibernate) virsh save win11 /tmp/win11.state
virsh restore <file> 从状态文件恢复 VM virsh restore /tmp/win11.state
virsh managedsave <domain> 立即保存 VM 运行状态并停止 VM;下次 start 可恢复 virsh managedsave win11
virsh managedsave-remove <domain> 删除自动保存的状态文件 virsh managedsave-remove win11

virsh shutdown vs destroy vs reset 对比:

graph TD
    RUN[VM 运行中] -->|"virsh shutdown / (ACPI 信号, 优雅)"| STOP[正常关机]
    RUN -->|"virsh destroy / (强制断电, 拔插头)"| OFF[立即终止]
    STOP -->|"可能丢失内存数据"| OFF
    OFF -->|"virsh start"| RUN
    STOP -->|"virsh start"| RUN
    RUN -->|"virsh save <file>"| FILE[状态文件 / (保存 RAM)]
    FILE -->|"virsh restore <file>"| RUN

推荐:总是先尝试 virsh shutdown,超时才用 virsh destroy。ACPI 关机依赖客户机 ACPI 支持和策略;guest-agent 关机还需要 agent 与 channel,不能将 virtio-win 驱动作为 ACPI 的必然前提。强制关机前应确认正常关机失败并接受数据风险。

虚拟机定义管理:

命令 说明
virsh define <file.xml> 从 XML 文件注册 VM(不启动)
virsh undefine <domain> 删除 VM 定义(保留磁盘文件)
virsh undefine --remove-all-storage <domain> 删除 VM + 关联的所有存储卷
virsh undefine --nvram <domain> 同时删除 NVRAM 文件(UEFI VM)
virsh undefine --snapshots-metadata <domain> 同时删除快照元数据
virsh edit <domain> 编辑 VM XML(退出时自动校验)
virsh dumpxml <domain> 导出 VM 完整 XML 到 stdout
virsh dumpxml --inactive <domain> 导出静态配置(不含运行时变化)
virsh autostart <domain> 设置为宿主机启动时自动启动
virsh autostart --disable <domain> 取消 autostart

实用示例:

# 批量查看所有 VM 状态
virsh list --all

# 备份 VM 配置
virsh dumpxml win11 > ~/vm-backups/win11-$(date +%F).xml

# 从备份恢复并启动
virsh define ~/vm-backups/win11-2025-01-15.xml
virsh start win11

# 彻底删除一个 VM (包括磁盘)
virsh destroy win11
virsh undefine --remove-all-storage --nvram --snapshots-metadata win11

2.2 Domain 信息与监控

基本信息

命令 说明 关键输出字段
virsh dominfo <domain> VM 概览 State, CPU, Memory, Autostart, Security
virsh domstate <domain> 运行状态 running / shutoff / paused / crashed
virsh domstate --reason <domain> 状态 + 原因 如 "shut off (shutdown)"
virsh domid <domain> 获取运行中 VM 的 ID 数字 ID,关机后为 -1
virsh domuuid <domain> 获取 VM UUID 固定不变的 UUID
virsh domname <uuid> 通过 UUID 反查名称 脚本中常用
virsh domcontrol <domain> QEMU monitor 连接状态 ok / error
virsh domtime <domain> 查看/设置 VM 时钟 virsh domtime --sync win11

资源监控

# 类 top 的实时监视器 (持续刷新)
virt-top --connect qemu:///system

# CPU 统计
virsh domstats --cpu-total <domain>

# 内存统计 (RSS, 缓存, swap-in/out)
virsh dommemstat <domain>

# 磁盘 I/O 统计 (rd_req, wr_req, rd_bytes, wr_bytes)
virsh domblkstat win11 vda

# 网卡 I/O 统计 (rx_bytes, tx_bytes, rx_packets, tx_packets)
virsh domifstat win11 vnet0

# 列出块设备
virsh domblklist <domain> --details

# 列出网络接口
virsh domiflist <domain>

# 宿主机信息
virsh nodeinfo        # CPU 型号、核心数、内存总量
virsh nodememstats    # 宿主机内存使用
virsh nodecpustats    # 宿主机 CPU 使用率(百分比)
virsh nodecpumap      # CPU topology map

vCPU 分析

命令 说明
virsh vcpucount <domain> vCPU 数量摘要(current / maximum / 在线数)
virsh vcpuinfo <domain> 每个 vCPU 与 pCPU 的映射关系、CPU 时间
virsh vcpupin <domain> 查看/设置 vCPU 到 pCPU 的绑定
virsh emulatorpin <domain> 查看/设置 QEMU 模拟器线程到 pCPU 的绑定

实用示例:

# 获取 VM 当前资源消耗全貌
virsh dominfo win11
virsh dommemstat win11
virsh domblklist win11 --details
virsh domiflist win11

# 实时监控 (类似 top)
virt-top --connect qemu:///system

# 脚本化: 获取 VM 当前使用内存
virsh dommemstat win11 | awk '/rss/ {print $2}'

# 查看 vCPU 绑定情况
virsh vcpuinfo win11

2.3 存储池与卷管理

池/卷操作也可能写入或删除真实后端。pool-build 对某些 backend 会格式化资源,vol-delete/upload 不应对在线磁盘执行;明确所属池、文件/块设备与所有消费者。仅下载一个正在写的卷不构成一致备份。后端支持依 libvirt 编译与软件包而变,NFS 的池类型为 netfs。

libvirt 的存储管理分为两层:存储池(Pool) 是存储后端,卷(Volume) 是池中的具体磁盘文件。

存储池(Pool)操作

命令 说明
virsh pool-list 列出所有存储池
virsh pool-list --all 包含未激活的池
virsh pool-list --details 显示路径和状态详情
virsh pool-info <pool> 池的详细信息(类型、容量、已用、分配)
virsh pool-define-as <name> dir --target <path> 创建目录型存储池
virsh pool-define-as <name> logical --target /dev/vg0 创建 LVM 存储池
virsh pool-build <pool> 构建池的基础设施(如格式化分区)
virsh pool-start <pool> 激活存储池
virsh pool-autostart <pool> 设为自动启动
virsh pool-autostart --disable <pool> 取消自动启动
virsh pool-destroy <pool> 强制停用池
virsh pool-delete <pool> 删除池资源
virsh pool-undefine <pool> 删除池定义
virsh pool-refresh <pool> 刷新池中的卷列表(新增磁盘文件后执行)
virsh pool-dumpxml <pool> 导出池 XML 定义

卷(Volume)操作

命令 说明
virsh vol-list <pool> 列出池中所有卷
virsh vol-list --details <pool> 显示卷的详细信息(类型、容量)
virsh vol-info <vol> --pool <pool> 单个卷的详细信息
virsh vol-create-as <pool> <name> <size> 创建卷(支持 K/M/G/T 单位)
virsh vol-create-as <pool> <name> <size> --format qcow2 创建 qcow2 格式卷
virsh vol-create-as <pool> <name> <size> --format raw --prealloc-metadata 创建 raw 格式预分配卷
virsh vol-clone <vol> <newname> --pool <pool> 克隆卷
virsh vol-resize <vol> <newsize> --pool <pool> 扩容卷
virsh vol-delete <vol> --pool <pool> 删除卷
virsh vol-download <vol> <file> --pool <pool> 下载卷到本地文件
virsh vol-upload <vol> <file> --pool <pool> 上传本地文件为卷
virsh vol-path <vol> --pool <pool> 获取卷在文件系统中的绝对路径
virsh vol-key <vol> --pool <pool> 获取卷的 key(Ceph RBD 等需此值)
virsh vol-dumpxml <vol> --pool <pool> 导出卷 XML 定义
virsh vol-wipe <vol> --pool <pool> 安全擦除卷数据

实用示例:

# 创建自定义存储池
virsh pool-define-as my-vms dir --target /data/libvirt/images
virsh pool-start my-vms
virsh pool-autostart my-vms

# 创建 VM 磁盘
virsh vol-create-as my-vms archlinux.qcow2 40G --format qcow2

# 查看磁盘文件的实际路径
virsh vol-path archlinux.qcow2 --pool my-vms
# => /data/libvirt/images/archlinux.qcow2

# 扩容 VM 磁盘(注意:仅扩大虚拟磁盘,分区/文件系统需 VM 内操作)
virsh vol-resize archlinux.qcow2 60G --pool my-vms

# 克隆 VM 磁盘
virsh vol-clone archlinux.qcow2 archlinux-clone.qcow2 --pool my-vms

# 备份卷到文件
virsh vol-download archlinux.qcow2 /mnt/backup/archlinux.qcow2 --pool my-vms

常见存储池类型:dir(目录)、logical(LVM)、disk(物理磁盘)、iscsi、rbd(Ceph)、zfs、gluster、netfs(NFS 使用 netfs 类型与 nfs 格式)。最常用的是 dir 类型。

2.4 虚拟网络管理

命令 说明
virsh net-list 列出活动网络
virsh net-list --all 列出所有定义的网络
virsh net-info <net> 网络详情(bridge 设备、IP 范围)
virsh net-start <net> 启动网络
virsh net-autostart <net> 设为自动启动
virsh net-autostart --disable <net> 取消自动启动
virsh net-destroy <net> 强制停止网络
virsh net-define <file.xml> 从 XML 文件定义网络
virsh net-undefine <net> 删除网络定义
virsh net-edit <net> 编辑网络 XML
virsh net-dumpxml <net> 导出网络 XML
virsh net-dhcp-leases <net> 查看 DHCP 租约表
virsh net-update <net> 实时更新网络配置(不重启)

实用示例:

# 查看 default 网络的 DHCP 分配情况
virsh net-dhcp-leases default

# 输出示例:
#  Expiry Time           MAC address         Protocol  IP address        Hostname
#  2025-06-20 14:30:00   <GENERATED_MAC_ADDRESS>   ipv4      192.0.2.100   ubuntu-server

自定义网络 XML 示例(隔离网络):

<network>
  <name>isolated-net</name>
  <bridge name='virbr1' stp='on' delay='0'/>
  <ip address='203.0.113.1' netmask='255.255.255.0'>
    <dhcp>
      <range start='203.0.113.10' end='203.0.113.200'/>
    </dhcp>
  </ip>
</network>
# 定义并启动自定义网络
virsh net-define isolated-net.xml
virsh net-start isolated-net
virsh net-autostart isolated-net

2.5 快照管理

重要:internal 将磁盘快照存入支持该功能的镜像;external 切换到新的 overlay 文件。snapshot-create 从 XML 读取要求,snapshot-create-as 从参数生成要求,两者都不能单凭命令名区分快照类型。--disk-only 表示不保存内存,不能替代对每块盘的 snapshot=external/文件路径及链状态检查。快照不是独立备份;TPM、UEFI NVRAM、VFIO、外部存储及当前版本会限制快照、回滚和迁移。

命令 说明
virsh snapshot-create-as <domain> --name <name> 按支持的默认设置创建快照;先检查类型与客体状态
virsh snapshot-create-as <domain> --name <name> --description "变更前" 创建含备注的快照
virsh snapshot-create-as <domain> --name <name> --disk-only 请求 disk-only 快照;明确 diskspec 并核对 overlay 链
virsh snapshot-create-as <domain> --name <name> --disk-only --diskspec "vda,snapshot=external,file=/path/snap.qcow2" 指定 external 快照目标
virsh snapshot-create <domain> <snapshotfile.xml> 从 XML 文件创建快照
virsh snapshot-list <domain> 查看快照列表
virsh snapshot-list <domain> --tree 树形查看快照链
virsh snapshot-info <domain> --snapshotname <name> 快照详情
virsh snapshot-current <domain> 查看当前快照
virsh snapshot-revert <domain> --snapshotname <name> 还原到指定快照
virsh snapshot-revert <domain> --snapshotname <name> --running 还原后自动启动
virsh snapshot-delete <domain> --snapshotname <name> 删除快照;internal 丢弃该恢复点,external 操作受版本与链结构限制,不等同于无条件合并
virsh snapshot-delete <domain> --snapshotname <name> --children-only 仅删除子快照
virsh snapshot-parent <domain> --snapshotname <name> 查看快照的父快照
virsh snapshot-dumpxml <domain> --snapshotname <name> 导出快照 XML

典型快照工作流:

下面是支持 internal 快照的示意流程:先验证磁盘格式、domain 功能与当前快照支持,备份必要外部状态。关机命令是异步请求;创建、回滚与删除前用 domstate 确认所需状态。不能将其直接套用到带 VFIO、TPM、NVRAM 或复杂 external 链的 Windows VM。在线一致性快照需客体 quiesce/agent 与应用配合;失败时不得假定事务整体成功。

# 1. 做危险操作前创建快照
virsh snapshot-create-as win11 --name before-driver-update \
    --description "更新显卡驱动前"

# 2. 执行操作...出问题了

# 3. 还原快照
virsh shutdown win11
virsh snapshot-revert win11 --snapshotname before-driver-update

# 4. 确认没问题后清理快照
virsh snapshot-delete win11 --snapshotname before-driver-update

2.6 控制台与交互

命令 说明
virsh console <domain> 连接 VM 串口控制台(按 Ctrl+] 退出)
virsh console --force <domain> 强制连接(即使已有连接)
virsh send-key <domain> <keycode> 向 VM 发送按键(如 KEY_LEFTCTRL KEY_LEFTALT KEY_DELETE)
virsh qemu-monitor-command <domain> --hmp <cmd> 直接发送 QEMU monitor 命令(高级)
virsh qemu-agent-command <domain> <cmd> 通过 QEMU Guest Agent 发送命令
virsh domfsinfo <domain> 通过 guest agent 获取 VM 内文件系统信息
virsh domifaddr <domain> 通过 guest agent 获取 VM IP 地址
# 获取 VM 的 IP 地址(需安装 qemu-guest-agent)
virsh domifaddr --source agent ubuntu-server

# 向 Windows VM 发送 Ctrl+Alt+Del
virsh send-key win11 KEY_LEFTCTRL KEY_LEFTALT KEY_DELETE

2.7 其他常用命令

命令 说明
virsh uri 显示当前连接 URI
virsh version 显示 libvirt 和 hypervisor 版本
virsh sysinfo 显示宿主机 SMBIOS 信息
virsh capabilities 显示宿主机虚拟化能力(支持的特性、模拟器)
virsh hostname 显示宿主机名
virsh maxvcpus 查询 hypervisor 支持的最大 vCPU
virsh cpu-models <arch> 列出可用 CPU 模型名
virsh domcapabilities 查看 VM 的虚拟化能力
virsh event --all --loop 监听所有 libvirt 事件流(脚本监控用)
virsh desc <domain> 查看/设置 VM 描述文本

3. XML Domain 配置精要#

libvirt 以 XML 作为 VM 配置的单一事实来源。理解 domain XML 结构是掌握 libvirt 的关键。

3.1 XML 顶层结构

<domain type='kvm'>
  <name>demo-vm</name>                        <!-- VM 名称 -->
  <!-- 首次 define 时省略 UUID,由 libvirt 生成;更新现有 VM 则保留其 UUID。 -->
  <title>My Demo VM</title>                    <!-- 可选:可读标题 -->

  <memory unit='GiB'>8</memory>               <!-- 启动时的最大内存 -->
  <currentMemory unit='GiB'>4</currentMemory> <!-- 当前实际分配的内存 -->
  <vcpu placement='static'>4</vcpu>            <!-- vCPU 数量 -->

  <os>...</os>           <!-- 启动/固件 -->
  <features>...</features>   <!-- 虚拟化特性 -->
  <cpu>...</cpu>          <!-- CPU 模型与拓扑 -->
  <clock>...</clock>      <!-- 时钟配置 -->
  <on_poweroff>...</on_poweroff>  <!-- 关机行为 -->
  <on_reboot>...</on_reboot>      <!-- 重启行为 -->
  <on_crash>...</on_crash>        <!-- 崩溃行为 -->
  <devices>...</devices>  <!-- 所有虚拟设备 -->
</domain>

3.2 关键 XML 元素详解

CPU 配置

各片段是独立示例。topology 的 sockets × dies × cores × threads 要与 vCPU 总数一致。host-model 不保证异构主机热迁移兼容;迁移要验证共同 CPU baseline、机器类型、QEMU/libvirt、固件与设备支持。

<!-- 方案 1: host-passthrough —— 尽量暴露宿主CPU特性;性能与迁移须实测 -->
<!-- 适合:同型号 CPU 集群,不需迁移 -->
<cpu mode='host-passthrough' check='none'>
  <topology sockets='1' dies='1' cores='4' threads='2'/>
</cpu>

<!-- 方案 2: host-model —— 兼容性好,可近迁移 -->
<!-- 适合:同架构但不同型号 CPU 间迁移 -->
<cpu mode='host-model' check='partial'>
  <topology sockets='1' dies='1' cores='4' threads='2'/>
</cpu>

<!-- 方案 3: 指定 CPU 模型 —— 最大兼容性,支持跨集群迁移 -->
<!-- 适合:异构集群统一运行时 -->
<cpu mode='custom' match='exact' check='full'>
  <model fallback='forbid'>EPYC-Milan</model>
  <topology sockets='1' cores='4' threads='2'/>
</cpu>

选择策略:单机不做迁移选 host-passthrough;同架构集群选 host-model;异构集群选 custom + 厂商模型。NixOS 用户默认使用 host-passthrough。

磁盘配置

cache 控制页缓存与写确认语义,io 选择 I/O 后端;性能与断电一致性还取决于客体 flush、宿主文件系统和存储。unsafe 忽略 flush,不适合需要持久性的工作负载。块设备源必须通过稳定的 /dev/disk/by-id/<DISK_ID> 与容量确认,误选会直接影响真实磁盘。

<!-- virtio 磁盘 (推荐,性能最佳) -->
<disk type='file' device='disk'>
  <driver name='qemu' type='qcow2' cache='writeback' discard='unmap'/>
  <source file='/var/lib/libvirt/images/vm-disk.qcow2'/>
  <target dev='vda' bus='virtio'/>
  <address type='pci' domain='0x0000' bus='0x04' slot='0x00' function='0x0'/>
</disk>

<!-- 原始块设备 (LVM / ZFS zvol) -->
<disk type='block' device='disk'>
  <driver name='qemu' type='raw' cache='none' io='native'/>
  <source dev='/dev/vg0/vm-disk'/>
  <target dev='vdb' bus='virtio'/>
</disk>

<!-- CD-ROM (ISO) -->
<disk type='file' device='cdrom'>
  <driver name='qemu' type='raw'/>
  <source file='/var/lib/libvirt/images/ubuntu-24.04.iso'/>
  <target dev='sdc' bus='sata'/>
  <readonly/>
</disk>

disk driver 关键属性:

属性 可选值 说明
type raw, qcow2, vmdk 镜像格式
cache none, writeback, writethrough, directsync, unsafe 缓存策略
discard unmap, ignore TRIM/DISCARD 支持(unmap 动态回收空间)
io threads, native I/O 模式(raw 块设备选 native)
detect_zeroes on, off, unmap 零块检测

网络配置

<!-- 方式 1: NAT 虚拟网络 (最常用) -->
<interface type='network'>
  <source network='default'/>
  <model type='virtio'/>
  <!-- 未指定 MAC,由 libvirt 生成;迁移现有 VM 应保留其地址。 -->
</interface>

<!-- 方式 2: Bridge 桥接 (VM 与宿主机同级) -->
<interface type='bridge'>
  <source bridge='br0'/>
  <model type='virtio'/>
</interface>

<!-- 方式 3: Macvtap (直通物理网卡,不需宿主机 bridge) -->
<interface type='direct'>
  <source dev='enp3s0' mode='bridge'/>
  <model type='virtio'/>
</interface>

网络模型对比:

模型 说明 性能 场景
virtio 半虚拟化网卡 最高 Linux/BSD VM(需驱动)
e1000e Intel 千兆网卡模拟 中 Windows VM 无 virtio 驱动
rtl8139 Realtek 百兆网卡模拟 低 兼容性兜底

推荐:Linux VM 一律用 virtio(<model type='virtio'/>);Windows VM 装了 virtio-win 驱动后也用 virtio。

显卡与显示

<!-- SPICE (推荐, 更丰富的显示功能) -->
<graphics type='spice' autoport='yes' listen='127.0.0.1'>
  <listen type='address' address='127.0.0.1'/>
  <image compression='auto_glz'/>
  <gl enable='no'/>
</graphics>
<video>
  <model type='virtio' heads='1' primary='yes'>
    <acceleration accel3d='no'/>
  </model>
</video>

<!-- VNC (更简单, 但功能少) -->
<graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1'>
  <listen type='address' address='127.0.0.1'/>
</graphics>
<video>
  <model type='qxl' ram='65536' vram='65536' vgamem='16384' heads='1'/>
</video>

SPICE vs VNC:

维度 SPICE VNC
双向剪贴板 支持 手动
音频传输 内置 需额外配置
USB 重定向 原生支持 不支持
视频流畅度 更好(自适应压缩) 一般
客户端 virt-viewer / spicy 任何 VNC 客户端

UEFI 启动配置 (Windows 11 必需)

<os firmware='efi'>
  <type arch='x86_64' machine='q35'>hvm</type>
  <loader readonly='yes' type='pflash'>/usr/share/edk2/x64/OVMF_CODE.fd</loader>
  <nvram template='/usr/share/edk2/x64/OVMF_VARS.fd'>
    /var/lib/libvirt/qemu/nvram/win11_VARS.fd
  </nvram>
  <boot dev='hd'/>
</os>

<features>
  <acpi/>
  <apic/>
  <hyperv mode='custom'>
    <!-- 启用 Hyper-V enlightenments 加速 Windows -->
  </hyperv>
</features>

<!-- TPM 2.0 (Windows 11 要求) -->
<tpm model='tpm-crb'>
  <backend type='emulator' version='2.0'/>
</tpm>

3.3 XML 编辑技巧

  1. 永远用 virsh edit <domain> 而非直接编辑文件。virsh edit 会在退出时校验 XML,格式错误会被拒绝保存。

  2. 编辑持久定义先导出 inactive XML,无需先 destroy/undefine:

    virsh -c qemu:///system dumpxml --inactive win11 > win11-new.xml
    # 编辑文件;保留现有 UUID、磁盘、NVRAM 和设备身份
    virt-xml-validate win11-new.xml
    virsh -c qemu:///system define win11-new.xml

    define 更新持久定义;已运行实例不会自动获得所有修改。需要分别选择 live/config 热插拔或安排正常重启。

  3. 修改后无需重启:部分设备(如磁盘、网卡)支持热插拔,可用 virsh attach-device / virsh detach-device 在线生效。

  4. XML 查询与校验:

    # 使用 virt-xml 查询/修改单个属性(比编辑整份 XML 更安全)
    virt-xml win11 --edit --memory maxMemory=8192,currentMemory=4096
    
    # 校验 XML 语法
    virt-xml-validate win11-domain.xml

4. 常用管理脚本#

4.1 备份 VM

以下仅演示离线、文件磁盘备份。先正常关闭 VM,确认所有写入者都已停止;内部快照或“先拍一张快照”并不能让对正在变化磁盘的普通 cp 自动一致。在线备份应使用 libvirt backup/block 作业并核对应用一致性与完整链。

#!/usr/bin/env bash
set -euo pipefail
DOMAIN="${1:?provide domain name}"
BACKUP_DIR="/path/to/backup/vms/${DOMAIN}/$(date +%F-%H%M%S)"
URI="qemu:///system"
state=$(LC_ALL=C virsh -c "$URI" domstate "$DOMAIN")
[[ "$state" == "shut off" ]] || { echo "Guest must be shut off" >&2; exit 1; }
mkdir -p "$BACKUP_DIR"
virsh -c "$URI" dumpxml --inactive "$DOMAIN" > "$BACKUP_DIR/domain.xml"
virsh -c "$URI" domblklist --inactive "$DOMAIN" --details

# 根据 XML 和 domblklist 人工核对所有 disk 源;示例只列一块文件磁盘。
# 路径、格式、空间、权限必须确认;多盘 VM 对每块盘重复并生成恢复清单。
qemu-img info --backing-chain /path/to/vm/disk.qcow2
qemu-img convert -f qcow2 -O qcow2 /path/to/vm/disk.qcow2 "$BACKUP_DIR/disk.qcow2"
qemu-img check "$BACKUP_DIR/disk.qcow2"
echo "Backup saved to: $BACKUP_DIR"

convert 将选定链拍平到独立镜像,但 XML 仍指向原路径,恢复时需在副本 XML 中更新路径并检查 UUID、MAC、权限。另行备份 UEFI NVRAM、软件 TPM 状态、libvirt secrets 引用对应的安全恢复资料和磁盘加密恢复密钥;不要将真实密钥写进公开 XML 或日志。块设备、RBD、LVM 等后端应采用相应一致性备份流程。验证恢复副本时使用隔离网络,避免与原 VM 身份冲突。

4.2 批量查看所有 VM IP

#!/bin/bash
# show-vm-ips.sh — 显示所有运行中 VM 的 IP(需 guest agent)

for vm in $(virsh list --name); do
  ip=$(virsh domifaddr --source agent "$vm" 2>/dev/null \
    | awk 'NR>2 {print $4}' | cut -d'/' -f1 | head -1)
  printf "%-20s %s\n" "$vm" "${ip:-No agent}"
done

4.3 创建 VM 完整命令

# virt-install 一行创建 VM
virt-install --connect qemu:///system \
  --name ubuntu-server \
  --ram 4096 \
  --vcpus 4 \
  --disk path=/var/lib/libvirt/images/ubuntu-server.qcow2,size=40,format=qcow2 \
  --os-variant ubuntu24.04 \
  --network network=default \
  --graphics spice \
  --console pty,target_type=serial \
  --cdrom /var/lib/libvirt/images/ubuntu-24.04-live-server-amd64.iso \
  --boot uefi \
  --autostart \
  --noautoconsole

--os-variant 不是装饰品:它影响默认磁盘总线、网卡型号、USB 控制器等默认值,建议精确匹配。

4.4 克隆 VM

克隆前确认源 VM 停止,目标文件不存在且空间足够。--auto-clone 可自动选择名称/存储,或像本例显式使用 --file;不要混合两种意图。克隆需调整客户机 hostname、网络、machine-id、SSH host keys 等身份;virt-sysprep 只操作离线副本。UEFI/TPM 和直通设备需要单独处理。

# 克隆 VM
virt-clone \
  --original ubuntu-server \
  --name ubuntu-test \
  --file /var/lib/libvirt/images/ubuntu-test.qcow2

运维口诀

  • 关机:先 shutdown 并检查 domstate;超时按应用恢复计划决定是否强制断电
  • 编辑:永远 virsh edit,不直接改文件
  • 备份:持久 XML + 一致的完整磁盘 + NVRAM/TPM 等外部状态,并验证恢复
  • 快照:按后端支持和恢复目标选择 internal/external;核对完整链,不能代替备份
  • 监控:virt-top 看实时,domstats 做采集,event 做告警

下一步 virsh 是力量,但 GUI 也可爱。下一章 virt-manager 图形化管理 介绍如何用图形界面创建 VM、SPICE 远程连接、快照快照和硬件面板操作——比你想象的好用得多。



参考与延伸

  1. virsh 命令参考 ↗
  2. Domain XML ↗
  3. Snapshot XML ↗
  4. QEMU 离线镜像工具 ↗
  5. libvirt backup API ↗

根据技术笔记重新整理,示例使用通用名称。

沿专题继续阅读

KVM 宿主与管理基础

  1. 01KVM、QEMU 与 libvirt 的职责边界
  2. 02KVM 宿主安装、权限与网络准备
  3. 03用 virsh 管理域、存储、网络与恢复
  4. 04virt-manager 创建、硬件面板与远程控制
CONTINUE READING / 下一篇virt-manager 创建、硬件面板与远程控制

将 GUI 创建向导、设备设置和远程显示对应到实际 domain 配置与认证条件。