news 2026/10/2 2:53:31

KVM虚拟化快照管理:virsh命令从创建到回滚的完整指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
KVM虚拟化快照管理:virsh命令从创建到回滚的完整指南

KVM虚拟化环境里,快照这个功能平时不起眼,等哪天真把一台虚拟机搞到起不来的时候,你才会意识到它有多救命。我用virsh这套命令行管理KVM快照好几年了,从最初给测试机打快照练手,到后来在生产环境升级内核、装补丁、调数据库参数之前都习惯性地留一个快照,可以说它已经成了我肌肉记忆里的标准动作。这篇文章直接把virsh快照从创建、查看、回滚到删除的完整命令链讲清楚,同时把底层机制和踩坑实录一起放出来,适合刚接手KVM环境的新手,也适合已经用了virsh一段时间但没仔细研究过快照原理的运维老手。

我先把结论放在这里:virsh快照本身不复杂,复杂的是搞清楚内部快照、外部快照、磁盘快照、系统快照这几组概念之间的关系,以及哪些场景不能直接用默认命令。下面我按"原理→实操→排错"的顺序逐个讲。

1. 快照是什么,为什么说它是KVM运维的保命符

一开始先说清楚:KVM快照就是在某个时间点给虚拟机"拍一张照片",把当时的磁盘状态(甚至可以连同内存状态)完整保存下来。之后不管你对系统做了什么改动,只要想回到那个时间点,一条virsh snapshot-revert命令就能把虚拟机整个拉回去。这个能力在日常运维里的价值,怎么强调都不过分。

我举个自己踩过的例子。有一回给一台跑着生产业务的CentOS虚拟机升级内核,按理说升级内核这种事很常规,结果那台机器正好赶上内核与某张网卡驱动不兼容,重启之后网络直接起不来。当时如果手里没有快照,就得进机房挂ISO、进单用户模式折腾半天,业务停机时间至少按小时算。幸好我在升级前用virsh snapshot-create-as留了个快照,发现不对之后一条revert命令,两分钟内系统恢复到升级前的状态,业务照常跑。从那以后我定了个规矩:凡是给虚拟机做大版本升级、改内核参数、动数据库配置、批量更新软件包之前,一律先留快照。

快照适合谁来用?只要你的KVM环境使用qcow2镜像,都建议掌握。做虚拟机模板打包的、给客户交付测试环境的、搞自动化运维的,这些都是快照的高频使用场景。甚至在学校机房或实验室里,老师用快照给学生准备一套干净的实验环境,学生随便折腾,下课一条命令还原,也是常见玩法。

2. virsh快照体系的底层逻辑

2.1 磁盘快照与系统快照的区别

libvirt对快照的划分很清晰。磁盘快照(disk snapshot)只保存虚拟机虚拟磁盘在某一时刻的状态,不含内存数据。系统快照(system snapshot)在磁盘快照的基础上,还会把虚拟机当时的内存状态、CPU寄存器状态、设备状态一起保存下来。

这两种快照的使用场景完全不同。磁盘快照用来"恢复数据",比如你在文件系统层面做了错误的修改,回滚磁盘快照就能让文件系统回到过去的状态。系统快照则更接近"挂起恢复"的效果,它连当时正在运行的程序、未保存的临时数据、内存里的缓存都能还原。如果虚拟机里跑着重要的服务,你想在某个业务低谷点留一个"运行中状态"的完整备份,系统快照更合适。

有个细节必须提前说明:创建系统快照需要把内存状态写到磁盘上,这一步对虚拟机的运行会产生短暂影响,libvirt会短暂暂停虚拟机来获取一致的内存镜像。生产环境对业务连续性要求极高的话,建议使用--live参数配合创建,或者干脆只做磁盘快照,把影响降到最低。

2.2 内部快照与外部快照的实现差异

这一组概念很多人容易混淆。内部快照(internal snapshot)的数据保存在qcow2镜像文件内部,快照和原始数据共用一个文件;外部快照(external snapshot)则是把快照状态放到一个独立的新镜像文件里,原来的磁盘文件变成只读的基底(backing file),新产生的写入全部进入新文件。

内部快照的好处是管理简单,virsh snapshot-list就能直接看到,一条命令就能创建和删除,不需要关心附加文件。缺点是快照和原文件绑死在一起,一旦qcow2文件损坏,所有内部快照跟着一起报废。而且内部快照数量一多,文件体量增长很快,每个快照都会占用文件头部和写入区域的空间,整盘性能也会逐渐劣化。

外部快照的好处是快照链清晰、便于做增量备份,也适合配合其他存储手段做更精细的管理。但libvirt对外部快照的回滚支持有限制,不能像内部快照那样随意在快照点之间来回跳。常规做法是通过blockcommit或者blockpull命令把外部快照合并回基底文件,过程比较绕。对于大多数中小环境的日常运维,我建议先用好内部快照,等你对镜像链的管理很熟了再碰外部快照。

我把两组概念整理成一个对比表,方便大家一眼看清差异:

对比项磁盘快照系统快照内部快照外部快照
保存内容仅磁盘状态磁盘+内存+设备状态位于qcow2文件内部独立的新镜像文件
管理复杂度低中低高
回滚便利性高较高(需匹配运行状态)高受限,需块合成
数据安全性--与源文件共存,同生共死独立文件,相对安全
性能影响小创建时有短暂暂停快照多时明显链式影响,可配合策略管理

2.3 qcow2镜像格式是快照的地基

快照能不能做、做成什么形式,最终由磁盘镜像格式说了算。raw格式是完全裸的磁盘数据,不支持内部快照;qcow2格式因为天生设计了快照相关的元数据结构,才是内部快照的正统载体。

判断一台虚拟机能不能做内部快照,先看它的磁盘文件格式:

qemu-img info /var/lib/libvirt/images/web01.qcow2

如果输出里image format显示raw,那就别指望virsh snapshot-create能成功,得先把raw转成qcow2再做快照。转换要在虚拟机关机状态下进行:

qemu-img convert -f raw -O qcow2 /var/lib/libvirt/images/web01.img \ /var/lib/libvirt/images/web01.qcow2 virsh edit web01 # 修改disk段,把source file和driver type改成qcow2

这是最基础、也最容易被人忽略的前置条件。我见过不止一个同事拿着raw格式的盘直接敲快照命令,报错之后一脸茫然地问我为什么创建失败。先把格式搞对,后面的路才顺。

3. 快照管理实操:从创建到回滚的核心命令

3.1 创建快照:snapshot-create-as的参数选择

创建快照有两条命令:snapshot-create和snapshot-create-as。前者不指定名称,libvirt自动生成;后者可以自己命名,并且支持携带描述信息。生产环境中强烈建议用snapshot-create-as,一个可读的名称和一段清楚的描述,在几周之后回看时能省掉大量回忆时间。

最基本的创建方式是:

virsh snapshot-create-as web01 web01-before-kernel-upgrade \ --description "2025-06-01 内核升级前快照,含内存状态"

如果你的虚拟机正在运行,又没有加任何额外参数,libvirt会尝试做一个系统快照,也就是把内存状态一并保存。如果再补上--live参数:

virsh snapshot-create-as web01 web01-before-kernel-upgrade \ --description "升级前快照" --live

--live的存在是为了保证虚拟机在快照过程中不中断业务,磁盘和内存快照尽量一致。不加--live时,为了拿到一致的内存状态,虚拟机可能会被短暂暂停,体现在业务侧就是瞬时卡顿。

如果只想保存磁盘状态、不碰内存,使用--disk-only:

virsh snapshot-create-as web01 web01-before-config-change \ --description "只做磁盘快照" --disk-only --atomic

--disk-only快照默认是外部快照,它不会碰内存,速度快得多。--atomic的含义是让所有磁盘要么全部完成快照、要么一个都不做,不会出现某个磁盘快照成功、另一个失败的中间态。注意,--disk-only搭配--quiesce可以调用qemu-guest-agent先把文件系统刷到一个一致的状态,这个对跑数据库的虚拟机特别重要:

virsh snapshot-create-as db01 db01-before-schema-change \ --disk-only --quiesce --atomic

--quiesce生效的前提是虚拟机里安装了qemu-guest-agent,并且agent正常运行。agent的作用等于告诉操作系统"把脏页和缓存都写回磁盘",这样拍出来的磁盘快照才不会在恢复时出现文件系统不一致的问题。没有安装agent的Windows虚拟机尤其要注意,强行用--quiesce大概率会因为agent不响应而失败。

3.2 查看快照:snapshot-list与snapshot-info

快照建好之后,第一件事是确认它真的存在,并且记录了正确的时间点。列出快照用:

virsh snapshot-list web01

输出里有一列名称、创建时间和状态。状态这个字段值得多说一句:如果显示running,说明这个快照是在虚拟机运行状态下拍的;如果显示shutoff,则是关机状态拍的。这一点直接决定了后续回滚时虚拟机的状态行为。

想进一步看某个快照的细节,用snapshot-info:

virsh snapshot-info web01 web01-before-kernel-upgrade

它会显示名称、域状态、是否包含内存状态、磁盘状态等字段。其中"包含内存状态"那一项是判断该快照能否"原样恢复运行现场"的关键。生产环境排障时,我最习惯把snapshot-list和snapshot-info搭配使用,先列全貌,再看关键快照的类型。

如果要导出某个快照的详细XML配置,比如为了复制一个快照到别的环境,可以用snapshot-dumpxml。这条命令平时用得少,但一旦涉及用libvirt API做自动化快照管理,它就是最关键的调试工具。

3.3 回滚快照:snapshot-revert的使用要点

回滚是整个快照体系里最需要谨慎对待的操作,因为它直接覆盖当前状态。命令本身很简单:

virsh snapshot-revert web01 web01-before-kernel-upgrade

但回滚的语义有几种情况,必须区分清楚。如果快照包含内存状态、且虚拟机当前正在运行,回滚时libvirt会把虚拟机的运行状态整体切回快照时刻,包括内存里的进程状态都会恢复,效果很像从休眠中唤醒。如果快照只包含磁盘状态、虚拟机正在运行,libvirt会重启虚拟机来应用磁盘回滚。如果你的虚拟机正处于关闭状态,回滚磁盘快照是最干净利落的,直接改磁盘数据,下次开机即生效。

这里有个我必须反复强调的坑:回滚会丢掉当前磁盘上的所有变更。假设你一周前做了快照,这周业务产生了一大批新数据,在不做任何备份的情况下revert,这些新数据瞬间全部消失。所以在回滚之前,想清楚这周的数据要不要保留,要的话先把需要的文件复制出来,或者先做一个新的快照。

另外,外部快照存在时,回滚不是一句revert就能搞定的。libvirt对"回滚到外部快照链中的某个非当前节点"支持有限,我在实践中遇到的情况是,要先确认当前快照节点,必要时通过blockcommit把覆盖层合并或者用blockpull拉取数据,再执行回滚。这部分内容比较深,建议在测试环境先完整演练一遍,别在生产上临场摸索。

3.4 删除快照:snapshot-delete的常见姿势

时间久了快照会积累很多,该清理就要清理。最基本的删除命令:

virsh snapshot-delete web01 web01-before-kernel-upgrade

这条命令会同时删掉快照的元数据和内部快照对应的磁盘数据。如果你的qcow2文件很大,删除内部快照时会明显感觉到文件体积变化,这是正常的。

需要小心的情况有两个。一是快照之间存在父子关系,如果只删父快照不删子快照,系统会提示还有child snapshot存在,这时加--children可以连同子孙快照一起删除:

virsh snapshot-delete web01 web01-before-kernel-upgrade --children

如果你只想删子快照、保留父快照,则用--children-only。二是只想保留数据、不要元数据的时候,用--metadata参数。这个参数会保留快照记录对应的数据块,但把virsh管理层面的元数据删掉。常用的场景是磁盘文件已经被外部工具合并过了,libvirt里的快照记录变成了无效残留,此时用--metadata把它们清掉即可。

删除前想清楚,快照一旦删除,那个时间点的状态就再也找不回来了。

3.5 一个完整的快照生命周期示例

把前面的命令串成一个完整流程,方便直接抄作业。假设有一台名为web01的虚拟机,磁盘格式是qcow2,跑着nginx服务。

第一步,确认磁盘格式和虚拟机状态:

qemu-img info /var/lib/libvirt/images/web01.qcow2 virsh list --all

第二步,升级前创建磁盘快照,使用--disk-only加--quiesce:

virsh snapshot-create-as web01 web01-before-upgrade \ --description "nginx 1.24升级前快照" \ --disk-only --quiesce --atomic

第三步,确认快照生成:

virsh snapshot-list web01 virsh snapshot-info web01 web01-before-upgrade

第四步,正式升级,这里可以是yum upgrade,也可以是跑维护脚本。升级之后如果发现系统异常,执行回滚:

virsh snapshot-revert web01 web01-before-upgrade

第五步,业务验证通过后,清理掉不再需要的快照:

virsh snapshot-delete web01 web01-before-upgrade

这套流程我已经跑了无数遍,稳定可靠。唯一要提醒的是,如果--quiesce没有生效(比如agent没装),建议在打快照前先把nginx或数据库的写操作停掉十几秒,人工保证一致性。

4. 常见问题与排查实录

4.1 快照创建失败:raw格式磁盘不支持

这是出现频率最高的问题。报错信息通常长这样:

error: internal error: unable to execute QEMU command 'blockdev-snapshot-sync': The node has no device and no backing file

很多人第一反应是排查权限或者存储空间,实际上最简单的一步就是先看磁盘格式:

qemu-img info /var/lib/libvirt/images/web01.img

如果显示file format: raw,结论就很明确:内部快照做不了。解决办法有两个,一是把raw转成qcow2,二是改用外部快照(--disk-only默认就是外部快照)。考虑到后续管理复杂度,我更推荐转qcow2,一次性把基础打牢。

4.2 虚拟机处于关机状态,却要创建带内存的快照

如果虚拟机处于shut off状态,你执行snapshot-create-as并期望带上内存状态,是注定要失败的,因为你根本没有运行中的内存可拍。此时的快照只能包含磁盘状态,命令加上--disk-only就好。反过来,如果你想创建一个完整系统快照,要保证虚拟机处于运行状态。

这个坑在自动化脚本里特别常见。很多人写了个定时任务打快照,却忘了判断虚拟机的运行状态,导致部分任务静默失败。我的建议是脚本里先执行virsh list --all判断state,再决定快照参数。

4.3 --quiesce报错:qemu guest agent没有响应

报错信息类似:

error: Requested operation is not valid: QEMU guest agent is not responding. QEMU snapshot may not be consistent

原因不外乎三种:agent没装、agent服务没启动、agent版本与libvirt不兼容。排查方法很直接,进入虚拟机检查agent进程和服务状态:

systemctl status qemu-guest-agent

确认agent正常后,再检查监听socket是否就绪。另外,Windows虚拟机记得安装对应版本的QEMU guest agent,并且服务要设为自动启动。如果你实在不想折腾agent,退而求其次,在打快照前手动停掉数据库或者执行sync,也能达到基本一致的效果。

4.4 回滚后虚拟机网络或服务异常

快照回滚成功不等于业务正常。最常见的情况是回滚后网络配置、主机名、密钥等出现错位。原因通常是快照时间和当前时间跨度过大,期间别的管理工具或人为改动引入了新的配置,回滚把旧配置带回来了。

排查思路是这样的:先看虚拟机的控制台,确认系统能正常登录;再看网卡状态和网络连通性;然后看关键服务日志,比如journalctl -xe或者对应应用的错误日志。如果发现回滚后的状态不理想,而你回滚前又留过新快照,可以再revert回去。这也是我前面强调"回滚前先做新快照"的原因,进可攻退可守。

4.5 快照太多导致qcow2文件膨胀和性能下降

内部快照每增加一个,qcow2文件头部就会增加元数据,同时快照间的差异数据全挤在同一个文件里。快照数量超过十个以后,你会发现文件占用比预期大很多,虚拟机磁盘写入也可能变慢。这属于qcow2内部快照的固有特性,目前没有银弹。

我的处理习惯是严格控制快照数量,最长保留时间不超过一到两周,过期的及时删除。确实需要长期保留多个还原点时,优先考虑外部快照加特定备份方案,而不是把所有还原点都压在一个文件里。性能敏感的生产虚拟机,我甚至建议干脆不用内部快照,用定期rsync加备份工具的组合来替代。

4.6 不同宿主之间迁移虚拟机时快照丢失

这个坑比较隐蔽。有些朋友把qcow2文件从一个宿主机拷贝到另一个宿主机,然后在新宿主机上virsh snapshot-list一看,发现快照全没了。原因是快照元数据同时存在于两个地方:一部分在qcow2文件内部,另一部分在libvirt的本地配置里(/var/lib/libvirt/qemu/snapshot/目录下)。直接拷贝qcow2文件,镜像内的数据跟着走了,但libvirt侧的迁移快照定义没有跟着走。

解决办法是把整个虚拟机的定义和快照定义一起导出。用virsh dumpxml导出虚拟机XML,同时把快照的XML也用snapshot-dumpxml逐个导出。迁移到新宿主机后,先定义虚拟机,再用snapshot-create的--xml选项重建快照元数据。流程不复杂,但初次接触的人很容易踩进去。

我把这六个问题整理成速查表,方便大家按症状快速定位:

症状大概率原因快速处理
快照创建失败,报node/backing file错误磁盘是raw格式转qcow2或改用外部快照
关机状态创建内存快照失败虚拟机没在运行加--disk-only或先开机
--quiesce报agent不响应未装或未启动agent安装/启动agent,或手动sync
回滚后网络/服务异常快照跨越时间太长,配置漂移查控制台、网卡、服务日志
qcow2文件膨胀、写入变慢内部快照过多及时清理,控制快照数量
迁移宿主机后快照消失只拷贝了qcow2,没迁移元数据dumpxml导出定义,再重建快照

5. 我的一些实操心得和建议

讲了这么多命令和排错,最后聊几句软性的东西。快照本质上是一种"后悔药",但它不是备份,这两件事不冲突。真正重要的数据,还是要靠完整备份策略来保障。快照更适合应对短期内的操作失误,而不是作为数据安全的最后一道防线。备份是否完好、能否恢复,需要单独验证,这个意识最好从用快照第一天就开始建立。

还有一个心态上的建议:打快照这件事,成本低收益高,但前提是要养成习惯。不要只在系统升级这种大动作前才想起它,改负载均衡配置、调防火墙规则、甚至批量改文件权限之前,顺手打一个快照,代价可能只有几秒钟,关键时刻能救回来的东西却可能是整个业务。

最后分享一个小技巧,我一直用它来降低误操作风险。给快照命名时,把用途和日期都写进名字里,比如web01-before-upgrade-20250601。回滚前先执行snapshot-list看清楚快照名称,再执行revert,并且revert之前手动再打一个新快照作为"后悔药的后悔药"。这两步看起来多余,但我用它们避免过不止一次生产事故。快照管理说白了就一句话:随手留一手,回滚前再留一手,稳得很。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/2 2:52:24

Ubuntu忘记root密码?恢复模式与init=/bin/bash破解指南

凌晨两点,你刚在服务器上改完sshd配置,手一抖把会话断了,重新登录却发现密码怎么输都不对——再一查,root密码好像也被你忘得一干二净。这种时刻我经历过不止一次,我的第一反应曾经是“完了,只能重装系统”…

作者头像 李华
网站建设 2026/10/2 2:52:24

多目标人脸识别毕设实战:Python+深度学习从检测到识别全流程解析

简介:面向毕业设计、课程设计和期末大作业场景的Python深度学习多目标人脸识别项目,以完整可运行源码与逐段注释为核心,新手可对照理解模型加载、特征提取和多目标匹配流程,部署后即可用于人脸检测演示。压缩包共121个文件&#x…

作者头像 李华
网站建设 2026/10/2 2:51:48

SpringBoot集成Skywalking:微服务链路跟踪与无侵入排查实战

如果你也经历过微服务环境下的深夜排查:用户反馈下单慢,你打开三台服务器的日志,先按时间戳对齐,再逐个服务找堆栈,最后还得靠猜“大概是哪个环节”卡住了,那这篇关于SpringBoot集成Skywalking链路跟踪的内…

作者头像 李华
网站建设 2026/10/2 2:51:04

Linux运维必备:LVM逻辑卷管理从入门到生产实战

干运维这几年,磁盘管理和LVM一直是我最常用也最怕出错的两个基本功。尤其是碰到线上服务器磁盘不够用、数据盘要扩容、系统重装要保住数据这些场景,LVM(逻辑卷管理)几乎是绕不开的解决方案。很多人一开始只会fdisk分区、mount挂载…

作者头像 李华
网站建设 2026/10/2 2:50:06

从零配置IDE中的Git:环境准备、SSH认证与高频报错排查全指南

从命令行到图形界面,Git 在 IDE 里的配置其实没你想的那么玄乎。大部分开发者日常工作都离不开 IDE,而 Git 早就成了 IDE 的标配能力,无论是 IntelliJ IDEA、VS Code,还是 Eclipse、Android Studio,开箱就带 Git 集成。…

作者头像 李华
网站建设 2026/10/2 2:49:36

电影院订票系统:SpringBoot+Vue前后端分离实战指南

简介:这是一套面向Java与Vue全栈初学者及课程设计者的电影院订票系统实战源码,聚焦前后端分离架构落地,解决从环境搭建、接口联调到数据库集成的完整开发闭环问题。资源含300个文件,主体为82个Java后端业务与控制器代码、41个Vue组…

作者头像 李华