挂载虚拟机镜像文件里的普通分区

用 virt-manager, virsh 或其他工具可以选择把 KVM 或 Xen HVM 的虚拟机安装在一个镜像文件上,虽然因为性能的关系这种方式不推荐在生产环境使用,但是因为用起来非常简便,所以 VPSee 平时做实验或测试的时候会经常用这种方式存储虚拟机。上星期提到了 “挂载虚拟机镜像文件里的 LVM 逻辑分区”,那么如何挂载虚拟机镜像文件里的普通分区呢?这比挂载 LVM 逻辑分区要简单多了,不用算那个地址偏移量 offset,也不用 LVM 打交道。

和以前一样,首先用 losetup 工具把 centos.img 文件和 loop 设备映射起来,-f 参数用来找出下一个可用的 loop 设备:

# losetup -f
/dev/loop0

# losetup /dev/loop0 /home/vpsee/centos.img

一个镜像文件里可能包含多个分区,所以不能简单 mount -o loop centos.img,我们需要把 centos.img 里面包含的每个分区映射出来后在一个一个挂载,所以需要一个工具来读分区表,kpartx 就是这样一个在特定设备上读取分区表并为每个分区创建映射的工具,-a 参数表示加入分区映射;-v 参数表示完成后输出结果:

# kpartx -av /dev/loop0 
add map loop0p1 : 0 208782 linear /dev/loop0 63
add map loop0p2 : 0 1044225 linear /dev/loop0 208845
add map loop0p3 : 0 19711755 linear /dev/loop0 1253070

上面 loop0p1, loop0p2, loop0p3 分别映射到镜像文件里的3个分区里,可以通过 fdisk 来查看:

# fdisk -l /dev/loop0

Disk /dev/loop0: 10.7 GB, 10737418240 bytes
255 heads, 63 sectors/track, 1305 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

      Device Boot      Start         End      Blocks   Id  System
/dev/loop0p1   *           1          13      104391   83  Linux
/dev/loop0p2              14          78      522112+  82  Linux swap / Solaris
/dev/loop0p3              79        1305     9855877+  83  Linux

有了上面的映射以后就可以挂载 centos.img 里的普通逻辑分区了,我们这里只挂载 root 分区,root 分区在 loop0p3,挂载成功后用 ls 查看一下是否正确:

# ls -l /dev/mapper/
total 0
crw------- 1 root root  10, 63 Sep 24 11:34 control
brw-r----- 1 root disk 253,  2 Oct 14 19:55 loop0p1
brw-r----- 1 root disk 253,  3 Oct 14 19:55 loop0p2
brw-r----- 1 root disk 253,  4 Oct 14 19:55 loop0p3

# mount /dev/mapper/loop0p3 /mnt
# ls /mnt
bin   dev  home  lib64       media  opt   root  selinux  sys  usr
boot  etc  lib   lost+found  mnt    proc  sbin  srv      tmp  var

使用完后,需要按顺序干净卸载:

# umount /mnt

# kpartx -dv /dev/loop0
del devmap : loop0p1
del devmap : loop0p2
del devmap : loop0p3

# losetup -d /dev/loop0

挂载虚拟机镜像文件里的 LVM 逻辑分区

如果按照 “在 CentOS 上安装和配置 KVM” 这篇文章介绍的方法安装 guest 操作系统到一个 raw 文件里(virt-install … –disk path=/home/vpsee/centos.img …),那么在以后的维护过程中就可能会遇到麻烦。比如,前段时间 VPSee 碰到一位用户忘了 root 密码需要挂载这个虚拟机的文件系统并恢复 shadow,这时候就需要能够挂载虚拟机的文件系统。虚拟机的文件系统在一个 raw 文件上,这个镜像文件完全模拟了一个硬盘,包含硬盘分区表和 LVM 逻辑卷,所以不能通过 mout 简单挂载,需要一些额外的工作,那么如何才能挂载这个镜像文件里的 LVM 逻辑分区呢?

首先用 losetup 工具把 centos.img 文件和 loop 设备映射起来,-f 参数用来找出下一个可用的 loop 设备:

# losetup -f
/dev/loop0

# losetup /dev/loop0 /home/vpsee/centos.img

然后通过 fdisk /dev/loop0 来查看 centos.img 里的分区表,-u 参数指明使用 sector 为单位记录偏移量(offset)而不是 cylinder 为单位:

# fdisk -u -l /dev/loop0

Disk /dev/loop0: 10.7 GB, 10737418240 bytes
255 heads, 63 sectors/track, 1305 cylinders, total 20971520 sectors
Units = sectors of 1 * 512 = 512 bytes

      Device Boot      Start         End      Blocks   Id  System
/dev/loop0p1   *          63      208844      104391   83  Linux
/dev/loop0p2          208845    20964824    10377990   8e  Linux LVM

因为每个 sector 是 512 字节(bytes),所以 offset 等于 208845 X 512 = 106928640,这个 offset 很重要,在下面的操作中会用到。

先解除掉 /dev/loop0 和 centos.img 的映射,然后重新用 offset = 106928640 映射起来:

# losetup -d /dev/loop0
# losetup /dev/loop0 /home/vpsee/centos.img -o 106928640

现在可以看到系统上有2个 PV(物理卷组),一个是系统本身,一个是 centos.img 里面的 PV,这两个 PV 的名字都是一样的,是因为当初安装系统的时候都使用了默认的名字,这带来了麻烦,后面的操作会改变一个 PV 的名字以方便后续操作:

# lvm pvscan
  PV /dev/sda2    VG VolGroup00   lvm2 [465.66 GB / 0    free]
  PV /dev/loop0   VG VolGroup00   lvm2 [9.88 GB / 0    free]
  Total: 2 [475.53 GB] / in use: 2 [475.53 GB] / in no VG: 0 [0   ]

# lvm vgchange -ay
  2 logical volume(s) in volume group "VolGroup00" now active
  2 logical volume(s) in volume group "VolGroup00" now active

因为要给两个相同名字的 VolGroup00 改名,所以要先找到他们不同的 UUID:

# vgs -v
    Finding all volume groups
    Finding volume group "VolGroup00"
    Finding volume group "VolGroup00"
  VG         Attr   Ext    #PV #LV #SN VSize   VFree VG UUID                               
  VolGroup00 wz--n- 32.00M   1   2   0 465.66G    0  dqfs1x-QBY1-kNRr-l0X0-RnoW-GgIR-ZfjkCS
  VolGroup00 wz--n- 32.00M   1   2   0   9.88G    0  XrQNej-Aikn-qjxy-q7Lf-mBDk-gSfs-bLEgT6

上面第2个是 centos.img 里面的 VolGroup00(9.88GB 那个),改名为 vps01:

# vgrename XrQNej-Aikn-qjxy-q7Lf-mBDk-gSfs-bLEgT6 vps01
  Volume group "VolGroup00" successfully renamed to "vps01"

根据卷组名字和空间大小我们可以判断我们需要挂载 LogVol00 vps01(LogVol01 vps01 是 swap):

# lvm lvs
  LV       VG         Attr   LSize   Origin Snap%  Move Log Copy%  Convert
  LogVol00 VolGroup00 -wi-ao 460.03G                                      
  LogVol01 VolGroup00 -wi-ao   5.62G                                      
  LogVol00 vps01      -wi---   8.88G                                      
  LogVol01 vps01      -wi---   1.00G

现在终于可以挂载 centos.img 里的 LVM 逻辑分区了:

# mount /dev/mapper/vps01-LogVol00 /mnt

# ls /mnt
bin   dev  home  lib64       media  opt   root  selinux  sys  usr
boot  etc  lib   lost+found  mnt    proc  sbin  srv      tmp  var

使用完后,需要按顺序干净卸载:

# umount /mnt
# vgchange -an vps01
  0 logical volume(s) in volume group "vps01" now active
# losetup -d /dev/loop0

延伸阅读:如何挂载虚拟机镜像文件里的普通分区?