家里使用的 NAS 是 DIY 的 All In One 主机,母鸡是 PVE(Proxmox Virtual Environment)。

为便于管理和维持良好的独立性,我把主要的 Docker 服务部署在基于 PVE 虚拟机的开源 NAS 系统 OMV(openmediavault)上。由于计划赶不上变化,原先给 OMV 预分配的磁盘空间已经耗尽,以致 web 管理页面也无法登录,只能通过 ssh 方式管理。为解决这个问题,在保数据的前提下,从母鸡分配磁盘空间进行扩容已是唯一选择。

原本以为扩容操作可以直接通过 PVE 的 web 管理页面便能轻松实现(我部分虚拟机确实是这样)。但是,OMV 这个情况和我预想的还是有点偏差,扩容后的空间无法合并到根目录上。具体原因是部署 OMV 时,我使用安装方式为虚拟机 IOS 镜像直读模式。从 win32 开始遗传的电脑使用习惯(安装直接点 “下一步”)安装的 OMV,自然自带 swap 分区。由于 swap 分区的存在,导致 pve 扩容的空间无法和原来 OMV 磁盘组成连贯分区,无法实现根目录扩容的目的。网上清一色的教程均为简单的独立分区无损扩容,并没有提及这种带其他分区的磁盘该如何扩容。因此,我写下这个笔记供后续遇到类似需求的朋友作为参考,避免踩坑。

存在swap分区的PVE虚拟机磁盘如何扩容?

母鸡扩容

母鸡扩容的方法很简单,可通过 PVE 的 Web 管理系统 -> 目标主机 -> 硬件 -> 选定目标磁盘 -> 操作菜单:磁盘操作 -> 调整大小,给你目标的主机设置需扩容的磁盘空间。

扩容操作
扩容操作

信息确认

通过 ssh 工具访问 OMV,查看磁盘的基本情况。

PS:本例子使用的磁盘均为 sda

$sudo parted /dev/sda 'unit s print' free
Model: ATA VBOX HARDDISK (scsi)
Disk /dev/sda: 14336000s
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:

Number  Start      End        Size       Type      File system     Flags
        63s        2047s      1985s                Free Space
 1      2048s      10485759s  10483712s  primary   ext4            boot
        10485760s  10487805s  2046s                Free Space
 2      10487806s  12580863s  2093058s   extended
 5      10487808s  12580863s  2093056s   logical   linux-swap(v1)
        12580864s  14335999s  1755136s             Free Space

如上面 shell 信息所示,sda1 被扩容的空间在磁盘分区的最后,中间隔着一个 swap 分区,这样扩容的空间是无法直接分配到 sda1 上。

如果要实现无损扩容必须把 swap 分区删除,然后把 sda1 扩容后再重建 swap 分区。

第一步,关闭swap分区

$ free -h
              total        used        free      shared  buff/cache   available
Mem:           992M         52M        464M        3.2M        475M        784M
Swap:          1.0G          0B        1.0G

通过 free 命令查看 swap 是否存在占用,如果没有,直接关掉;如果有,可以尝试重启下该虚拟机。

$sudo swapoff /dev/sda5

第二步,重新配置分区列表

$sudo fdisk /dev/sda

(注意:假如你的虚拟机磁盘初始扇区是 63 而不是 2048, 你需要在 fdisk 命令后面增加一个参数 -c=dos)

参考下面的操作步骤删除 swap 分区和重建分区列表。

PS:本操作虽然是无损扩容,但数据无价建议有条件的一定要先备份数据!!!

Welcome to fdisk (util-linux 2.27.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Command (m for help): p
Disk /dev/sda: 6.9 GiB, 7340032000 bytes, 14336000 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
Disklabel type: dos
Disk identifier: 0x9e11c6df

Device     Boot    Start      End  Sectors  Size Id Type
/dev/sda1  *        2048 10485759 10483712    5G 83 Linux
/dev/sda2       10487806 12580863  2093058 1022M  5 Extended
/dev/sda5       10487808 12580863  2093056 1022M 82 Linux swap / Solaris

Command (m for help): d
Partition number (1,2,5, default 5): 2

Partition 2 has been deleted.

Command (m for help): d
Selected partition 1
Partition 1 has been deleted.

Command (m for help): n
Partition type
   p   primary (0 primary, 0 extended, 4 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (1-4, default 1): 1
First sector (2048-14335999, default 2048):
Last sector, +sectors or +size{K,M,G,T,P} (2048-14335999, default 14335999): 12242941

Created a new partition 1 of type 'Linux' and of size 5.9 GiB.

Command (m for help): n
Partition type
   p   primary (1 primary, 0 extended, 3 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (2-4, default 2): 2
First sector (12242942-14335999, default 12242944):
Last sector, +sectors or +size{K,M,G,T,P} (12242944-14335999, default 14335999):

Created a new partition 2 of type 'Linux' and of size 1022 MiB.

Command (m for help): a
Partition number (1,2, default 2): 1

The bootable flag on partition 1 is enabled now.

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Re-reading the partition table failed.: Device or resource busy

The kernel still uses the old table. The new table will be used at the next reboot or after you run partprobe(8) or kpartx(8).

这部分有两个地方需要注意的:

1、sda1 扩容后的总大小必须是整个磁盘减去 swap 分区的大小,我上面的例子 sda1 就是: 14335999-2093058=12242941

2、fdisk 分区使用‘a’命令是用来激活主分区,这个一定要重新激活。

第三步,重载分区列表

这里使用到的是 part­probe,OMV 是基于 De­bian 的,默认应该安装了,如果没有安装请自行搜索安装方法.

$ sudo partprobe

第四步,重新扫描磁盘容量

使用 re­size2fs 命令对 sda1 进行扩容有重扫描容量。

$ sudo resize2fs /dev/sda1
resize2fs 1.42.12 (29-Aug-2014)
Filesystem at /dev/sda1 is mounted on /; on-line resizing required
old_desc_blocks = 3, new_desc_blocks = 10
The filesystem on /dev/sda1 is now 38833617 (4k) blocks long.

第五步,重新配置swap分区

因为 fdisk 对 ext4 扩展分区支持不足,建议使用 cfdisk 进行重新配置 swap 分区。

$ sudo cfdisk

选择 sda2 分区,转换成 82 Linux swap / Solaris 类型并保存。

第六步,重新激活swap分区

$ mkswap /dev/sda2
/dev/sda2
UUID=d58bf1cb-d27a-487d-b337-056767fd5ad6 none swap sw 0 0

记下上面的 UUID。

用命令行重新激活 swap 分区。

$ swapon /dev/sda2

通过命令把上面的 UUID 修改到 fstab 中

$ sudo nano /etc/fstab
# swap was on /dev/sda5 during installation
UUID=d58bf1cb-d27a-487d-b337-056767fd5ad6 none            swap    sw              0       0

确保没有问题后,重启虚拟机。

至此,无损扩容工作便全部完成。

祝你好运!