1. 程式人生 > 其它 >如何快捷地修改虛擬機器映象——libguestfs-tools工具集介紹

如何快捷地修改虛擬機器映象——libguestfs-tools工具集介紹

前言

在使用雲伺服器產品時,由於問題修復、功能新增、軟體更新等原因,往往需要對已有系統映象進行二次修改。

這種情況下,最為簡單的做法是:使用原映象建立例項,在例項中進行修改,修改完畢後再轉映象。這種做法比較粗暴,系統啟動的過程可能會為原本乾淨的系統映象帶來一些不必要的殘留資料,而且也無法執行硬碟分割槽、檔案系統等需要目標檔案系統不在掛載狀態下才能夠執行的操作。

針對這些問題,一種改善的方法是:使用原映象建立一塊雲硬碟,隨後將這塊雲硬碟掛載至一臺已建立的例項上並進行修改,修改完畢後將雲硬碟轉映象。這樣能夠在較大程度上保證系統映象的純淨性,也能夠進行分割槽、檔案系統方面的修改。

不過上述方式整體操作流程仍然比較冗長,為了縮減流程,libvirt提供了名為libguestfs-tools的工具,用來快捷地操作硬碟映象。

簡介

libguestfs-tools是一款系統管理員用來管理虛擬機器硬碟映象的工具包,裡面包含了用於各種各樣用途的工具,能夠幫忙我們操作硬碟映象的分割槽、檔案系統、檔案等等。

libguestfs-tools包含了如下工具:

  1. guestfish提供了一個互動式shell,在這個shell中可以通過一系列內建命令操作硬碟映象的分割槽、檔案系統、檔案等等。
  2. guestmount能夠將硬碟映象中的檔案系統掛載至宿主機上,從而像操作宿主機的檔案一樣操作硬碟映象中的檔案。
  3. virt-alignment-scan能夠掃描磁碟映象並檢測分割槽對齊問題。
  4. virt-builder用於快速地構建一個可用的硬碟映象。
  5. virt-cat用來展示硬碟映象中指定檔案的內容。
  6. virt-copy-in和virt-copy-out用來上傳/下載硬碟映象中的檔案/目錄。
  7. virt-customize用來定製硬碟映象。
  8. virt-df展示硬碟映象空間的使用情況。
  9. virt-diff展示硬碟映象內兩個檔案的差異。
  10. virt-edit用來編輯硬碟映象中的檔案。
  11. virt-filesystems展示硬碟映象中的檔案系統、硬碟分割槽、塊裝置、LVM資訊等等。
  12. virt-format用來格式化硬碟映象內部的檔案系統。
  13. virt-get-kernel用來獲取硬碟映象中的kernel/initrd。
  14. virt-inspector用來探測硬碟映象內部的系統資訊。
  15. virt-log展示硬碟映象中的日誌。
  16. virt-ls用來列出硬碟映象中的檔案。
  17. virt-make-fs能夠使用指定的檔案或歸檔包建立包含有一個檔案系統的硬碟映象。
  18. virt-rescue提供了一個互動式shell,用於操作硬碟映象。
  19. virt-resize能夠擴容硬碟映象中的分割槽。
  20. virt-sparsify能夠消除硬碟映象中的空洞,壓縮映象大小。
  21. virt-syspgrep用於映象初始化。
  22. virt-tail能夠追蹤硬碟映象中指定檔案的更新情況。
  23. virt-tar-in和virt-tar-out能夠上傳/下載硬碟映象中的檔案/目錄並歸檔。
  24. virt-win-reg能夠修改windows硬碟映象中的登錄檔。

如上,可以看到為了簡化對硬碟映象的操作,libguestfs-tools提供了非常非常多的工具,這些工具每個都有著各自的用途,有的十分好用,而有的卻很雞肋。在絕大多數情況下,guestmount工具就可以滿足我們的需求。

安裝

libguestfs-tools工具位於centos的base源中,確認軟體源後安裝libguestfs-tools工具包:

yum install -y libguestfs-tools

案例

檔案系統、分割槽、塊裝置、LVM資訊獲取

通過virt-filesystems命令可以方便地獲取到硬碟映象中所有分割槽和檔案系統的資訊:

export LIBGUESTFS_BACKEND=direct
virt-filesystems --all --long --uuid -h -a centos.qcow2
Name                         Type       VFS  Label MBR Size Parent                  UUID
/dev/sda1                    filesystem xfs  -     -   1.0G -                       c21cde6e-fe3a-4aa1-8adb-d26d096b1889
/dev/sda2                    filesystem swap -     -   2.0G -                       ef8945c2-3538-4adf-a70c-c46d339b150d
/dev/centos_hikvisionos/root filesystem xfs  -     -   17G  -                       70ced207-d3bc-4ca0-b3ea-3050ebd4990c
/dev/centos_hikvisionos/root lv         -    -     -   17G  /dev/centos_hikvisionos gjQuy8-ed48-WMDo-PROV-14Sl-ghdp-UGE0b9
/dev/centos_hikvisionos      vg         -    -     -   17G  /dev/sda3               BXeW80Nd2VQNBnvOCypsbf0a0n8etjSQ
/dev/sda3                    pv         -    -     -   17G  -                       ZuUKoHbV7jyJW6C57p36BXvOuUzz4BRB
/dev/sda1                    partition  -    -     83  1.0G /dev/sda                -
/dev/sda2                    partition  -    -     82  2.0G /dev/sda                -
/dev/sda3                    partition  -    -     83  17G  /dev/sda                -
/dev/sda                     device     -    -     -   20G  -                       -

* 檔案修改

我們對硬碟映象的改動在絕大多數情況下都屬於檔案修改,而不需要涉及到分割槽或檔案系統的情況下,使用guestmount命令可以輕鬆搞定。

# 映象的掛載路徑
MOUNT_PATH=/mnt/centos
# 映象的路徑
IMAGE=/root/centos.qcow2

export LIBGUESTFS_BACKEND=direct
# -a指定映象,-i表示自動識別待掛載的映象檔案系統
guestmount -a $IMAGE -i $MOUNT_PATH
# -m手動指定映象內的待掛載檔案系統
# guestmount -a $IMAGE -m /dev/centos/root $MOUNT_PATH
# 進入掛載路徑
cd $MOUNT_PATH

上面這種方式能夠修改硬碟映象中的檔案,不過,卻無法執行硬碟映象中的命令,如果涉及到需要執行映象中命令的操作,比如說yum install安裝軟體、grub-install生成grub配置、dracut生成initrd等等,還需要增加一步chroot。

# 掛載必要的裝置路徑並chroot
mount -t proc none $MOUNT_PATH/proc
mount --bind /dev $MOUNT_PATH/dev
mount -t devpts devpts $MOUNT_PATH/dev/pts
mount -t sysfs none $MOUNT_PATH/sys
chroot $MOUNT_PATH

# 執行操作
rm -rf /tmp/*
yum clean all
rm -rf /var/cache/yum
cd /var/log/; ls -I audit -I sa -I samba|xargs rm -rf

在操作完後,解除安裝映象掛載路徑,對映象的改動就算作是完成了,如果之前有chroot,那麼還需退出chroot並解除安裝相關裝置路徑。

# 退出chroot並解除安裝裝置路徑
exit
rm -f $MOUNT_PATH/root/.bash_history
umount $MOUNT_PATH/proc
umount $MOUNT_PATH/dev/pts
umount $MOUNT_PATH/dev
umount $MOUNT_PATH/sys
# 解除安裝映象掛載路徑
umount $MOUNT_PATH

分割槽移除

注:分割槽的移除可直接使用virt-resize工具完成,本章節僅演示virt-rescue工具的用法

分割槽移除涉及到分割槽操作,務必謹慎,確保硬碟映象已備份。分割槽移除分為末尾分割槽移除和非末尾分割槽移除兩種情況,末尾分割槽移除比較簡單,不做介紹,這裡只考慮非末尾分割槽的移除。比如說硬碟映象中不再需要用到swap功能,於是乎需要將中間的swap分割槽移除。

使用virt-rescue工具操作該映象:

export LIBGUESTFS_BACKEND=direct
virt-rescue -a centos.qcow2
><rescue> lsblk
NAME                        MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda                           8:0    0  20G  0 disk
|-sda1                        8:1    0   1G  0 part
|-sda2                        8:2    0   2G  0 part
`-sda3                        8:3    0  17G  0 part
  `-centos_hikvisionos-root 252:0    0  17G  0 lvm
sdb                           8:16   0   4G  0 disk /

歸檔第三個分割槽,並刪除lvm相關配置(防止分割槽同步報錯):

><rescue> mount /dev/centos_hikvisionos/root /sysroot/
><rescue> tar -cf rootfs.tgz /sysroot/
><rescue> umount /sysroot/
><rescue> lvremove centos_hikvisionos root
><rescue> vgremove centos_hikvisionos

刪除第二、三分割槽,使用所有剩餘空間重建為第二分割槽:

><rescue> fdisk /dev/sda

Command (m for help): p
...
Device     Boot   Start      End  Sectors Size Id Type
/dev/sda1  *       2048  2099199  2097152   1G 83 Linux
/dev/sda2       2099200  6293503  4194304   2G 82 Linux swap / Solaris
/dev/sda3       6293504 41943039 35649536  17G 83 Linux

d
d
n

Command (m for help): p
...

Device     Boot   Start      End  Sectors Size Id Type
/dev/sda1  *       2048  2099199  2097152   1G 83 Linux
/dev/sda2       2099200 41943039 39843840  19G 83 Linux

Command (m for help): w
The partition table has been altered.

重建檔案系統:

><rescue> pvcreate /dev/sda2
><rescue> vgcreate centos_hikvisionos /dev/sda2
><rescue> lvcreate --name root -l 100%FREE centos_hikvisionos
><rescue> mkfs.xfs /dev/centos_hikvisionos/root
><rescue> mount /dev/centos_hikvisionos/root /sysroot/
><rescue> tar -xf rootfs.tgz -C /

注意如果涉及到根分割槽或boot分割槽的改動,那麼需要更新grub的啟動配置:

# 這裡省略guestmount並chroot的操作
# 如果boot分割槽被改動,需要執行這一步將grub安裝到該硬碟映象中
# grub2-install /dev/sda
grub2-mkconfig -o /boot/grub2/grub.cfg

隨後退出互動式shell,使用該映象作為系統盤建立一臺雲伺服器,除錯該映象是否能夠正常啟動。

分割槽擴容/縮容/刪除

virt-resize工具可以用於硬碟映象的分割槽操作,該工具在操作分割槽的同時也會考慮到其上的檔案系統,較為方便。

# 建立一個空映象,大小為10G,作為輸出映象
qemu-img create -f qcow2 -o preallocation=metadata test-new.qcow2 10G
# 將sda2分割槽擴充套件至最大(9G)
virt-resize --expand /dev/sda2 test.qcow2 test-new.qcow2
# 將sda2分割槽擴充套件至最大,與此同時sda1分割槽擴充套件200M
virt-resize --resize /dev/sda1=+200M --expand /dev/sda2 test.qcow2 test-new.qcow2
# 將sda2分割槽擴充套件至最大,並將邏輯卷與檔案系統擴容至最大
virt-resize --expand /dev/sda2 --LV-expand /dev/centos/root test.qcow2 test-new.qcow2
# 縮容分割槽,注意縮容前需要事先縮容檔案系統或pv,否則會報錯
virt-resize --shrink /dev/sda2 test.qcow2 test-new.qcow2
virt-resize --resize /dev/sda1=-200M test.qcow2 test-new.qcow2
# 刪除分割槽
virt-resize --delete /dev/sda2 test.qcow2 test-new.qcow2

映象空洞去除並壓縮

virt-sparsify工具可以去除硬碟映象的空洞並壓縮。經測試,一個大小為4G的普通centos映象能夠壓縮到700M,壓縮比率較高,推薦使用,不過據工具說明,可能存在風險,目前尚未遇到有檔案系統損壞的情況。

qemu-img info hikos.raw|grep virtual
# virtual size: 6 GiB (6443696128 bytes)

# 建立一個新的同樣大小的映象test.qcow2
qemu-img create -f qcow2 -o preallocation=metadata test.qcow2 6G
# 使用virt-sparsify去除映象空洞並壓縮
virt-sparsify hikos.raw --compress --convert qcow2 test.qcow2

參考文件

guestfish(1) - Linux man page (die.net)

KVM映象管理利器-guestfish使用詳解_xiaoli110的技術部落格_51CTO部落格