kvm

KVM镜像本地挂载

Posted by elrond on August 20, 2021

1. 场景

查看操作虚拟机镜像的文件系统

  • 查看/修改 windows 镜像密码
  • 查看/修改 linux 镜像密码、cloud-init 文件
  • 其他

2. 环境

环境 版本 备注
OS CentOS7.9  
libguestfs 1.40.2-10.el7.x86_64  
libguestfs-tools 1.40.2-10.el7.noarch  
libguestfs-winsupport 7.2-3.el7.x86_64 实际安装了这个包也没法兼容 ntfs 文件系统
ntfs-3g 2017.3.23-11.el7.x86_64 挂载 ntfs 文件系统
kpartx 0.4.9-134.el7_9.x86_64 根据分区表将分区映射为不同的 lvm 设备

3. 操作

3.1. Linux

修改 cloud-init 配置使得用该镜像启动的虚拟机可以通过 root 用户 ssh

# 使用 `guestfish` 命令连接虚拟磁盘
guestfish -a CentOS-7-x86_64-GenericCloud.qcow2
# 启动虚拟磁盘
run
# 列举文件系统
list-filesystems
# 挂载要操作的分区到/ 我们要修改的 cloud-init, 一般在/dev/sda1
mount /dev/sda1 /
# 修改文件
vi /etc/cloud/cloud.cfg
# 修改完之后退出
exit

这样就算修改完成了,再次启动磁盘上的内容就是我们修改过的。

3.2. Windows

windows 比较麻烦点,上面版本的 libguestfs-tools 不支持 ntfs

我们使用 kpartx 先将磁盘分区映射到服务器的 lvm 然后使用 loop 设备挂载

kpartx 可以映射 raw 格式镜像,无法映射 qcow2 格式镜像,qcow2 格式镜像要么转换成 raw 格式镜像再映射,要么使用 nbd 映射

3.2.1. raw 镜像

# qcow2 to raw
qemu-img convert -f qcow2 -O raw xxxx.qcow2 xxxx.raw
# kpartx mapper
kpartx -av xxxx.raw
# 输出入下
add map loop1p1 (253:16): 0 1024000 linear /dev/loop1 2048
add map loop1p2 (253:17): 0 40914944 linear /dev/loop1 1026048
# 映射的 loop 设备在 /dev/mapper/ 下,使用 dmsetup 命令也可以看到
# 一般 c 盘在loop1p2
# 挂载前安装 ntfs-3g 否则无法挂载
mount /dev/mapper/loop1p2  /mnt/
cd /mnt/
# 查看 windows 密码,前提镜像密码是通过 ec2-config 设置的
cat Program\ Files/Bingosoft/Ec2Config/SysPrepInit.cmd
# 看到的密码就是这个经想的密码了,如果要修改修改这里也就相当于修改了镜像
# 搞完之后 umount,delete mapper
cd -
umount /mnt
kpartx -dv xxx.raw

如果如果没有EC2 文件的话,一样的也是挂载到宿主机上,然后找到C盘的windows/system32/sethc.exe文件,把这个文件改为其他名字,然后把cmd.exe复制一份成这个文件。然后开机后连按5次shift键,就会跳出cmd界面了。然后用net user administrator 123456重置下密码。

3.2.2. qcow2

qcow2 镜像使用 nbd 驱动挂载, nbd 要先重新编译到内核里面,否则下面操作无法继续

这种方式我没有实操,参照mounting-raw-and-qcow2-images

# 加载内核
modprobe nbd max_part=63
# 连接镜像
qemu-nbd -c /dev/nbd0 disk1.qcow2
# 挂载
mount /dev/nbd0p1 /mnt/t01
# 如果是 lvm 的话关联一个 llop 设备到 lvm 分区
losetup /dev/loop0 /dev/nbd0p2
# 在 /dev/mapper 中找到 lvm 也可以使用 lvdisplay 显示 lvm vgdisplay 显示 vg vgchange 激活 vg
ls -l /dev/mapper
# 挂载
mount /dev/mapper/vg_volgroupname-lv_logicalgroupname /mnt/t02
# 操作
...
# 卸载
umount /mnt/t02
umount /mnt/t01
# deactivate 卷组
vgchange -an vg_volgroupname
# 删除 loop 设备
losetup -d /dev/loop0
# 卸载 ndb
qemu-nbd -d /dev/nbd0
# 删除 nbd 模块
rmmod nbd

4. 参考

https://www.linuxunbound.com/2016/07/mounting-raw-and-qcow2-images/