先说一个经常遇到的场景:KVM上跑的Windows Server 2008,每次重启都来一次漫长的磁盘检查,新装的系统也不例外,一等就是好几个小时。这种体验,谁碰谁知道。至于虚拟机镜像的挂载修改,在guestfish套件普及之前,操作起来也是颇为折腾——要么把虚拟机跑起来再动手,要么就得先把镜像转成raw,再把raw转成所谓的“裸格式”,然后才能挂载,整个过程堪称煎熬。所以,guestfish的出现,确实解决了不少实际问题。
1. 虚拟机镜像挂载及w2k8虚拟机启动自检慢问题解决办法
下面介绍的挂载办法,只适用于块设备镜像的挂载。而针对Windows 2008 Server启动时那个让人头疼的磁盘检查问题,我们可以通过裸设备挂载的方式,直接擦除其磁盘检查标志,从根本上绕过去。
具体操作如下:
第一步,在宿主机上安装最新版的ntfs-3g。
wget https://tuxera.com/opensource/ntfs-3g_ntfsprogs-2012.1.15.tgz
tar -zxvf ntfs-3g_ntfsprogs-2012.1.15.tgz
cd ntfs-3g_ntfsprogs-2012.1.15
./configure --bindir=/usr/bin
make
make install
第二步,扩展镜像,将其挂载并进行检查。先使用 losetup -f 获取一个可用的loop设备,然后挂载镜像:
losetup -f
/dev/loop0
losetup /dev/loop0 /dev/vmVG/ptyyb-webzb-57_vda
接着,使用kpartx将镜像分区映射。对于2008的镜像,如果它只有一个分区,默认会挂载到 /dev/mapper/loop0p1。但2008默认安装时通常会有一个boot分区,所以C盘往往在 /dev/mapper/loop0p2 上,具体挂载哪个分区,需要根据实际情况来定。
kpartx -a v /dev/loop0
检查镜像时,-b -d 这两个参数很关键,只有最新版的ntfs-3g才支持。
ntfsfix -b -d /dev/mapper/loop0p1
完成后,分别分离镜像映射和挂载:
kpartx -dv /dev/loop0
losetup -d /dev/loop0
2. KVM虚拟化与guestfish套件
guestfish套件究竟是一套什么样的工具?简单来说,它是虚拟机镜像管理的利器,提供了一系列针对镜像管理的命令行工具,同时也囊括了对外API。其核心组件包括:
- guestfish:交互式Shell,用于挂载镜像并提供操作环境。
- guestmount/guestumount:在宿主机上挂载/卸载客户机文件系统到指定目录。
- virt-alignment-scan:检查镜像分区的块对齐情况。
- virt-builder:快速创建虚拟机镜像。
- virt-cat/virt-edit:查看/编辑虚拟机内部的文件。
- virt-copy-in/virt-copy-out:将文件拷入或拷出虚拟机磁盘镜像。
- virt-customize:定制虚拟机镜像。
- virt-df:查看虚拟机镜像的空间使用状况。
- virt-diff:在不启动虚拟机的情况下,比较内部两份文件的差异。
- virt-filesystems/virt-list-partitions:显示文件系统、分区、LVM等信息。
- virt-format:格式化镜像内的磁盘。
- virt-inspector/virt-inspector2:检查并显示虚拟机的操作系统版本、内核等信息。
- virt-log/virt-ls:查看镜像内的日志或文件列表。
- virt-make-fs:在镜像中创建文件系统。
- virt-p2v/virt-p2v-make-disk/virt-p2v-make-kickstart:物理机向KVM虚拟机转换的相关工具。
- virt-rescue:进入虚拟机的救援模式。
- virt-resize:调整虚拟机磁盘分区大小。
- virt-sparsify:消除镜像中的稀疏空洞,有助于缩小镜像体积。
- virt-sysprep:在克隆前对虚拟机镜像进行初始化(如重置主机名、清理日志等)。
- virt-tar/virt-tar-in/virt-tar-out:以tar包形式导入或导出镜像内的文件。
- virt-v2v:将其他虚拟化格式的镜像转换为KVM镜像。
- virt-win-reg:操作Windows虚拟机的注册表。
- libguestfs-test-tool/libguestfs-make-fixed-appliance:libguestfs相关的测试与工具制作。
- hivex/hivexregedit/hivexsh/hivexml/hivexget:用于提取、合并、交互式修改、转换Windows注册表文件的一套工具。
- guestfsd:guestfs后台守护进程。
可以说,客座文件系统相关的日常操作,这套工具基本都覆盖到了。
3. guestfish安装与注意事项
guestfish套件的安装非常直接,一条命令即可搞定:
yum install libguestfs-tools
但这里有一个注意点:默认安装是不包含Windows系统支持的。如果你需要操作Windows虚拟机镜像,还得额外运行一条命令:
yum install libguestfs-winsupport
这个步骤很容易被遗漏,值得留意一下。
4. 使用guestfish查看虚拟机信息
查看虚拟机镜像信息,主要靠 virt-inspector 和 virt-inspector2 这两个命令。
- virt-inspector:显示虚拟机中的OS版本、内核、驱动、挂载点、应用等详细信息。
- virt-inspector2:主要显示OS版本及其他相关信息,输出格式为XML,内容上比前者更详细。
来看几个实际例子。
virt-inspector 示例:
virt-inspector centos5332.qcow2
linux centos i386 5.3 (CentOS release 5.3 (Final)) on /dev/vmvg/root:
Mountpoints:
/dev/vmvg/root /
/dev/sda1 /boot
/dev/vmvg/swap swap
Filesystems:
/dev/sda1:
label: /boot
UUID: 152ec813-72cc-4ea1-ad76-71c470feff2f
type: ext3
content: linux-grub
/dev/vmvg/root:
label:
UUID: 9462b99e-04d9-4648-9d5d-2ce50d8ed8f2
type: ext3
content: linux-root
/dev/vmvg/swap:
type: swap
Modprobe aliases:
binfmt-204 binfmt_aout
...
也可以通过 --query 参数输出一些固定内容,方便脚本做判断:
virt-inspector --query centos5332.qcow2
windows=no
linux=yes
rhel=no
fedora=no
debian=no
fullvirt=yes
xen_domU_kernel=no
xen_pv_drivers=yes
virtio_drivers=yes
kernel_arch=i386
userspace_arch=i386
输出格式也支持XML,加上 --xml 参数即可。
virt-inspector 操作Windows虚拟机示例:
windows i386 5.2 (Microsoft Windows Server 2003) on /dev/sda1:
Mountpoints:
/dev/sda1 /
Filesystems:
/dev/sda1:
type: ntfs
content: windows-root
Applications:
...
virt-inspector2 示例(Linux):
virt-inspector2 centos5332.qcow2
/dev/vmvg/root
linux
i386
centos
CentOS release 5.3 (Final)
5
3
rpm
yum
localhost.localdomain
installed
/
/boot
...
virt-inspector2 操作Windows虚拟机示例:
i386
windows
Microsoft Windows Server 2003
5
2
/WINDOWS
ControlSet001
ks-55e1e4a74d40
installed
/
ntfs
4A5061F55061E7E1
/dev/sda1
Google Chrome
...
5. 使用guestfish查看虚拟机分区及文件系统
这部分主要用到三个命令:
- virt-list-partitions:列出虚拟机磁盘镜像中的分区信息。
- virt-filesystems:列出镜像中的文件系统、分区、块设备及LVM信息。
- virt-alignment-scan:检查虚拟机分区的块对齐情况。
示例:
virt-list-partitions centos6232.qcow2
/dev/sda1
/dev/sda2
virt-list-filesystems centos6232.qcow2
/dev/sda1
/dev/vmvg/root
virt-list-filesystems win2k3.qcow2
/dev/sda1
virt-list-partitions win2k3.qcow2
/dev/sda1
virt-alignment-scan -a win2k3.qcow2
/dev/sda1 32256 512 bad (alignment < 4K)
virt-alignment-scan -a centos6232.qcow2
/dev/sda1 1048576 1024K ok
/dev/sda2 210763776 1024K ok
对齐检查在性能优化中是非常关键的一步,尤其是对于Windows虚拟机来说。
6. 去掉磁盘空洞——KVM虚拟镜像的稀疏问题
KVM虚拟化中,镜像文件通常使用RAW或QCOW2格式。RAW会一次性把规划的空间全部分配出去,而QCOW2则是典型的精简模式——磁盘用多少,才在宿主机上占多少实际空间。这得益于ext4文件系统的稀疏特性:当一个文件内容全是空时,ext4并不会真的分配物理块。
我们可以做个简单的测试:
qemu-img create -f raw test.raw 5G
qemu-img create -f qcow2 test.qcow2 5G
dd if=/dev/zero of=/root/test.dd bs=1G count=5
然后通过 ls -l 和 du 分别查看:
ls -l
-rw-r--r-- 1 root root 5.0G test.dd
-rw-r--r-- 1 root root 193K test.qcow2
-rw-r--r-- 1 root root 5.0G test.raw
du test*
5242880 test.dd
196 test.qcow2
0 test.raw
这个结果很有意思:ls告诉我们RAW文件是5G,但du给出的实际占用空间却是0。原因就在于文件全为空时,ext4的稀疏特性让系统“偷了个懒”,没有真正分配物理空间。如果希望用RAW格式并按计划一次性占满空间,可以用dd命令来创建。
QCOW2同样存在稀疏问题。从磁盘级别看,一些分区(比如刚创建好的swap)里会存在大量连续的相同空洞。利用 virt-sparsify 可以消除这些空洞,显著缩小镜像占用空间,方便传输。
使用前,需要先创建一个与原镜像等大的QCOW2镜像:
qemu-img create -f qcow2 test2.qcow2 5G
然后执行:
virt-sparsify -x /root/test.qcow2 --convert qcow2 /root/test2.qcow2
7. 用guestfish操作虚拟机内部文件
这部分列出的常用命令基本涵盖了所有文件操作场景:
- virt-df:查看镜像磁盘空间使用情况。
- virt-ls:列出镜像内指定目录的文件。
- virt-cat:显示指定文件的内容。
- virt-edit:编辑指定文件。
- virt-copy-in/virt-copy-out:文件拷贝进出镜像。
- virt-tar-in/virt-tar-out/virt-tar:打包或解包镜像内的文件。
示例:
查看镜像磁盘空间:
virt-df -a centos6364.qcow2
Filesystem 1K-blocks Used A vailable Use%
centos6364.qcow2:/dev/sda1 198337 32098 155999 17%
centos6364.qcow2:/dev/vmvg/root 16308136 1210172 14269548 8%
列出 /root 目录内容:
virt-ls -a centos6364.qcow2 /root
.bash_history
.bash_logout
.bash_profile
.bashrc
.cshrc
.tcshrc
anaconda-ks.cfg
install.log
install.log.syslog
显示 /root/anaconda-ks.cfg 文件内容:
virt-cat -a centos6364.qcow2 /root/anaconda-ks.cfg
# Kickstart file automatically generated by anaconda.
...
编辑该文件:
virt-edit -a centos6364.qcow2 /root/anaconda-ks.cfg
文件拷入与拷出:
touch test.txt
virt-copy-in test.txt -a centos6364.qcow2 /root/
virt-copy-out -a centos6364.qcow2 /root/test.txt /home
压缩包处理:
virt-tar-in -a disk.img data.tar /destination
virt-tar-out -a disk.img /dir files.tar
virt-tar -x domname /home home.tar
virt-tar -u domname uploadstuff.tar /tmp
8. guestfish修改镜像格式和大小
镜像格式和大小修改,主要依赖 virt-convert 和 virt-resize。
- virt-convert:在虚拟机镜像格式之间进行转换。
- virt-resize:修改虚拟机镜像的磁盘大小。
示例:
RAW转QCOW2,需要先用 qemu-img 创建一个同等大小的空QCOW2镜像,然后执行:
virt-convert -i raw -o qcow2 old.img new.qcow2
原始镜像也可以是VMware的vmx格式、KVM镜像或ovf格式的镜像。
将指定分区扩大5G:创建一个比原镜像大5G的新镜像,然后扩展:
virt-resize --expand /dev/sda2 olddisk newdisk
把boot分区增加200M,剩余空间扩充给 /dev/sda2:
virt-resize --resize /dev/sda1=+200M --expand /dev/sda2 olddisk newdisk
LVM扩展:
virt-resize --expand /dev/sda2 --LV-expand /dev/vg_guest/lv_root olddisk newdisk
扩展分区的同时将RAW格式转换为QCOW2:
qemu-img create -f qcow2 newdisk.qcow2 15G
virt-resize --expand /dev/sda2 olddisk newdisk.qcow2
两个需要注意的地方:一是扩展分区时,目标磁盘文件必须大于原始磁盘;二是磁盘缩小操作相对复杂,要求缩小后的空间远大于文件系统实际占用的大小。
9. guestfish挂载、修改、运行救援方式
最后这部分涉及镜像的挂载与救援模式操作:
- guestmount:使用FUSE和libguestfs,将客户机文件系统挂载到宿主机指定目录。
- guestfish:挂载镜像并提供一个交互式Shell。
- virt-rescue:进入虚拟机的救援模式。
示例:
只读方式将Windows镜像挂载到 /mnt:
guestmount -a windows.img -m /dev/sda1 --ro /mnt
将Linux虚拟机根目录挂载到 /mnt:
guestmount -a linux.qcow2 -m /dev/sda2 /mnt
用guestfish编辑镜像的grub配置文件:
guestfish --rw --add disk.img \
--mount /dev/vg_guest/lv_root \
--mount /dev/sda1:/boot \
edit /boot/grub/grub.conf
进入镜像的救援模式:
$ virt-rescue --suggest -d Fedora15
Inspecting the virtual machine or disk image ...
This disk contains one or more operating systems. You can use these
mount commands in virt-rescue (at the > prompt) to mount the
filesystems.
# /dev/vg_f15x32/lv_root is the root of a linux operating system
# type: linux, distro: fedora, version: 15.0
# Fedora release 15 (Lovelock)
mount /dev/vg_f15x32/lv_root /sysroot/
mount /dev/vda1 /sysroot/boot
mount --bind /dev /sysroot/dev
mount --bind /dev/pts /sysroot/dev/pts
mount --bind /proc /sysroot/proc
mount --bind /sys /sysroot/sys
Another way is to list the logical volumes (with lvs(8)) and partitions (with parted(8)) and mount them by hand:
> lvs
LV VG Attr LSize Origin Snap% Move Log Copy% Convert
lv_root vg_f15x32 -wi-a- 8.83G
lv_swap vg_f15x32 -wi-a- 992.00M
> mount /dev/vg_f15x32/lv_root /sysroot
> mount /dev/vda1 /sysroot/boot
> ls /sysroot
Another command to list a vailable filesystems is virt-filesystems(1).
To run commands in a Linux guest (for example, grub), you should chroot into the /sysroot directory first:
> chroot /sysroot
进入救援模式后,可以根据提示挂载文件系统,甚至chroot进去执行修复性操作,如修复grub。整个过程比启动虚拟机再操作要快得多,也安全得多。
