添加和动态调整虚拟机数据磁盘
通过组合合适的VM文件系统功能(例如支持在线resize的XFS文件系统)和QEMU底层
virsh qemu-monitor-command指令可以实现在线动态调整虚拟机磁盘容量,无需停机,对维护在线应用非常方便。本文实践在线不停机情况下添加KVM虚拟机磁盘以及在线扩展Linux虚拟机磁盘及文件系统。(Windows扩容虚拟磁盘需要重启vm后识别)本文虚拟机磁盘扩容(resize)部分步骤需要在VM内部使用操作系统命令,所以适合自建自用的测试环境。
生产环境reize虚拟机磁盘系统,可采用libguestfs来修改虚拟机磁盘镜像。
libguestfs可以查看和编辑guest内部文件,脚本化修改VM,监控磁盘使用和空闲状态,以及创建虚拟机,P2V,V2V,以及备份,clone虚拟机,构建虚拟机,格式化磁盘,resize磁盘等等。
快速起步
案例使用的虚拟机名字是
dev7,增加和resize的磁盘文件是dev7-data.img
创建虚拟磁盘文件(qcow2类型)
cd /var/lib/libvirt/images
qemu-img create -f qcow2 dev7-data.img 20G虚拟磁盘文件添加到虚拟机
qemu可以映射物理存储磁盘(/dev/sdb)或虚拟磁盘文件到KVM虚拟机my_vm的虚拟磁盘(vdb),语法如下
virsh attach-disk dev7 --source /var/lib/libvirt/images/dev7-data.img --target vdb --persistent --driver qemu --subdriver qcow2注意:这里一定要指定
--driver qemu --subdriver qcow2,因为libvirtd出于安全因素默认关闭了虚拟磁盘类型自动检测功能,并且默认使用的磁盘格式是raw,如果不指定磁盘驱动类型会导致被识别成raw格式,就会在虚拟机内部看到非常奇怪的极小的磁盘。
(演示动态扩容磁盘文件系统)
在dev7虚拟机内部格式化文件系统和挂载文件系统
mkfs.xfs /dev/vdb
mkdir /data
echo "/dev/vdb                /data                   xfs     defaults        0 0" >> /etc/fstab
mount /data此时在
dev7虚拟机内部df -h /data可以看到输出信息显示磁盘20G
Filesystem      Size  Used Avail Use% Mounted on
/dev/vdb         20G   33M   20G   1% /data检查虚拟设备详细情况
virsh qemu-monitor-command dev7 --hmp "info block"这里可以看到dev7-data.img虚拟磁盘文件对应的块信息
drive-virtio-disk1: removable=0 io-status=ok file=/var/lib/libvirt/images/dev7-data.img ro=0 drv=qcow2 encrypted=0 bps=0 bps_rd=0 bps_wr=0 iops=0 iops_rd=0 iops_wr=0在线修改虚拟磁盘大小
virsh qemu-monitor-command dev7 --hmp "block_resize drive-virtio-disk1 30G"注意:最近我在arch linux上执行上述 info block 命令并没有正确显示出磁盘镜像名称,显示的是类似:
libvirt-3-format: /var/lib/libvirt/images/sles12_data.qcow2 (qcow2)
    Attached to:      /machine/peripheral/virtio-disk1/virtio-backend
    Cache mode:       writeback这导致 block_resize 命令不能针对设备执行。所以我改为直接采用 qemu-img 命令进行resize,类似命令:
sudo qemu-img resize /var/lib/libvirt/images/rhel8.qcow2 +10G在
dev7虚拟机内部
此时在dev7虚拟机内部fdisk -l /dev/vbd可以看到磁盘设备已经增长到30G
在虚拟机内部调整文件系统(XFS可以在线调整挂载磁盘的文件系统大小)
xfs_growfs /data/此时在
dev7虚拟机内部df -h /data可以看到输出信息显示磁盘30G
Filesystem      Size  Used Avail Use% Mounted on
/dev/vdb         30G   33M   30G   1% /dataWindows虚拟机磁盘添加和扩展方法类似,但需要注意处理
virtio驱动以及磁盘resize后需要重启VM操作系统才能识别。详细见下文。
以下是实践过程记录
以下是实践过程记录Linux虚拟机
添加磁盘
检查虚拟机列表
virsh list以下操作针对dev7虚拟机操作
检查虚拟机
dev7的虚拟磁盘设备
virsh qemu-monitor-command dev7 --hmp "info block"
--hmp表示human monitor command,可以直接传入monitor中操作的命令,不需要任何格式转换。如果缺少--hmp,则monitor会认为接收json格式命令,会出现错误,如internal error cannot parse json info kvm: lexical error: invalid char in json text
这里输出显示
drive-virtio-disk0: removable=0 io-status=ok file=/var/lib/libvirt/images/dev7.img ro=0 drv=qcow2 encrypted=0 bps=0 bps_rd=0 bps_wr=0 iops=0 iops_rd=0 iops_wr=0
drive-ide0-0-0: removable=1 locked=0 tray-open=0 io-status=ok [not inserted]创建一个本地的虚拟磁盘文件
cd /var/lib/libvirt/images
qemu-img create -f qcow2 dev7-data.img 20G显示输出(初始文件只有193K)
Formatting 'dev7-data.img', fmt=qcow2 size=10737418240 encryption=off cluster_size=65536 lazy_refcounts=off
警告不要在运行虚拟机所连接的磁盘镜像上使用
qemu-img命令修改镜像,有可能会导致镜像损坏。
检查新创建的磁盘信息
qemu-img info /var/lib/libvirt/images/dev7-data.img这里输出显示
image: /var/lib/libvirt/images/dev7-data.img
file format: qcow2
virtual size: 10G (10737418240 bytes)
disk size: 196K
cluster_size: 65536
Format specific information:
    compat: 1.1
    lazy refcounts: false
qemu-img也支持磁盘格式转换
qemu-img convert -O vmdk /images/sles11sp1.raw /images/sles11sp1.vmdk将磁盘文件映射添加到虚拟机
dev7
virsh attach-disk dev7 --source /var/lib/libvirt/images/dev7-data.img --target vdb --persistent提示
Disk attached successfully检查添加的虚拟磁盘
virsh domblklist dev7 --details显示输出
Type       Device     Target     Source
------------------------------------------------
file       disk       vda        /var/lib/libvirt/images/dev7.img
file       disk       vdb        /var/lib/libvirt/images/dev7-data.img
block      cdrom      hda        -登录到虚拟机
dev7内部检查
fdisk -l /dev/vdb可以看到输出
Disk /dev/vdb: 0 MB, 197120 bytes, 385 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes这里比较奇怪,在虚拟机内部看到的磁盘只有
0 MB, 197120 bytes, 385 sectors,并不是qemu-img create命令创建的10G磁盘。(尝试重启了一次虚拟机也没有解决问题)
在虚拟机内部格式化磁盘文件系统会提示报错 - 因为对虚拟机内部来说这个虚拟磁盘没有可用空间
mkfs.xfs /dev/vdb提示报错
size 48 of data subvolume is too small, minimum 100 blocks但是在物理服务器上可以看到设备文件是10G
file dev7-data.img显示输出
dev7-data.img: QEMU QCOW Image (v3), 10737418240 bytes这个问题困扰了我,直到我通过virsh edit dev7查看这个虚拟机设备配置才发现,原来virsh attach-disk添加磁盘设备时候没有指定磁盘设备类型,被默认添加成raw类型,对比了原虚拟机系统vda设备和vdb设备:
    <disk type='file' device='disk'>
      <driver name='qemu' type='qcow2'/>
      <source file='/var/lib/libvirt/images/dev7.img'/>
      <target dev='vda' bus='virtio'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
    </disk>
    <disk type='file' device='disk'>
      <driver name='qemu' type='raw'/>
      <source file='/var/lib/libvirt/images/dev7-data.img'/>
      <target dev='vdb' bus='virtio'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/>
    </disk>所以重新添加设备
virsh detach-disk dev7 /var/lib/libvirt/images/dev7-data.img --persistent
virsh attach-disk dev7 --source /var/lib/libvirt/images/dev7-data.img --target vdb --persistent --type qcow2但是提示error: unsupported configuration: unknown disk device 'qcow2',似乎不能正确传递--type参数。
我搞错了,不是传递
--type qcow2,而是使用--driver qcow2
检查/etc/libvirt/qemu.conf配置,原来为了安全原因,默认关闭了虚拟机镜像磁盘类型检测,即默认是注释掉 #allow_disk_format_probing = 1,建议通过更新guest XML的<disk>段落配置设置磁盘类型<driver type='XXXX'/>。
这里测试环境适当放低安全限制,生产环境不建议使用,而是应该通过控制系统来修订磁盘类型
# If allow_disk_format_probing is enabled, libvirt will probe disk
# images to attempt to identify their format, when not otherwise
# specified in the XML. This is disabled by default.
#
# WARNING: Enabling probing is a security hole in almost all
# deployments. It is strongly recommended that users update their
# guest XML <disk> elements to include  <driver type='XXXX'/>
# elements instead of enabling this option.
#
allow_disk_format_probing = 1然后再次使用
virsh attach-disk dev7 --source /var/lib/libvirt/images/dev7-data.img --target vdb --persistent但是还是出现报错error: unsupported configuration: unsupported driver name '(null)' for disk '/var/lib/libvirt/images/dev7-data.img',则参考sda系统盘配置传递参数
    <disk type='file' device='disk'>
      <driver name='qemu' type='qcow2'/>
      <source file='/var/lib/libvirt/images/dev7.img'/>
      <target dev='vda' bus='virtio'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
    </disk>virsh attach-disk dev7 --source /var/lib/libvirt/images/dev7-data.img --target vdb --persistent --driver qemu此时确实在dev7虚拟机内部看到了正确的磁盘大小,但是virsh edit dev7显示的sdb设备配置并没有自动加上类型type='qcow2'
    <disk type='file' device='disk'>
      <driver name='qemu' type='qcow2'/>
      <source file='/var/lib/libvirt/images/dev7.img'/>
      <target dev='vda' bus='virtio'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
    </disk>
    <disk type='file' device='disk'>
      <driver name='qemu'/>
      <source file='/var/lib/libvirt/images/dev7-data.img'/>
      <target dev='vdb' bus='virtio'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/>
    </disk>所以,我觉得开启libvirtd的allow_disk_format_probing = 1并没有什么方便,还是手工传递参数比较准确。即再次编辑/etc/libvirt/qemu.conf注释掉#allow_disk_format_probing = 1,再重启systemctl restart libvirtd.service。然后重新传递完整参数挂载磁盘
virsh attach-disk dev7 --source /var/lib/libvirt/images/dev7-data.img --target vdb --persistent --driver qemu --type qcow2依然失败unsupported configuration: unknown disk device 'qcow2'!!! 仔细看了 virsh help attach-disk帮助,发现传递参数实际上是和XML文件对应的。所以
<driver name='qemu' type='qcow2'/>对应的参数是
    --driver <string>  driver of disk device
    --subdriver <string>  subdriver of disk device即正确的命令是
virsh attach-disk dev7 --source /var/lib/libvirt/images/dev7-data.img --target vdb --persistent --driver qemu --subdriver qcow2终于成功
参考 Supported qemu-img Formats 说明,默认使用
raw格式,这个格式是最快的虚拟磁盘文件格式。如果文件系统支持空洞(例如ext2或ext3,则只有写过的扇区将使用空间)。使用qemu-img info可以获得镜像的实际大小,或者使用ls -l。不过,虽然raw格式镜像有性能优势,但是只支持基本特性。例如,raw格式不支持快照。
在虚拟机内部创建文件系统
mkfs.xfs /dev/vdb
mkdir /data
echo "/dev/vdb                /data                   xfs     defaults        0 0" >> /etc/fstab
mount /data挂载之后查看/data分区可以看到20G可用空间
/dev/vdb                  20G   33M   20G   1% /dataresize Linux磁盘
注意:只有
raw格式支持双向resize(扩大或缩小),qcow2版本2或qcow2版本3的镜像只支持扩大(grown)不支持缩小(shrunk)
qemu-img resize filename [+|-]size[K|M|G|T]将磁盘文件扩容到30G
qemu-img resize /var/lib/libvirt/images/dev7-data.img 30G此时在虚拟机内部
fdisk -l /dev/vbd查看磁盘是看不到磁盘空间增长到30G,依然是原先的20G
Disk /dev/vdb: 21.5 GB, 21474836480 bytes, 41943040 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes这说明qemu-img resize只在hypervisor层调整了虚拟磁盘镜像,所以我们需要采用qemu-monitor的底层命令
使用
qemu-monitor底层命令获取虚拟机内部磁盘信息
virsh qemu-monitor-command dev7 --hmp "info block"信息显示输出
drive-virtio-disk0: removable=0 io-status=ok file=/var/lib/libvirt/images/dev7.img ro=0 drv=qcow2 encrypted=0 bps=0 bps_rd=0 bps_wr=0 iops=0 iops_rd=0 iops_wr=0
drive-ide0-0-0: removable=1 locked=0 tray-open=0 io-status=ok [not inserted]
drive-virtio-disk1: removable=0 io-status=ok file=/var/lib/libvirt/images/dev7-data.img ro=0 drv=qcow2 encrypted=0 bps=0 bps_rd=0 bps_wr=0 iops=0 iops_rd=0 iops_wr=0则我们需要扩容的磁盘是drive-virtio-disk1 (对应dev7-data.img)
virsh qemu-monitor-command dev7 --hmp "block_resize drive-virtio-disk1 30G"此时再在虚拟机内部fdisk -l检查磁盘就可以看到vbd磁盘已经扩容到30G
Disk /dev/vdb: 32.2 GB, 32212254720 bytes, 62914560 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes不过此时XFS文件系统
/data还看不到增长的磁盘空间,我们还需要使用XFS支持的动态扩容
# df -h /data
Filesystem      Size  Used Avail Use% Mounted on
/dev/vdb         20G   33M   20G   1% /data
# mount -v | grep /data
/dev/vdb on /data type xfs (rw,relatime,seclabel,attr2,inode64,noquota)扩容XFS
# xfs_growfs /data/显示输出
meta-data=/dev/vdb               isize=512    agcount=4, agsize=1310720 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=0 spinodes=0
data     =                       bsize=4096   blocks=5242880, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=1
log      =internal               bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
data blocks changed from 5242880 to 7864320再次检查文件系统/data可以看到已经30G空间
# df -h /data
Filesystem      Size  Used Avail Use% Mounted on
/dev/vdb         30G   33M   30G   1% /dataWindows虚拟机
virtio设备驱动
virtio设备驱动Windows虚拟机默认安装采用了
IDE磁盘类型设备,性能较差,需要转换成virtio磁盘类型才能在KVM环境得到较好的性能。不过,Windows发行版并没有这个KVM Praavirtualized(virtio)驱动,需要独立安装以便识别出virtio磁盘。
virtio驱动盘安装方法参考 KVM Paravirtualized (virtio) Drivers
在HOST物理服务器上安装
virtio驱动盘(针对物理服务器RHEL 6.8操作系统)
yum install virtio-win安装后,在
/usr/share/virtio-win/有virtio-win.iso驱动ISO镜像,在virtio磁盘添加到Windows虚拟机之后,Windows操作系统会识别到新设备,就可以引导从该镜像安装驱动。如果要在Windows安装时候就直接安装到
virtio半虚拟化磁盘(viostor/virtio-scsi)上,则需要在Windows安装过程中选择virtio-win.iso驱动或者虚拟软盘镜像virtio-win<version>.vfd
RHEL/CentOS 7没有找到virtio-win软件包,参考 Windows Virtio Drivers 直接下载 Latest virtio-win iso 或 Stable virtio-win iso 存放到 /var/lib/libvirt/images目录下,连接到虚拟机
virsh attach-disk windev /var/lib/libvirt/images/virtio-win.iso hdb --type cdrom这里
hdb设备是从virsh edit windev查看的CDROM对应设备
如果原先在Windows虚拟机中已经添加了iso设备,则擦用virsh update-device(从XML文件获取配置)命令来更换ISO镜像 - 先创建virtio-iso.xml文件内容如下
<disk type='file' device='cdrom'>
  <driver name='qemu' type='raw'/>
  <source file='/var/lib/libvirt/images/virtio-win.iso'/>
  <backingStore/>
  <target dev='hdb' bus='ide'/>
  <readonly/>
  <alias name='ide0-0-1'/>
  <address type='drive' controller='0' bus='0' target='0' unit='1'/>
</disk>然后执行
virsh update-device windev virtio-iso.xml如果要持久替换,则使用
virsh update-device windev virtio-iso.xml --persistent
增加磁盘设备
检查虚拟机列表
virsh list以下操作针对windev虚拟机操作
检查虚拟机
windev的虚拟磁盘设备
virsh qemu-monitor-command windev --hmp "info block"这里输出显示
drive-ide0-0-0: removable=0 io-status=ok file=/var/lib/libvirt/images/windev.img ro=0 drv=qcow2 encrypted=0 bps=0 bps_rd=0 bps_wr=0 iops=0 iops_rd=0 iops_wr=0
drive-ide0-0-1: removable=1 locked=0 tray-open=0 io-status=ok file=/var/lib/libvirt/images/win2012.iso ro=1 drv=raw encrypted=0 bps=0 bps_rd=0 bps_wr=0 iops=0 iops_rd=0 iops_wr=0创建一个本地的虚拟磁盘文件
cd /var/lib/libvirt/images
qemu-img create -f qcow2 windev-data.img 20G添加磁盘设备
virsh attach-disk windev --source /var/lib/libvirt/images/windev-data.img --target vdb --persistent --driver qemu --subdriver qcow2在Windows虚拟机中更新
virtio驱动识别新增磁盘设备
在Windows虚拟机添加了virtio磁盘设备vdb之后,使用Window设备管理器可以看到新增加了一个SCSI控制器,此时还没有驱动安装,所以无法使用。在这个SCSI控制器设备上右击鼠标,选择更新驱动程序软件...,然后搜索D:\驱动器更新驱动程序
可以同时更新另外一个没有识别的
PCI设备驱动,方法相同,这个原先未识别到PCI设备实际上是VirtIO Balloon Driver
此时打开计算机管理(本地)工具查看磁盘管理(或者命令行调用diskmgmt.msc)可以看到新增了一块未知且脱机的20G磁盘,就是我们刚才动态添加的磁盘设备
按照Windows操作系统增加磁盘方法,先将新增磁盘联机,然后再初始化(创建MBR或GPT分区)
然后再创建简单卷(分配盘符格式化)
完成后即可使用磁盘
resize Windows磁盘
检查虚拟设备详细情况
virsh qemu-monitor-command windev --hmp "info block"这里可以看到windev-data.img虚拟磁盘文件对应的块信息
drive-virtio-disk1: removable=0 io-status=ok file=/var/lib/libvirt/images/windev-data.img ro=0 drv=qcow2 encrypted=0 bps=0 bps_rd=0 bps_wr=0 iops=0 iops_rd=0 iops_wr=0在线修改虚拟磁盘大小
virsh qemu-monitor-command windev --hmp "block_resize drive-virtio-disk1 30G"此时在物理服务器查看文件可以看到增长到30G
qemu-img info windev-data.img这里输出显示
image: windev-data.img
file format: qcow2
virtual size: 30G (32212254720 bytes)
disk size: 87M
cluster_size: 65536
Format specific information:
    compat: 1.1
    lazy refcounts: false但是在Windows虚拟内部还看不到磁盘空间增加依然显示是20G
没有找到不停止Windows虚拟机动态扩展磁盘方法,通过关闭Windows操作系统然后再次启动操作系统,就可以看到磁盘从20G更改到了30G:
接下来只需要在Windows虚拟机中扩展磁盘分区就可以完整使用扩容后的30G磁盘空间。
参考
Last updated
Was this helpful?