Linux虚拟机扩充硬盘

前言

由于虚拟机硬盘经常被干满,就需要经常去加盘,每次加盘都要上网搜一下fdisk怎么用,很麻烦,因此,在这篇博客中我将总结一下这个过程,以便以后可以直接查阅。

虚拟机硬盘扩充(fdisk)

当虚拟机硬盘空间不足时,我们该如何处理?通常有两种选择:添加一块新硬盘或者增大原有硬盘的容量。

对于不使用LVM(逻辑卷管理)的情况,添加新硬盘并不容易直接扩展原始分区的容量。这对于像我这样将整个硬盘挂载在根目录(/)下的用户来说并不友好。

因此,通常我们会选择增大原有硬盘的容量。这样一来,fdisk就可以识别到硬盘容量的增加。但是,由于分区表尚未修改,实际可用空间并不会有所变化。

接下来,我们将通过fdisk来扩大分区容量。

数据无价,谨慎操作,如有重要信息,务必提前备份。

查看原始分区表信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
ihopenot@ihopenot-virtual-machine:~$ sudo fdisk /dev/sda

Welcome to fdisk (util-linux 2.34).
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: 100 GiB, 107374182400 bytes, 209715200 sectors
Disk model: Virtual disk
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: 0x07ea7416

Device Boot Start End Sectors Size Id Type
/dev/sda1 * 2048 1050623 1048576 512M b W95 FAT32
/dev/sda2 1052670 188741631 187688962 89.5G 5 Extended
/dev/sda5 1052672 188741631 187688960 89.5G 83 Linux

Command (m for help): F
Unpartitioned space /dev/sda: 10 GiB, 10738466816 bytes, 20973568 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes

Start End Sectors Size
188741632 209715199 20973568 10G

使用sudo fdisk /dev/*来打开硬盘,p查看分区信息,F查看未分配的区域。

可以看到扩充的10个G是硬盘最末尾的区域。

如果sda5是primary分区的话可以直接删除sda5,再新建一个sda5将后面未分配的区域包括进来就行了。由于这里sda5是sda2扩展出来的逻辑分区,所以操作麻烦一点。另外,如果要扩展的分区不是最后一个的话会比较麻烦,可能需要将后面的分区先备份之后再扩展了。

修改分区表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
Command (m for help): p  
Disk /dev/sda: 100 GiB, 107374182400 bytes, 209715200 sectors
Disk model: Virtual disk
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: 0x07ea7416

Device Boot Start End Sectors Size Id Type
/dev/sda1 * 2048 1050623 1048576 512M b W95 FAT32
/dev/sda2 1052670 188741631 187688962 89.5G 5 Extended
/dev/sda5 1052672 188741631 187688960 89.5G 83 Linux // 需要扩充的分区,注意记录一下Start sector的值

Command (m for help): d // 删除2号分区
Partition number (1,2,5, default 5): 2

Partition 2 has been deleted.

Command (m for help): p
Disk /dev/sda: 100 GiB, 107374182400 bytes, 209715200 sectors
Disk model: Virtual disk
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: 0x07ea7416

Device Boot Start End Sectors Size Id Type
/dev/sda1 * 2048 1050623 1048576 512M b W95 FAT32

Command (m for help): n //创建新的extend分区
Partition type
p primary (1 primary, 0 extended, 3 free)
e extended (container for logical partitions)
Select (default p): e
Partition number (2-4, default 2):
First sector (1050624-209715199, default 1050624): // 默认即可,没必要和之前一样
Last sector, +/-sectors or +/-size{K,M,G,T,P} (1050624-209715199, default 209715199):

Created a new partition 2 of type 'Extended' and of size 99.5 GiB.
Partition #2 contains a vfat signature.

Do you want to remove the signature? [Y]es/[N]o: Y // 不确定是否必须移除

The signature will be removed by a write command.

Command (m for help): p
Disk /dev/sda: 100 GiB, 107374182400 bytes, 209715200 sectors
Disk model: Virtual disk
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: 0x07ea7416

Device Boot Start End Sectors Size Id Type
/dev/sda1 * 2048 1050623 1048576 512M b W95 FAT32
/dev/sda2 1050624 209715199 208664576 99.5G 5 Extended

Filesystem/RAID signature on partition 2 will be wiped.

Command (m for help): n // 新建逻辑分区
All space for primary partitions is in use.
Adding logical partition 5
First sector (1052672-209715199, default 1052672): // 起始sector,一定要和之前一样
Last sector, +/-sectors or +/-size{K,M,G,T,P} (1052672-209715199, default 209715199):

Created a new partition 5 of type 'Linux' and of size 99.5 GiB.
Partition #5 contains a ext4 signature.

Do you want to remove the signature? [Y]es/[N]o: Y // 不确定是否必须移除

The signature will be removed by a write command.

Command (m for help): w // 写回磁盘
The partition table has been altered.
Failed to add partition 2 to system: Device or resource busy

The kernel still uses the old partitions. The new table will be used at the next reboot.
Syncing disks.

因为sda5是sda2 extend的逻辑分区,所以这里直接把sda2整个删了重建,不知道为啥只删sda5再重建的话起始sector不在可选范围里。

之后新建sda2,选extend不要选primary,新建sda5,如果让选分区类型就选logical,注意新建sda5的时候起始的sector一定要和之前的分区表一致,不然会丢数据。

如果要扩充的是primary分区,就直接删除重建对应分区就行,也要保证起始sector一致。

扩展文件系统

fdisk将更改写回磁盘后重启一下就能生效了,但是用df看的话可用磁盘空间还是不会变,这是因为虽然分区的容量扩充了,但是上面的文件系统并不知道,需要使用resize2fs将对应分区上的文件系统扩容,之后就能正常使用了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
ihopenot@ihopenot-virtual-machine:~$ df -h
Filesystem Size Used Avail Use% Mounted on
udev 7.8G 0 7.8G 0% /dev
tmpfs 1.6G 1.6M 1.6G 1% /run
/dev/sda5 88G 7.0G 77G 9% / // sda5大小未改变

ihopenot@ihopenot-virtual-machine:~$ sudo resize2fs /dev/sda5
resize2fs 1.45.5 (07-Jan-2020)
Filesystem at /dev/sda5 is mounted on /; on-line resizing required
old_desc_blocks = 12, new_desc_blocks = 13
The filesystem on /dev/sda5 is now 26082816 (4k) blocks long.

ihopenot@ihopenot-virtual-machine:~$ df -h
Filesystem Size Used Avail Use% Mounted on
udev 7.8G 0 7.8G 0% /dev
tmpfs 1.6G 1.6M 1.6G 1% /run
/dev/sda5 98G 7.0G 86G 8% / // 成功扩容

虚拟机硬盘扩充(lvm)

lvm(Logical Volume Manager)是一个逻辑卷管理器,在物理磁盘上抽象出的逻辑分区,由于直接使用物理磁盘的分区存储扩展和管理起来非常麻烦,比如之前说到的,如果磁盘上未分配的区域不是正好在要扩充的分区后面紧贴着,那么扩展这个分区就相当麻烦。在这种情况下,lvm应运而生。

在ubuntu安装的过程中,可以选择开启lvm。之后再进行磁盘的扩充就非常容易了。

扩充lvm的逻辑是,在未分配的磁盘区域或是一块新磁盘上新建一块分区,并在这个分区上创建PV(Physical volume),之后将PV加入到你要扩充的LV(Logical Volume)所在的VG(Volume group),之后扩展LV的容量大小,最后resize一下这个LV上的文件系统。

查看lvm信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
ihopenot@ubuntu:~$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda 8:0 0 30G 0 disk
├─sda1 8:1 0 1M 0 part
├─sda2 8:2 0 1.8G 0 part /boot
└─sda3 8:3 0 18.2G 0 part
└─ubuntu--vg-ubuntu--lv 253:0 0 10G 0 lvm /

ihopenot@ubuntu:~$ sudo lvdisplay
--- Logical volume ---
LV Path /dev/ubuntu-vg/ubuntu-lv
LV Name ubuntu-lv
VG Name ubuntu-vg
LV UUID moq0Mb-SRCu-UfxE-8ZGG-l2TN-LYdA-73CuHH
LV Write Access read/write
LV Creation host, time ubuntu-server, 2023-03-29 09:50:31 +0000
LV Status available
# open 1
LV Size 10.00 GiB
Current LE 2560
Segments 1
Allocation inherit
Read ahead sectors auto
- currently set to 256
Block device 253:0

使用lsblk和lvdisplay查看lvm相关信息,可以发现根目录 / 是挂载的ubuntu–vg-ubuntu-lv逻辑卷。

新建分区

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
Command (m for help): p

Disk /dev/sda: 30 GiB, 32212254720 bytes, 62914560 sectors
Disk model: VMware Virtual S
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: gpt
Disk identifier: 538FA7A9-20C7-4F29-B05C-881BC791F1DF

Device Start End Sectors Size Type
/dev/sda1 2048 4095 2048 1M BIOS boot
/dev/sda2 4096 3719167 3715072 1.8G Linux filesystem
/dev/sda3 3719168 41940991 38221824 18.2G Linux filesystem

Command (m for help): n // 新建一个分区,使用所有剩余空间
Partition number (4-128, default 4):
First sector (41940992-62914526, default 41940992):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (41940992-62914526, default 62914526):

Created a new partition 4 of type 'Linux filesystem' and of size 10 GiB.

Command (m for help): p
Disk /dev/sda: 30 GiB, 32212254720 bytes, 62914560 sectors
Disk model: VMware Virtual S
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: gpt
Disk identifier: 538FA7A9-20C7-4F29-B05C-881BC791F1DF

Device Start End Sectors Size Type
/dev/sda1 2048 4095 2048 1M BIOS boot
/dev/sda2 4096 3719167 3715072 1.8G Linux filesystem
/dev/sda3 3719168 41940991 38221824 18.2G Linux filesystem
/dev/sda4 41940992 62914526 20973535 10G Linux filesystem

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

先将物理硬盘中未分配的区域新建一个分区,之后将这个分区合并到vg (volume group) 中去。

扩充卷组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
ihopenot@ubuntu:~$ sudo vgextend ubuntu-vg /dev/sda4
Physical volume "/dev/sda4" successfully created.
Volume group "ubuntu-vg" successfully extended

ihopenot@ubuntu:~$ sudo vgdisplay
--- Volume group ---
VG Name ubuntu-vg
System ID
Format lvm2
Metadata Areas 2
Metadata Sequence No 3
VG Access read/write
VG Status resizable
MAX LV 0
Cur LV 1
Open LV 1
Max PV 0
Cur PV 2
Act PV 2
VG Size <28.22 GiB
PE Size 4.00 MiB
Total PE 7224
Alloc PE / Size 2560 / 10.00 GiB
Free PE / Size 4664 / <18.22 GiB
VG UUID p1xePf-Ye3h-wFoq-sFBX-kRi6-I3qI-wI0SYj

使用vgextend ubuntu-vg /dev/sda4将在新分区上创建PV并加入ubuntu-vg,可以看到ubuntu-vg中Free PE / Size已经扩充10个G了。

扩充逻辑卷

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
ihopenot@ubuntu:~$ df -h
Filesystem Size Used Avail Use% Mounted on
tmpfs 389M 1.6M 388M 1% /run
/dev/mapper/ubuntu--vg-ubuntu--lv 9.8G 3.2G 6.2G 34% /

ihopenot@ubuntu:~$ sudo lvextend --resizefs -l +50%FREE /dev/ubuntu-vg/ubuntu-lv
Size of logical volume ubuntu-vg/ubuntu-lv changed from 10.00 GiB (2560 extents) to <19.11 GiB (4892 extents).
Logical volume ubuntu-vg/ubuntu-lv successfully resized.
resize2fs 1.46.5 (30-Dec-2021)
Filesystem at /dev/mapper/ubuntu--vg-ubuntu--lv is mounted on /; on-line resizing required
old_desc_blocks = 2, new_desc_blocks = 3
The filesystem on /dev/mapper/ubuntu--vg-ubuntu--lv is now 5009408 (4k) blocks long.

ihopenot@ubuntu:~$ df -h
Filesystem Size Used Avail Use% Mounted on
tmpfs 389M 1.6M 388M 1% /run
/dev/mapper/ubuntu--vg-ubuntu--lv 19G 3.7G 15G 21% /

使用lvextend --resizefs -l +50%FREE /dev/ubuntu-vg/ubuntu-lv来扩充逻辑卷的大小,--resizefs参数会在扩充完成后自动扩充逻辑卷上文件系统的大小。-l +50%FREE指定扩容的大小,这里将50%的剩余空间分配到了当前逻辑卷,可以看到根目录 / 的容量扩充了9个G。