KVM虚拟化快照管理:virsh命令从创建到回滚的完整指南
发布时间:2026/10/2 2:53:31 锦皓数字建站

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-onlyvirsh 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-infovirsh 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加--quiescevirsh 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之前手动再打一个新快照作为后悔药的后悔药。这两步看起来多余但我用它们避免过不止一次生产事故。快照管理说白了就一句话随手留一手回滚前再留一手稳得很。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。