raw,qcow2虚拟磁盘挂载
在实际使用过程中可能会碰到这样一种情况,因某种原因导致虚拟机无法启动,但又需要读取虚拟机内的文件,可以通过挂载虚拟磁盘来进行读取,并且可以直接写入。
RAW
KVM官方默认的虚拟磁盘文件格式为RAW。
对于RAW格式可以通过losetup工具来模拟出一个新设备加以挂载。
示例:挂载rhel7-mode.img
A.标准分区
root@jun-live:images#pwd
/var/lib/libvirt/images
root@jun-live:images#qemu-img info rhel7-mode.img
image: rhel7-mode.img
file format: raw
virtual size: 8.0G (8589934592 bytes)
disk size: 3.5G
1.将rhel7-mode.img映射为loop10
root@jun-live:images#losetup /dev/loop10 rhel7-mode.img
root@jun-live:images#ls /dev/mapper/loop10*
ls: cannot access /dev/mapper/loop10*: No such file or directory
此时,内核没有识别到该设备的分区表,和普通硬盘刚分完区后重新加载分区表类似,需要kpartx -a
2.加载设备分区表
root@jun-live:images#kpartx -l rhel7-mode.img
loop18p1 : 0 409600 /dev/loop18 2048
loop18p2 : 0 16365568 /dev/loop18 411648
loop: device /dev/loop18 still in use, retrying delete
loop deleted : /dev/loop18
通过kpartx -l我们其实就已经可以看到,rhel7-mode.img包含两个分区,并且自动映射在loop18上,但loop18已经被其它镜像所使用,所以报了个资源忙。
root@jun-live:images#kpartx -a /dev/loop10
root@jun-live:images#ls /dev/mapper/loop10*
/dev/mapper/loop10p1@
root@jun-live:images#fdisk -u -l /dev/loop10
Disk /dev/loop10: 8589 MB, 8589934592 bytes
255 heads, 63 sectors/track, 1044 cylinders, total 16777216 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
Disk identifier: 0x00067969
/dev/loop10p1
Partition 1 does not end on cylinder boundary.
/dev/loop10p2
可以看到,有两个分区(实际上loop10p1为boot分区,loop10p2为LVM)
3.挂载标准分区
root@jun-live:images#mount /dev/mapper/loop10p1 /mnt/iso/
root@jun-live:images#mount|grep /mnt/iso
/dev/mapper/loop10p1 on /mnt/iso type xfs (rw)
root@jun-live:images#ls /mnt/iso/
config-3.10.0-123.el7.x86_64
grub2/
initramfs-0-rescue-ddcdf1804942b72473cc9c4a
initramfs-3.10.0-123.el7.x86_64.img
initramfs-3.10.0-123.el7.x86_64kdump.img
initrd-plymouth.img
symvers-3.10.0-123.el7.x86_64.gz
System.map-3.10.0-123.el7.x86_64
vmlinuz-0-rescue-ddcdf1804942b72473cc9c4a
vmlinuz-3.10.0-123.el7.x86_64*
4.测试写入
root@jun-live:images#touch /mnt/iso/test.losetup
root@jun-live:images#ls /mnt/iso/
config-3.10.0-123.el7.x86_64
grub2/
initramfs-0-rescue-ddcdf1804942b72473cc9c4a
initramfs-3.10.0-123.el7.x86_64.img
initramfs-3.10.0-123.el7.x86_64kdump.img
initrd-plymouth.img
symvers-3.10.0-123.el7.x86_64.gz
System.map-3.10.0-123.el7.x86_64
test.losetup
vmlinuz-0-rescue-ddcdf1804942b72473cc9c4a
vmlinuz-3.10.0-123.el7.x86_64*
可以直接读写,再来看看LVM
B.RAW---lvm
1.取消设备映射
root@jun-live:images#umount /mnt/iso/
root@jun-live:images#mount /dev/mapper/loop10p2 /mnt/iso/
mount: unknown filesystem type 'LVM2_member'
LVM不能直接挂载,需要作特殊处理。
root@jun-live:images#kpartx -d /dev/loop10
root@jun-live:images#losetup -d /dev/loop10
2.通过偏移量重新映射
fdisk -u 参数指明使用 sector 为单位记录偏移量(offset)而不是 cylinder 为单位
root@jun-live:images#bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software
Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.
411648*512
210763776
quit
root@jun-live:images#losetup /dev/loop10 rhel7-mode.img
-o
210763776
确认卷组名是否重复,如果有重复需要重命名
root@jun-live:images#pvscan
可以看到,该RAW设备里的卷组名也叫vg0,和我本地物理机的卷组重名了,这个时候需要根据卷组的UUID来重命名。
root@jun-live:images#vgs -v
... ...
root@jun-live:images#vgrename
rJGSsG-3ebw-8c2c-88bM-Am6M-Xycu-WNcQsh virt_vg0
... ...
4.激活lvm
root@jun-live:images#lvscan
root@jun-live:images#vgchange -ay virt_vg0
root@jun-live:images#lvscan|grep virt_vg0
root@jun-live:images#mount /dev/virt_vg0/root /mnt/iso/
root@jun-live:images#ls /mnt/iso/
bin@
boot/
root@jun-live:images#mount|grep /mnt/iso
/dev/mapper/virt_vg0-root on /mnt/iso type xfs (rw)
6.读写完毕后还原
root@jun-live:images#umount /mnt/iso
root@jun-live:images#lvchange -an virt_vg0
root@jun-live:images#kpartx -d /dev/loop10
root@jun-live:images#losetup -d /dev/loop10
补充:
对于还没有分区的RAW虚拟磁盘可以直接以loop格式挂载:
mount -o loop
qcow2
[root@test ~]# lsb_release -a
LSB Version:
Distributor ID:
Description:
Release:
Codename:
[root@test ~]# uname -a
Linux test 3.10.0-123.el7.x86_64 #1 SMP Mon Jun 30 12:09:22 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
[root@test boot]# grep NBD /boot/config-3.10.0-123.el7.x86_64
# CONFIG_BLK_DEV_NBD is not set
发现CentOS 7默认不支持,怎么办,重新编译内核模块
[root@test boot]# yum -y install gcc gcc-c++ make kernel-devel ncurses-devel
[root@test boot]# cd /usr/src/kernels/3.10.0-123.el7.x86_64/
[root@test 3.10.0-123.el7.x86_64]# cp -f /boot/config-3.10.0-123.el7.x86_64 .config
[root@test 3.10.0-123.el7.x86_64]# vim .config
CONFIG_BLK_DEV_NBD=m
更详细的内核及模块编译方法,请参看:Ubuntu14.04升级内核3.14.25
Device Drivers
编译安装完成后,再次尝试,映射原理同上面的RAW
[root@test boot]# grep NBD /boot/config-3.10.0-123.el7.x86_64
CONFIG_BLK_DEV_NBD=m
或直接编译内核模块
以CentOS7.2 3.10.0-327为例
mv /usr/src/kernels/$(uname -r) /usr/src/kernels/$(uname -r)-old
rpm -ivh http://vault.centos.org/7.2.1511/os/Source/SPackages/kernel-3.10.0-327.el7.src.rpm
tar -xvf ~/rpmbuild/SOURCES/linux-3.10.0-327.el7.tar.xz
mv linux-3.10.0-327.el7 /usr/src/kernels/$(uname -r)
cd /usr/src/kernels/$(uname -r)
make mrproper
cp -f /usr/src/kernels/$(uname -r)-old/Module.symvers /usr/src/kernels/$(uname -r)
cp -f /boot/config-$(uname -r) /usr/src/kernels/$(uname -r)/.config
make oldconfig
make prepare
make scripts
make CONFIG_BLK_DEV_NBD=m M=drivers/block
cp -f /usr/src/kernels/$(uname -r)/drivers/block/nbd.ko /lib/modules/$(uname -r)/kernel/drivers/block/
depmod -a
modprobe nbd
modinfo nbd
[root@test images]# modprobe nbd
[root@test images]# qemu-nbd -c /dev/nbd0 foo.qcow2
[root@test images]# kpartx -a /dev/nbd0
[root@test images]# mount /dev/nbd0p1 /mnt/
[root@test images]# umount /mnt
[root@test images]# qemu-nbd -d /dev/nbd0
qemu-nbd -b 0.0.0.0 -p 10809 -e 10 -t centos7-s1.qcow2
/usr/libexec/qemu-kvm -enable-kvm -name demo -m 1024 -hda nbd:192.168.130.254:10809-vnc :19 -snapshot
qemu-nbd -k /tmp/nbd.sock -e 10 -t centos7-s1.qcow2
/usr/libexec/qemu-kvm -enable-kvm -name demo -m 1024 -hda nbd:unix:/tmp/nbd.sock -vnc :19 -snapshot
补充:虚拟机磁盘镜像修改工具guestfish
http://libguestfs.org/
https://docs.openstack.org/image-guide/modify-images.html