命令与 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
done1.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 # 此后不再需要 -c1.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 virtqemud2. 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 win112.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 mapvCPU 分析
| 命令 | 说明 |
|---|---|
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 win112.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-net2.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-update2.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_DELETE2.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 编辑技巧
永远用
virsh edit <domain>而非直接编辑文件。virsh edit会在退出时校验 XML,格式错误会被拒绝保存。编辑持久定义先导出 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.xmldefine 更新持久定义;已运行实例不会自动获得所有修改。需要分别选择 live/config 热插拔或安排正常重启。
修改后无需重启:部分设备(如磁盘、网卡)支持热插拔,可用
virsh attach-device/virsh detach-device在线生效。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}"
done4.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 远程连接、快照快照和硬件面板操作——比你想象的好用得多。
参考与延伸
根据技术笔记重新整理,示例使用通用名称。