尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
KVM虚拟机磁盘在线扩容实战:从virsh blockresize到文件系统扩展
1. 开篇为什么你躲不开在线扩容这一刀聊到KVM的磁盘管理可能很多人觉得这就是qemu-img加virsh那点命令的事——创建、挂载、快照顶多再搞个离线resize好像没什么新鲜的。但真到了生产环境你迟早会碰到一个让人头疼的需求虚拟机磁盘满了业务不能停服务不能断你只能在线把磁盘空间撑大。说实话我第一次做在线扩容的时候也踩了不少坑。那时候虚拟机跑着数据库磁盘使用率到了92%监控告警一直在响。我一开始想的还是老办法关机、改磁盘大小、开机、进系统重新分区。结果被值班同事拦下来——那个库是核心业务半夜都不让重启更别说大白天。没办法只能硬着头皮研究在线扩容。这篇文章我就把当时整理出来的完整操作流程、原理和踩坑记录写下来给同样被磁盘空间逼到墙角的兄弟一个参考。这篇是系列的第二篇重点讲“在线扩展”也就是不关机、不中断业务的前提下把KVM虚拟机的磁盘空间撑大。为了方便起见我会以CentOS/RHEL系列的虚拟机为例来讲Win系列的逻辑略有差异但在线扩容的原理是一致的。先说明白一个核心概念KVM的在线扩容不是“一句话”的事它是由“宿主机侧存储调整 虚拟机侧总线刷新 分区表更新 文件系统扩展”四个环节组成的链路。任何一个环节掉了链子结果都可能是宿主机的空间划过去了但虚拟机里面什么也没发生——看起来扩了个寂寞。2. 在线扩容的前置条件与空间准备2.1 不是所有磁盘都能在线扩你得先看清后端格式动手之前第一个问题你这台虚拟机的磁盘到底是什么格式KVM的磁盘后端格式常见的有qcow2、raw、lvm还有比较少见但存在的rbdCeph、glusterfs等。在线扩容的可行性和格式强相关逻辑大概是这样的qcow2可以在线扩容用qemu-img resize或virsh blockresize。qcow2支持“稀疏扩展”也就是扩容后不会立刻占满宿主机空间用多少占多少这点很友好。raw同样可以在线扩容但要注意raw是“实打实”的扩容后宿主机空间会被预留。如果宿主机本身磁盘紧张建议先看下df -h余量再动手。LVM卷宿主机直接把LV作为虚拟机的磁盘。这种情况下你既可以从LV层面扩容也可以在虚拟机里面配合使用LVM形成“存储池LV 虚拟机内LV”的双层结构。在线扩容的痛感小很多因为LVM天生支持在线扩展关键要执行的只是刷新分区和文件系统。rbd/glusterfs属于分布式存储扩容一般走存储侧接口KVM只是“使用方”不在本文讨论范围内但思路类似存储侧扩大/增加后虚拟机侧通过rescan-scsi-bus.sh或virsh blockresize刷新。所以就一句话先确认后端格式再决定用哪条命令。这个确认过程别凭印象务必查看虚拟机的XML定义里的disk段或者直接登录宿主机看对应路径下的文件类型。2.2 宿主机侧空间余量扩容前的硬性检查我知道很多人拿到“磁盘满”的工单第一反应就是在虚拟机上df -h然后开始删日志、清缓存。但做在线扩容是不同的逻辑——你不仅要在虚拟机里有空间宿主机侧同样要有足够空间来容纳后端镜像文件的“增长”。打个比方虚拟机看到的是一个100G的磁盘但实际后端qcow2文件可能只有50G稀疏文件。你打算扩到150G宿主机上至少要有50G以上的可用空间因为扩容动作会往镜像文件里追加数据块。如果是raw格式那就要求更严格了50G必须完全预留出来不存在“以后再说”的空间。这块我的建议是先执行df -h在宿主机上确认存放虚拟机镜像目录的剩余空间。如果剩余空间不足先做宿主机层面的空间清理或者考虑换一块数据盘把镜像迁移过去再扩。别在空间不够的时候强行扩qcow2会写坏元数据raw会直接NO SPACE哪个结果都不好受。还有一个容易忽略的点宿主机是否启用了thin provisioning或使用了ZFS/Btrfs这类支持动态分配的文件系统。如果宿主机文件系统本身快照满了或元数据区不够qemu-img resize也会失败所以扩容前最好连btrfs fi df或zpool list这种关联命令也顺手看一眼。2.3 虚拟机内的空间使用情况别把分区“卡死”在起始位置这一步开始涉及虚拟机内部但很多人容易卡在这。在线扩容的最终目标是“让虚拟机内文件系统变大”而你需要在fdisk -l、lsblk、pvdisplay这几个命令的输出里看清楚两件事虚拟机的磁盘有没有分区表分区是整块盘还是单分区虚拟机内是不是用了LVMPV、VG、LV的层级关系是什么这两个问题的答案决定了后续操作路径。如果虚拟机内是整块盘直接格式化文件系统没有分区表那在线扩容是最简单的宿主机扩容磁盘后虚拟机内执行resize2fs或xfs_growfs直接扩展连分区都不用更新。但如果是严格的分区表结构多数标准安装的系统都是这样那你必须做“分区扩容”这个动作在线情况下依赖growpart或parted这类工具比较麻烦后面我会详细说。还需要特别留意一点分区的起始位置一定不能动。很多人在线扩分区失败就是fdisk交互式操作时不小心改了起始扇区导致文件系统整个挂掉。在线扩容的铁律是只改结束位置绝不碰起始位置。3. 宿主机侧的操作从镜像到虚拟机的空间划拨3.1 三种常用扩容方式对比在宿主机侧向虚拟机磁盘追加空间有三种常见方式。先做一个对比再根据场景选择方式命令适用场景在线与否风险等级直接扩后端镜像qemu-img resizeqcow2/raw格式在线低通过libvirt在线调整virsh blockresize所有libvirt管理的虚拟机在线低宿主机LV扩展lvextend后端是LVM卷在线中需要额外刷新如果你还在用老旧的“关机改xml再开机”的方式请立即忘掉。libvirt早就提供了virsh blockresize这个命令它可以在虚拟机运行时直接调整块设备大小非常便利。3.2 virsh blockresize最稳的在线追加空间方式使用virsh blockresize需要知道两件事虚拟机的名字以及目标磁盘在虚拟机里的target dev一般是vda、vdb、vdc这样的设备名。查看方法virsh dumpxml 虚拟机名 | grep -A 5 disk或者更直接的virsh domblklist 虚拟机名比如输出里有一行是vda /var/lib/libvirt/images/vm1.qcow2那说明磁盘设备的target是vda后端文件路径是/var/lib/libvirt/images/vm1.qcow2。现在要把这台虚拟机的vda从100G扩到150G宿主机执行virsh blockresize 虚拟机名 vda 150G执行完可以用virsh domblklist --details确认新大小或者登录虚拟机内lsblk看设备是否已经变成了150G。这里有个坑要说明virsh blockresize是“宿主机视角”的存储层操作它通知QEMU把块设备的大小调整了但虚拟机内的内核不一定马上注意到这个变化还需要在虚拟机侧刷新设备状态。如果虚拟机内lsblk没变化一个常用办法是用virsh qemu-monitor-command发送热插拔刷新指令或者直接在虚拟机内重新扫描SCSI设备。比较常见的在线刷新命令echo 1 /sys/class/block/vda/device/rescan如果/sys里找不到对应路径也可以安装sg3_utils后用rescan-scsi-bus.sh扫描。总之宿主机通知设备变了但虚拟机内核的“感知”是异步的这一环很容易被刚接触的人忽略。3.3 qemu-img resize不在libvirt管理下的场景有些极简环境不通过libvirt启动QEMU直接用qemu-system-x86_64 -hda disk.img这种方式跑虚拟机那就只能用qemu-img resize了。执行qemu-img resize /var/lib/libvirt/images/vm1.qcow2 150G或者相对增加空间qemu-img resize /var/lib/libvirt/images/vm1.qcow2 50G需要注意qcow2的resize支持“增量”和“绝对大小”两种写法raw也类似。但对于正在运行的虚拟机qemu-img resize必须与QEMU进程协调否则会有竞态问题。所以通常做法是先qemu-img resize然后virsh blockresize同步或者反过来先blockresize再img resize。实际生产中我推荐优先用virsh blockresize因为它是libvirt官方支持的在线路径能处理好和QEMU的协调qemu-img resize更适合虚拟机处于关机状态时的操作。3.4 后端是LVM的扩展路径如果虚拟机的磁盘定义直接指向宿主机的LV比如source file/dev/vg_data/vm1_disk/那么宿主机侧的操作就是标准的LVM扩展lvextend -L 50G /dev/vg_data/vm1_disk执行完lvs查看新的LV大小确认无误后虚拟机内的操作和前面一样需要刷新设备并扩展分区/文件系统。唯一的区别是LVM卷扩展是否在线取决于LV在宿主机层面是否被激活状态对于虚拟机磁盘来说通常它处于活动状态lvextend可以在线执行。但是如果LV上创建了快照或者处于特殊状态需要小心对待。4. 虚拟机内部的回应从内核刷新到分区表调整4.1 让虚拟机感知新容量宿主机侧的操作完成之后登录虚拟机先看lsblk的输出lsblk如果设备大小仍然是老容量说明虚拟机内核还没有识别到新的大小。最常用的无损刷新方式echo 1 /sys/class/block/vda/device/rescan如果不支持这个路径可以执行which rescan-scsi-bus.sh || yum install -y sg3_utils rescan-scsi-bus.sh刷新之后再次执行lsblk正常情况下应该能看到vda已经是150G了。这里有一点要说明刷新后看到的是“磁盘设备”大了但分区和文件系统还是原来的大小所以下一步就是调整分区表。4.2 用growpart安全在线扩分区在线调整分区表最温和、最不容易出错的工具是growpart来自cloud-utils-growpart包。它的作用是把指定分区扩展到磁盘末尾同时保持起始位置不变。yum install -y cloud-utils-growpart growpart /dev/vda 1执行完lsblk应该可以看到vda1分区变大了。如果分区表类型是GPT可能还需要用parted修复一下备份头位置但growpart通常会自动处理如果报错可以用parted /dev/vda print检查。4.3 如果系统里没有growpart用parted处理有些精简版系统没有growpart只能用parted进行resizepart操作。命令如下parted /dev/vda resizepart 1 100%注意parted在线调整分区表依赖内核的支持老的发行版可能不支持在线resizepart需要确认内核版本一般2.6.32以上的RHEL6都支持。操作完同样用lsblk验证。这块真的是我踩过坑的重灾区——在某个RHEL7.2的老环境里parted resizepart报错“无法将分区调整到超出磁盘末尾”一查原因是分区表没刷新先做了一次partprobe才解决。4.4 虚拟机内LVM场景pvresize lvextend 文件系统扩展如果虚拟机内部用的是LVM那在线扩容的路径很清晰先让PV感知新大小再把LV扩展最后扩展文件系统。pvresize /dev/vda1 pvdisplay # 确认PV大小已更新 lvextend -l 100%FREE /dev/mapper/vg_xxx-lv_root这里需要强调先pvresize把PV扩展到分区大小再lvextend把LV扩到整个VG剩余空间顺序不能反。执行完LV扩展后文件系统并不会自动变大还需要额外执行文件系统层的扩展命令具体取决于文件系统类型。5. 文件系统层的最后一步xfs_growfs与resize2fs的那些坑5.1 ext4文件系统resize2fs的用法与限制如果虚拟机内用的是ext4那在线扩展文件系统非常顺畅resize2fs /dev/mapper/vg_xxx-lv_root执行完df -h就能看到文件系统变大了。resize2fs支持在线扩展这是它的优点。但有一点要注意ext4的在线扩容只能扩大不能缩小想缩小只能离线。而且如果在扩容过程中发生了断电或系统崩溃可能会导致文件系统需要fsck所以有条件的话先做快照再操作。5.2 xfs文件系统xfs_growfs与“只能扩不能缩”的铁律RHEL7及以上默认文件系统就是xfs在线扩容的方式完全不同xfs_growfs /mnt注意xfs_growfs的参数是一个挂载点不是设备路径这一点经常有人搞错。如果你传的是设备路径它也能识别但建议还是用挂载点更保险。另外一个和ext4不一样的点是xfs不支持缩小甚至不支持“离线缩小”。所以在给xfs分区做在线扩容之前千万确认分区表扩展的幅度是正确的别扩多了因为扩多了就缩不回来了。我在某次操作中本来想加50G结果分区表那边多划了一点最后只能硬着头皮把LV和文件系统全扩到那个大小。虽然没出事故但那种“没有后悔药”的感觉实在让人紧张。5.3 双文件系统兼容性速查文件系统扩展命令在线扩展在线缩小备注ext4resize2fs支持不支持在线缩小需要先卸载xfsxfs_growfs支持不支持即使离线也不能缩小btrfsbtrfs filesystem resize支持支持需要挂载ntfsntfsresize限Windows环境不支持一般Windows用 diskpart所以进行在线扩容前养成一个习惯先看blkid或/etc/fstab确认文件系统类型。这一步直接决定你用的是resize2fs还是xfs_growfs选错了命令轻则报错重则损坏文件系统。6. 在线扩容全流程复盘与避坑要点6.1 一次完整的在线扩容SOP可抄作业我把上面所有操作整理成一张完整的操作清单按顺序执行。宿主机侧# 1. 确认后端格式与空间余量 virsh domblklist 虚拟机名 df -h # 2. 在线扩容磁盘设备 virsh blockresize 虚拟机名 vda 150G虚拟机侧# 3. 刷新设备让内核感知新容量 echo 1 /sys/class/block/vda/device/rescan lsblk # 4. 扩展分区以第1个分区为例 yum install -y cloud-utils-growpart growpart /dev/vda 1 # 5. 如果用了LVM扩展PV/LV pvresize /dev/vda1 lvextend -l 100%FREE /dev/mapper/vg_xxx-lv_root # 6. 扩展文件系统 resize2fs /dev/mapper/vg_xxx-lv_root # 如果是xfs则改为 xfs_growfs /mnt # 7. 验证 df -h整个流程下来如果每一步都没有报错那恭喜你在线扩容成功了。如果哪一步卡住了参考下一节的排查方案。6.2 那些年我踩过的坑坑1忘了确认文件系统类型。RHEL7默认是xfs但有些只是从RHEL6原地升级上来的系统根分区还是ext4。如果你拿着xfs_growfs去扩ext4会直接报“not a valid XFS filesystem”。所以我现在的习惯是无论多急先执行df -T或blkid确认文件系统类型再动手。坑2growpart报错“unexpected input”。这种情况多半是因为磁盘设备名或分区号和实际情况不对。比如vda上可能有vda1、vda2两个分区而你要扩的是vda2就写growpart /dev/vda 2别只看到“sda”想当然。坑3分区表已扩展但文件系统报错“设备上没有空间”。这是“LV没扩到位”的典型症状。lvextend -l 100%FREE看起来是把所有剩余空间都给了某个LV但如果VG里还有其他LV占用了部分空间那实际能分到的空间并不到你想加的那么多。建议执行顺序改为先pvs看PV再vgs看VG再lvs看LV确认可用空间分布后再决定怎么分。坑4设备刷新失败。有些虚拟化环境比如KVM嵌套虚拟化不支持/sys/class/block/vda/device/rescan直接刷新需要virsh qemu-monitor-command通知QEMU。这种情况也别慌用sg3_utils里的rescan-scsi-bus.sh一般都能搞定。坑5没做快照就操作。虽然在线扩容本身风险不算高但任何对磁盘分区表的修改都有意外可能。有条件的话操作前在宿主机上给qcow2做一个外部快照或临时备份以防万一。我一般这样操作virsh snapshot-create-as 虚拟机名 pre-resize-$(date %Y%m%d) --disk-only --atomic做完扩容并确认无误后再删除这个临时快照。当然业务侧如果有文件系统级快照或数据库备份机制就多一层保险。6.3 在线扩容后还要做什么扩容完成、df -h确认新空间生效不意味着这件事就算结束了。按照我个人的习惯还要做三件事把虚拟机的XML配置文件保存一份记录新的磁盘容量便于后续维护时对比。如果虚拟机内有监控agent比如Telegraf、Zabbix Agent等确认磁盘容量采集正常避免因为文件系统大小变化导致监控误报或漏报。更新资产记录和应用配置。有些应用的JVM堆大小、数据库的innodb_data_file_path是基于磁盘空间估算的磁盘变大后可能要考虑调整这些参数而不是让空间白白空着。尤其是数据库类场景磁盘扩容后如果表空间文件本身没有自动扩展实际可用空间并不会有太大改善。所以在线扩容完成只是“给系统提供了更多空间”具体能利用多少还要看应用层和数据库层的配置。7. 个人心得在线扩容的正确打开方式做了这么多次在线扩容我的感受是真正难的不是命令怎么敲而是流程意识。很多人在宿主机上执行完virsh blockresize就以为大功告成结果虚拟机里一点变化没有就开始怀疑命令是不是没生效。其实整套链路就像接力跑宿主机扩容、内核刷新、分区调整、PV/LV扩展、文件系统扩展每一棒都缺一不可。另一个心得是尽量把业务侧的影响降到最低。虽然叫“在线扩容”不用停机但如果虚拟机磁盘压力已经到100%这时候做分区调整还是会引入额外的IO压力对业务的性能有影响。所以如果条件允许还是建议在业务低峰期操作配合应用的维护窗口来执行而不是监控告警一响就立刻动手。最后说句实在的在线扩容是一把双刃剑。用好了你可以把原本要折腾半小时的停机维护变成5分钟的无感知操作用不好也可能因为一个步骤顺序错了把原本还能用的系统搞到起不来。所以我的建议是不管是新上手还是老手操作前都花5分钟把上面的步骤走一遍脑内预演确认每一步的依赖关系再动手执行。宁可慢一点也别出事故。希望这篇关于KVM在线扩展磁盘的操作经验和踩坑记录对你有帮助。如果你在实操中遇到别的坑或者有其他更“野”的扩容场景欢迎交流。这篇文章由系列第二篇整理而来后续我还会写关于KVM磁盘缩容、跨存储迁移、qcow2快照链压缩等主题敬请关注。
RELATED

相关推荐

Python爬虫实战:抓取豆瓣短评7个字段并分析

Python爬虫实战:抓取豆瓣短评7个字段并分析

1. 为什幺要抓豆瓣短评:一次真实的数据需求做内容分析或者用户调研的时候,短评是特别有信息密度的一类数据。一个普通的短评页,单条评论里就同时藏着用户昵称、地理位置、评分、发布时间、内容、点赞数,把这些字段组合在一起&…

📅 2026/10/14 19:05:21
智能体安全测试指南:从权限边界到逃逸测试的完整实践

智能体安全测试指南:从权限边界到逃逸测试的完整实践

1. 从“能对话”到“能动手”,智能体扩张的不只是能力边界1.1 传统模型输出与智能体动作之间的风险断层过去几年大家做AI安全测试,核心盯着的其实是“模型会不会输出危险内容”。你给模型一个恶意 prompt,模型要么拒绝、要么配合,…

📅 2026/10/14 19:05:21
Qt自助点餐系统开发实战:从触摸界面到断网补单与打印对接

Qt自助点餐系统开发实战:从触摸界面到断网补单与打印对接

简介:QT自助点餐系统是一份面向C与Qt初学者、课程设计及桌面应用开发练习者的完整项目源码,围绕餐饮场景实现菜单浏览、选菜下单与支付等交互流程,帮助读者理解跨平台GUI程序的整体搭建思路。压缩包共23个文件,约23KB,…

📅 2026/10/14 19:05:21
MORE NEWS

更多资讯

📰

字节缓冲区Buffer源码剖析:底层数组、读写偏移与切片引用安全

只看递进到第二层就简单得出README中那个结论,很可能直接被错误引导。下面用一个具体模拟数据演示为什么既有成本差:递进轮次递进前数据是0的占比递进步调仍为0的数据占比一般递进深度预计递进总时长只递进一次90%大步幅80%1位极短块递进,锁定…

📰

VBA开发者转xlwings:对象映射、避坑指南与企业级自动化升级

1. 为什么从VBA转向xlwings不是“重学”,而是“升级”——一个老VBA开发者的真实过渡手记如果你写过三年以上Excel宏,能闭眼敲出Range("A1").Value "测试"、熟练用AutoFilter做数据清洗、靠Application.ScreenUpdating False撑过十…

📰

可执行文件装载与进程:虚拟地址空间和按需调页深度解析

十几年前第一次接触《程序员的自我修养》第六章,我还是个只会把代码写“通”的初学者:能编译、能运行,但一旦被问到“你按下运行之后,操作系统到底对你的可执行文件做了什么”,脑子里基本是一片空白。第六章“可执行文…

📰

全志T153接口能力解析:嵌入式中等带宽通信的‘刚刚好’方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

C# WCF与Web接口开发实战:从配置到跨域调用避坑指南

简介:这份资源面向具备一定.NET基础的开发者,聚焦C#中WCF与Web项目接口开发的实际案例,帮助读者理解如何用服务合同、数据契约与操作契约搭建可调用的分布式服务接口。内容围绕增删改查基础场景展开,涵盖服务定义、数据实体序列化…

📰

Tiptop与Easyflow系统集成避坑指南:从PDF样例到生产落地

简介:本资源是一份面向企业级ERP与OA系统集成工程师的Tiptop与Easyflow单据电子签核专项技术指南,聚焦制造业、流通业等使用Tiptop ERP并需对接Easyflow流程引擎的典型场景。文档系统梳理了从环境配置、数据表校验、AWS模块开发(含公共服务与…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬