第 6 章 Linux LVM 存储管理
LVM(Logical Volume Manager) 可以让分区变得弹性,可以随时随地的扩大和缩小分区大小,前提是该分区是 LVM 格式的。
LVM 需要使用的软件包为 lvm2,一般在 RHEL 系列发行版中都已经预安装了。
6.1、LVM 相关概念
-
PV(Physical Volume) 即物理卷
硬盘分区后(还未格式化为文件系统)使用 pvcreate 命令可以将分区创建为 pv,要求分区的 system ID 为 8e,即为 LVM 格式的系统标识符。
-
VG(Volume Group) 即卷组
将多个 PV 组合起来,使用 vgcreate 命令创建成卷组,这样卷组包含了多个 PV 就比较大了,相当于重新整合了多个分区后得到的磁盘。
虽然 VG 是整合多个 PV 的,但是创建 VG 时会将 VG 所有的空间根据指定的 PE 大小划分为多个 PE,在 LVM 模式下的存储都以 PE 为单元,类似于文件系统的 Block。
-
PE(Physical Extend)
PE 是 VG 中的存储单元,实际存储的数据都是存储在这里面的。
-
LV(Logical Volume)
VG 相当于整合过的硬盘,那么 LV 就相当于分区,只不过该分区是通过 VG 来划分的。
VG 中有很多 PE 单元,可以指定将多少个 PE 划分给一个 LV,也可以直接指定大小(如多少兆)来划分。
划分为 LV 之后就相当于划分了分区,只需再对 LV 进行格式化即可变成普通的文件系统。
-
LE(logical extent)
PE 是物理存储单元,而 LE 则是逻辑存储单元,也即为 LV 中的逻辑存储单元,和 PE 的大小是一样的。从 VG 中划分 LV,实际上是从 VG 中划分 PE,只不过划分 LV 后它不再称为 PE,而是 LE。
LVM 之所以能够伸缩容量,其实现的方法就是将 LV 里空闲的 PE 移出,或向 LV 中添加空闲的 PE。
以上概念使用逻辑图表示如下:
6.2、LVM 写入机制
LV 是从 VG 中划分出来的,LV 中的 PE 很可能来自于多个 PV。在向 LV 存储数据时,有多种存储机制,其中两种是:
- 线性模式(linear):先写完来自于同一个 PV 的 PE,再写来自于下一个 PV 的 PE。
- 条带模式(striped):一份数据拆分成多份,分别写入该 LV 对应的每个 PV 中,所以读写性能较好,类似于 RAID 0。
尽管 striped 读写性能较好也不建议使用该模式,因为 lvm 的着重点在于弹性容量扩展而非性能,要实现性能应该使用 RAID 来实现,而且使用 striped 模式时要进行容量的扩展和收缩将比较麻烦。
默认的是使用线性模式。
6.3、LVM 的实现
准备一个如上图的环境:我们使用一台 ARM64 架构的飞腾 2000+ 的物理服务器上的一台虚拟机实现。
首先需要将 /dev/sda 下的分区 /dev/sda{1,2,3,4} 修改为 LVM 格式的标识符。mbr 格式下标识符是 8e,gpt 格式下是 8300。
[root@arm64v8 ~]# gdisk -l /dev/sda
GPT fdisk (gdisk) version 0.8.10
Partition table scan:
MBR: protective
BSD: not present
APM: not present
GPT: present
Found valid GPT with protective MBR; using GPT.
Disk /dev/sda: 2147483648 sectors, 1024.0 GiB
Logical sector size: 512 bytes
Disk identifier (GUID): 2CBEB962-B6BD-4A42-AB11-56100F9BCC9D
Partition table holds up to 128 entries
First usable sector is 34, last usable sector is 2147483614
Partitions will be aligned on 2048-sector boundaries
Total free space is 1098907581 sectors (524.0 GiB)
Number Start (sector) End (sector) Size Code Name
1 2048 209717247 100.0 GiB 8300 Linux filesystem
2 209717248 419432447 100.0 GiB 8300 Linux filesystem
3 419432448 629147647 100.0 GiB 8300 Linux filesystem
4 629147648 838862847 100.0 GiB 8300 Linux filesystem
5 838862848 1048578047 100.0 GiB 8300 Linux filesystem
[root@arm64v8 ~]#
6.3.1、管理 PV
命令 | |
---|---|
pvcreate | 创建 PV |
pvscan | 扫描并列出所有的 pv |
pvdisplay | 列出 pv 属性信息 |
pvremove | 移除 pv |
pvmove | 移动 pv 中的数据 |
其中 pvscan 搜索目前有哪些 pv,扫描之后将结果放在缓存中;pvdisplay 会显示每个 pv 的详细信息,如 PV name 和 pv size 以及所属的 VG 等。
# 将 /dev/sda{1,2,3,4} 创建 pv
[root@arm64v8 ~]# pvcreate -y /dev/sda{1,2,3,4} # -y选项用于自动回答yes
# 使用pvscan来查看哪些pv和基本属性。
[root@arm64v8 ~]# pvscan
PV /dev/sda4 lvm2 [<102.40 GiB]
PV /dev/sda3 lvm2 [102.40 GiB]
PV /dev/sda2 lvm2 [<102.40 GiB]
PV /dev/sda1 lvm2 [<102.40 GiB]
Total: 4 [<409.60 GiB] / in use: 0 [0 ] / in no VG: 4 [<409.60 GiB]
[root@arm64v8 ~]#
注意最后一行显示的是 "pv 的总容量 / 已使用的 pv 容量 / 空闲的 pv 容量"
使用 pvdisplay 查看其中一个 pv 的属性信息。
[root@arm64v8 ~]# pvdisplay /dev/sda1
"/dev/sda1" is a new physical volume of "<102.40 GiB"
--- NEW Physical volume ---
PV Name /dev/sda1
VG Name
PV Size <102.40 GiB
Allocatable NO
PE Size 0
Total PE 0
Free PE 0
Allocated PE 0
PV UUID p9jsx0-AJIY-rWCf-eomh-mNTN-55eQ-dUo9C2
[root@arm64v8 ~]#
pvdisplay 还有一个很重要的选项 "-m",可以查看该设备中 PE 的使用分布图。以下是某次显示结果。
[root@arm64v8 ~]# pvdisplay -m /dev/sda2
--- Physical volume ---
PV Name /dev/sda2
VG Name BrinnattVg
PV Size <102.40 GiB / not usable 9.00 MiB
Allocatable yes
PE Size 16.00 MiB
Total PE 6553
Free PE 4454
Allocated PE 2099
PV UUID rQv2z4-VKB8-3kFq-X3Lr-iaP7-donM-sWAx3N
--- Physical Segments ---
Physical extent 0 to 4453:
FREE
Physical extent 4454 to 6552:
Logical volume /dev/BrinnattVg/first_lv
Logical extents 10807 to 12905
[root@arm64v8 ~]#
知道了 PE 的分布,就可以轻松地使用 pvmove 命令在设备之间进行 PE 数据的移动。具体关于 pvmove 的用法,请对照后文中的 lvm 缩容部分。
再测试 pvremove,移除 /dev/sda4,然后将其添加回 pv。
[root@arm64v8 ~]# pvremove /dev/sda4
Labels on physical volume "/dev/sda4" successfully wiped.
[root@arm64v8 ~]#
[root@arm64v8 ~]# pvcreate /dev/sda4
Physical volume "/dev/sda4" successfully created.
[root@arm64v8 ~]#
6.3.2、管理 VG
管理VG也有几个命令。
命令 | 功能 |
---|---|
vgcreate | 创建 VG |
vgscan | 扫描并列出所有的 vg |
vgdisplay | 列出 vg 属性信息 |
vgremove | 移除 vg,即删除 vg |
vgreduce | 从 vg 中移除 pv |
vgextend | 将 pv 添加到 vg 中 |
vgchange | 修改 vg 属性 |
创建一个 vg,并将上述 4 个 pv /dev/sda{1,2,3,4} 都添加到该 vg 中。
注意 vg 是需要命名的,vg 可以等同于磁盘的层次,而磁盘是有名称的,如 /dev/sdb,/dev/sdc 等。
同时创建 vg 时可以使用 -s 选项指定 pe 的大小,如果不指定默认为 4M。
[root@arm64v8 ~]# vgcreate -s 16M BrinnattVg /dev/sda{1,2,3,4}
Volume group "BrinnattVg" successfully created
[root@arm64v8 ~]#
此处创建的 vg 名称为BrinnattVg,指定 pe 大小为 16M。创建 vg 后,是很难再修改 pe 大小的,只有空数据的 vg 可以修改,但这样还不如重新创建 vg。
注意,lvm1 中每个 vg 中只能有 65534 个 pe,所以指定 pe 的大小能改变每个 vg 的最大容量。但在 lvm2 中已经没有该限制了,而现在说的 lvm 一般都指 lvm2,这也是默认的版本。
创建了 vg 实际上是在 /dev 目录下管理了一个 vg 目录 /dev/BrinnattVg,不过只有在创建了 lv 该目录才会被创建,而该 vg 中创建 lv,将会在该目录下生成链接文件指向 /dev/dm 设备。
# vgscan 查看
[root@arm64v8 ~]# vgscan
Reading volume groups from cache.
Found volume group "BrinnattVg" using metadata type lvm2
[root@arm64v8 ~]#
# vgdisplay 查看
[root@arm64v8 ~]# vgdisplay BrinnattVg
--- Volume group ---
VG Name BrinnattVg
System ID
Format lvm2
Metadata Areas 4
Metadata Sequence No 1
VG Access read/write
VG Status resizable
MAX LV 0
Cur LV 0
Open LV 0
Max PV 0
Cur PV 4
Act PV 4
VG Size 409.56 GiB
PE Size 16.00 MiB
Total PE 26212
Alloc PE / Size 0 / 0
Free PE / Size 26212 / 409.56 GiB
VG UUID 2TFj3n-4hVL-N0ui-jyUG-j7YL-wQBM-lPil4v
[root@arm64v8 ~]#
从 vg 中移除一个 pv,如 /dev/sda4,再 vgdisplay,发现 pv 少了一个,pe 相应的也减少了。
[root@arm64v8 ~]# vgreduce BrinnattVg /dev/sda4
Removed "/dev/sda4" from volume group "BrinnattVg"
[root@arm64v8 ~]#
[root@arm64v8 ~]# vgdisplay BrinnattVg
--- Volume group ---
VG Name BrinnattVg
System ID
Format lvm2
Metadata Areas 3
Metadata Sequence No 2
VG Access read/write
VG Status resizable
MAX LV 0
Cur LV 0
Open LV 0
Max PV 0
Cur PV 3
Act PV 3
VG Size 307.17 GiB
PE Size 16.00 MiB
Total PE 19659
Alloc PE / Size 0 / 0
Free PE / Size 19659 / 307.17 GiB
VG UUID 2TFj3n-4hVL-N0ui-jyUG-j7YL-wQBM-lPil4v
[root@arm64v8 ~]#
再将 /dev/sda4 加入 vg。
[root@arm64v8 ~]# vgextend BrinnattVg /dev/sda4
Volume group "BrinnattVg" successfully extended
[root@arm64v8 ~]#
vgchange 用于设置卷组的活动状态,卷组的激活状态主要影响的是 lv。使用 -a 选项来设置。
# 将BrinnattVg设置为活动状态(active yes)。
[root@arm64v8 ~]# vgchange -a y BrinnattVg
0 logical volume(s) in volume group "BrinnattVg" now active
[root@arm64v8 ~]#
# 将BrinnattVg设置为非激活状态(active no)。
[root@arm64v8 ~]# vgchange -a n BrinnattVg
0 logical volume(s) in volume group "BrinnattVg" now active
[root@arm64v8 ~]#
- 目前还没有创建 lv 层,所以激不激活实际上没有什么意思,卷组的激活状态主要影响的是 lv。
6.3.3、管理 LV
有了 vg 之后就可以根据 vg 进行分区,即创建 LV。管理 lv 也有类似的一些命令。
命令 | 功能 |
---|---|
lvcreate | 创建 LV |
lvscan | 扫描并列出所有的 lv |
lvdisplay | 列出 lv 属性信息 |
lvremove | 移除 lv,即删除 lv |
lvreduce(lvresize) | 缩小 lv 容量 |
lvextend(lvresize) | 增大 lv 容量 |
lvresize | 改变 lv 容量 |
lvcreate 命令常用的几个选项
lvcreate {-L size(M/G) | -l PEnum} -n lv_name vg_name
选项说明:
-L:根据大小来创建lv,即分配多大空间给此lv
-l:根据PE的数量来创建lv,即分配多少个pe给此lv,可以是百分比
-n:指定lv的名称
前面创建的 vg 有 26212 个 PE,总容量为 409.56GiB。
[root@arm64v8 ~]# vgdisplay | grep PE
PE Size 16.00 MiB
Total PE 26212
Alloc PE / Size 0 / 0
Free PE / Size 26212 / 409.56 GiB
[root@arm64v8 ~]#
使用 -L 和 -l 分别创建名称为 first_lv 和 second_lv 的 lv。
[root@arm64v8 ~]# lvcreate -L 10G -n first_lv BrinnattVg
Logical volume "first_lv" created.
[root@arm64v8 ~]#
[root@arm64v8 ~]# lvcreate -l 200 -n second_lv BrinnattVg
Logical volume "second_lv" created.
[root@arm64v8 ~]#
创建 lv 后,将在 /dev/BrinnattVg 目录中创建对应 lv 名称的软链接文件,同时也在 /dev/mapper 目录下创建链接文件,它们都指向 /dev/dm 设备。
[root@arm64v8 ~]# ll /dev/BrinnattVg/
total 0
lrwxrwxrwx 1 root root 7 Jun 23 09:03 first_lv -> ../dm-0
lrwxrwxrwx 1 root root 7 Jun 23 09:04 second_lv -> ../dm-1
[root@arm64v8 ~]#
[root@arm64v8 ~]# ll /dev/mapper/
total 0
lrwxrwxrwx 1 root root 7 Jun 23 09:03 BrinnattVg-first_lv -> ../dm-0
lrwxrwxrwx 1 root root 7 Jun 23 09:04 BrinnattVg-second_lv -> ../dm-1
crw------- 1 root root 10, 236 Jun 23 09:03 control
[root@arm64v8 ~]#
使用 lvscan 和 lvdisplay 查看 lv 信息。需要注意的是,如果 lvdisplay 要显示某一个指定的 lv,需要指定其全路径,而不能简单的指定 lv 名,当然如果不指定任何参数将显示所有 lv 的信息。
[root@arm64v8 ~]# lvscan
ACTIVE '/dev/BrinnattVg/first_lv' [10.00 GiB] inherit
ACTIVE '/dev/BrinnattVg/second_lv' [3.12 GiB] inherit
[root@arm64v8 ~]# lvdisplay /dev/BrinnattVg/first_lv
--- Logical volume ---
LV Path /dev/BrinnattVg/first_lv
LV Name first_lv
VG Name BrinnattVg
LV UUID HKjlKO-vYVZ-vg6b-q3kZ-YtM0-RnhF-uXIxX9
LV Write Access read/write
LV Creation host, time arm64v8, 2021-06-23 09:03:15 +0800
LV Status available
# open 0
LV Size 10.00 GiB
Current LE 640
Segments 1
Allocation inherit
Read ahead sectors auto
- currently set to 8192
Block device 252:0
[root@arm64v8 ~]#
6.3.4、格式化 lv 文件系统
对 lv 进行格式化,即可形成文件系统,然后进行挂载使用。
[root@arm64v8 ~]# mkfs.xfs /dev/BrinnattVg/first_lv
meta-data=/dev/BrinnattVg/first_lv isize=512 agcount=4, agsize=655360 blks
= sectsz=512 attr=2, projid32bit=1
= crc=1 finobt=0, sparse=0
data = bsize=4096 blocks=2621440, imaxpct=25
= sunit=0 swidth=0 blks
naming =version 2 bsize=4096 ascii-ci=0 ftype=1
log =internal log bsize=4096 blocks=2560, version=2
= sectsz=512 sunit=0 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0
[root@arm64v8 ~]#
查看 lv 格式化的文件系统大小和类型
# 上面格式化后,可以直接挂载使用
[root@arm64v8 ~]# mount /dev/BrinnattVg/first_lv /mnt/
[root@arm64v8 ~]# mount | grep /mnt
/dev/mapper/BrinnattVg-first_lv on /mnt type xfs (rw,relatime,attr2,inode64,noquota)
[root@arm64v8 ~]#
# 查看此时 first_lv 文件系统的大小
[root@arm64v8 ~]# df -h | grep /mnt
/dev/mapper/BrinnattVg-first_lv 10G 33M 10G 1% /mnt
[root@arm64v8 ~]#
# 查看 first_lv 文件系统类型
[root@arm64v8 ~]# file -s /dev/dm-0
/dev/dm-0: SGI XFS filesystem data (blksz 4096, inosz 512, v2 dirs)
[root@arm64v8 ~]#
- 如果使用 file -s 查看,要注意,/dev/BrinnattVg 和 /dev/mapper 下的 lv 都是链接到 /dev/ 下块设备的链接文件,所以只能对块设备进行查看,否则查看的结果也仅仅只是个链接文件类型。
再去看看 /dev/sda 的情况。
[root@arm64v8 ~]# lsblk -f /dev/sda
NAME FSTYPE LABEL UUID MOUNTPOINT
sda
├─sda4 LVM2_member O33Drf-4Hei-Q0LA-46ip-4OcY-zHbA-gcExVK
├─sda2 LVM2_member rQv2z4-VKB8-3kFq-X3Lr-iaP7-donM-sWAx3N
├─sda5
├─sda3 LVM2_member 3DjHsv-VBiR-2A7D-2VWM-91U5-XnAu-hUbrzW
└─sda1 LVM2_member p9jsx0-AJIY-rWCf-eomh-mNTN-55eQ-dUo9C2
├─BrinnattVg-second_lv
└─BrinnattVg-first_lv xfs 90543211-66da-404f-800d-16f4da95a82e /mnt
[root@arm64v8 ~]#
6.4、LVM 扩容
lvm 最大的优势就是其可伸缩性,而其伸缩性又更偏重于扩容,这时使用 lvm 的最大原因。
扩容的实质是将 vg 中空闲的 pe 添加到 lv 中,所以只要 vg 中有空闲的 pe,就可以进行扩容,即使没有空闲的 pe,也可以添加 pv,将 pv 加入到 vg 中增加空闲 pe。
扩容的两个关键步骤如下:
- 使用 lvextend 或者 lvresize 添加更多的 pe 或容量到 lv 中
- 使用 resize2fs 命令(xfs则使用xfs_growfs)将 lv 增加后的容量增加到对应的文件系统中(此过程是修改文件系统而非 LVM 内容)
举例:将一直没用到的 /dev/sda5 作为 first_lv 的扩容来源。首先将 /dev/sda5 创建成 pv,加入到 BrinnattVg 中。
[root@arm64v8 ~]# parted /dev/sda toggle 5 lvm
Information: You may need to update /etc/fstab.
[root@arm64v8 ~]# pvcreate /dev/sda5
Physical volume "/dev/sda5" successfully created.
[root@arm64v8 ~]#
[root@arm64v8 ~]# vgextend BrinnattVg /dev/sda5
Volume group "BrinnattVg" successfully extended
[root@arm64v8 ~]#
查看 BrinnattVg 中空闲的 pe 数量。
[root@arm64v8 ~]# vgdisplay BrinnattVg | grep -i pe
Open LV 1
PE Size 16.00 MiB
Total PE 32765
Alloc PE / Size 840 / 13.12 GiB
Free PE / Size 31925 / <498.83 GiB
[root@arm64v8 ~]#
现在 vg 中有 31925 个 PE 共 498.83GiB 容量可用。将其全部添加到 first_lv 中,有两种方式添加:按容量大小添加和按 PE 数量添加。
# 先卸载 first_lv
[root@arm64v8 ~]# umount /dev/BrinnattVg/first_lv
# 按容量大小添加
[root@arm64v8 ~]# lvextend -L +20G /dev/BrinnattVg/first_lv
Size of logical volume BrinnattVg/first_lv changed from 10.00 GiB (640 extents) to 30.00 GiB (1920 extents).
Logical volume BrinnattVg/first_lv successfully resized.
[root@arm64v8 ~]#
# 查看分配了多少PE,还剩下多少PE
[root@arm64v8 ~]# vgdisplay BrinnattVg | grep -i pe
Open LV 0
PE Size 16.00 MiB
Total PE 32765
Alloc PE / Size 2120 / 33.12 GiB
Free PE / Size 30645 / <478.83 GiB
[root@arm64v8 ~]#
# 按PE数量添加,使用百分比的方式,+10%FREE 表示未分配的 PE 的 10%
[root@arm64v8 ~]# lvextend -l +10%FREE /dev/BrinnattVg/first_lv
Size of logical volume BrinnattVg/first_lv changed from 30.00 GiB (1920 extents) to 77.89 GiB (4985 extents).
Logical volume BrinnattVg/first_lv successfully resized.
[root@arm64v8 ~]#
# 查看分配了多少PE,还剩下多少PE
[root@arm64v8 ~]# vgdisplay BrinnattVg | grep -i pe
Open LV 0
PE Size 16.00 MiB
Total PE 32765
Alloc PE / Size 5185 / <81.02 GiB
Free PE / Size 27580 / <430.94 GiB
[root@arm64v8 ~]#
# 按PE数量添加,使用PE个数
[root@arm64v8 ~]# lvextend -l +7580 /dev/BrinnattVg/first_lv
Size of logical volume BrinnattVg/first_lv changed from 77.89 GiB (4985 extents) to <196.33 GiB (12565 extents).
Logical volume BrinnattVg/first_lv successfully resized.
[root@arm64v8 ~]#
[root@arm64v8 ~]# vgdisplay BrinnattVg | grep -i pe
Open LV 0
PE Size 16.00 MiB
Total PE 32765
Alloc PE / Size 12765 / 199.45 GiB
Free PE / Size 20000 / 312.50 GiB
[root@arm64v8 ~]#
也可以使用 lvresize 来增加 lv 的容量方法和 lvextend 一样。
[root@arm64v8 ~]# vgdisplay BrinnattVg | grep -i pe
Open LV 0
PE Size 16.00 MiB
Total PE 32765
Alloc PE / Size 12765 / 199.45 GiB
Free PE / Size 20000 / 312.50 GiB
[root@arm64v8 ~]#
[root@arm64v8 ~]# lvresize -L +20G /dev/BrinnattVg/first_lv
Size of logical volume BrinnattVg/first_lv changed from <196.33 GiB (12565 extents) to <216.33 GiB (13845 extents).
Logical volume BrinnattVg/first_lv successfully resized.
[root@arm64v8 ~]#
[root@arm64v8 ~]# vgdisplay BrinnattVg | grep -i pe
Open LV 0
PE Size 16.00 MiB
Total PE 32765
Alloc PE / Size 14045 / 219.45 GiB
Free PE / Size 18720 / 292.50 GiB
[root@arm64v8 ~]#
[root@arm64v8 ~]# lvresize -l +720 /dev/BrinnattVg/first_lv
Size of logical volume BrinnattVg/first_lv changed from <216.33 GiB (13845 extents) to <227.58 GiB (14565 extents).
Logical volume BrinnattVg/first_lv successfully resized.
[root@arm64v8 ~]#
[root@arm64v8 ~]# vgdisplay BrinnattVg | grep -i pe
Open LV 0
PE Size 16.00 MiB
Total PE 32765
Alloc PE / Size 14765 / 230.70 GiB
Free PE / Size 18000 / 281.25 GiB
[root@arm64v8 ~]#
将 first_lv 挂载,查看该 lv 对应文件系统的容量。
[root@arm64v8 ~]# mount /dev/mapper/BrinnattVg-first_lv /mnt/
[root@arm64v8 ~]# df -hT /mnt/
Filesystem Type Size Used Avail Use% Mounted on
/dev/mapper/BrinnattVg-first_lv xfs 10G 33M 10G 1% /mnt
[root@arm64v8 ~]#
-
发现 first_lv 此时的容量大小跟前面刚刚创建 first_lv 大小一样,lvextend 多次并没有生效?
- 实际上并不是这样,lvextend 当然生效了,只不过增加的是 lv 逻辑卷的容量,lv 上面的文件系统并没有增加(看开篇那个图理解)。
- 增加 lv 逻辑卷上面的文件系统边界需要借助工具完成;resize2fs 工具用来改变 ext 文件系统的大小,如果是 xfs 文件系统,则使用 xfs_growfs。
-
使用 xfs_growfs 扩展 first_lv 文件系统边界。使 lvextend 变得彻底有意义。
# 此命令常用方式,-d 表示 lv 边界有多大就到多大;-D 指定大小 xfs_growfs -d | -D size mount-point [root@arm64v8 ~]# df -hT /mnt/ Filesystem Type Size Used Avail Use% Mounted on /dev/mapper/BrinnattVg-first_lv xfs 10G 33M 10G 1% /mnt [root@arm64v8 ~]# [root@arm64v8 ~]# xfs_growfs -d /mnt/ meta-data=/dev/mapper/BrinnattVg-first_lv isize=512 agcount=4, agsize=655360 blks = sectsz=512 attr=2, projid32bit=1 = crc=1 finobt=0 spinodes=0 data = bsize=4096 blocks=2621440, imaxpct=25 = sunit=0 swidth=0 blks naming =version 2 bsize=4096 ascii-ci=0 ftype=1 log =internal bsize=4096 blocks=2560, version=2 = sectsz=512 sunit=0 blks, lazy-count=1 realtime =none extsz=4096 blocks=0, rtextents=0 data blocks changed from 2621440 to 59658240 [root@arm64v8 ~]# [root@arm64v8 ~]# df -hT /mnt/ Filesystem Type Size Used Avail Use% Mounted on /dev/mapper/BrinnattVg-first_lv xfs 228G 37M 228G 1% /mnt [root@arm64v8 ~]#
接下来,使用 second_lv 逻辑卷创建 ext 文件系统,使用 lvextend 扩容,再使用 resize2fs 扩展文件系统边界。
# resize2fs 常用语法
resize2fs [ -fp ] device [ size ]
[root@arm64v8 ~]# mkfs.ext4 /dev/mapper/BrinnattVg-second_lv
[root@arm64v8 ~]# mount /dev/mapper/BrinnattVg-second_lv /media/
[root@arm64v8 ~]# df -h | grep /media
/dev/mapper/BrinnattVg-second_lv 3.1G 9.4M 2.9G 1% /media
[root@arm64v8 ~]#
[root@arm64v8 ~]# lvextend -L +20G /dev/BrinnattVg/second_lv
Size of logical volume BrinnattVg/second_lv changed from 3.12 GiB (200 extents) to 23.12 GiB (1480 extents).
Logical volume BrinnattVg/second_lv successfully resized.
[root@arm64v8 ~]#
[root@arm64v8 ~]# resize2fs /dev/mapper/BrinnattVg-second_lv
resize2fs 1.42.9 (28-Dec-2013)
Filesystem at /dev/mapper/BrinnattVg-second_lv is mounted on /media; on-line resizing required
old_desc_blocks = 1, new_desc_blocks = 3
The filesystem on /dev/mapper/BrinnattVg-second_lv is now 6062080 blocks long.
[root@arm64v8 ~]#
[root@arm64v8 ~]# df -h | grep /media
/dev/mapper/BrinnattVg-second_lv 23G 18M 22G 1% /media
[root@arm64v8 ~]#
-
对于 linux 2.6 内核之后的版本,支持在线 resize 而无需卸载,我这个 arm64v8 的系统内核版本较高 "Linux arm64v8 4.14.0-49.el7a.aarch64",在线 resize 成功。
-
resize2fs 一般无需使用选项,直接使用 resize2fs device 的方式即可,如果失败则尝试使用 -f 选项强制改变大小。
-
还有一个小技巧,lvextend -r 选项可以调用 resize2fs,也就是说使用 lvextend 扩容 lv 的同时,文件系统边界会自动随之扩大。
[root@arm64v8 ~]# df -h /media/ Filesystem Size Used Avail Use% Mounted on /dev/mapper/BrinnattVg-second_lv 23G 18M 22G 1% /media [root@arm64v8 ~]# [root@arm64v8 ~]# lvextend -L +20G -r /dev/BrinnattVg/second_lv Size of logical volume BrinnattVg/second_lv changed from 23.12 GiB (1480 extents) to 43.12 GiB (2760 extents). Logical volume BrinnattVg/second_lv successfully resized. resize2fs 1.42.9 (28-Dec-2013) Filesystem at /dev/mapper/BrinnattVg-second_lv is mounted on /media; on-line resizing required old_desc_blocks = 3, new_desc_blocks = 6 The filesystem on /dev/mapper/BrinnattVg-second_lv is now 11304960 blocks long. [root@arm64v8 ~]# df -h /media/ Filesystem Size Used Avail Use% Mounted on /dev/mapper/BrinnattVg-second_lv 43G 21M 41G 1% /media [root@arm64v8 ~]#
6.5、LVM 缩容
在生产应用环境中,不要考虑缩容,因为这并不安全,有丢失数据的风险。ext 文件系统支持缩容,xfs 文件系统不支持收缩。
下面我们接着上面已有的环境对 second_lv 玩一下缩容,理解一下 pvdisplay 和 pvmove 两个命令。
严格按照以下步骤执行:
-
首先卸载设备并使用 resize2fs 收缩文件系统的容量为目标大小
[root@arm64v8 ~]# ls /media/ anaconda-ks.cfg test1-ks.cfg test2-ky.cfgg test2-kzz.cfg lost+found test2-kx.cfg test2-kz.cfg [root@arm64v8 ~]# [root@arm64v8 ~]# [root@arm64v8 ~]# df -h /media/ Filesystem Size Used Avail Use% Mounted on /dev/mapper/BrinnattVg-second_lv 43G 21M 41G 1% /media [root@arm64v8 ~]# [root@arm64v8 ~]# umount /media [root@arm64v8 ~]# [root@arm64v8 ~]# e2fsck -f /dev/mapper/BrinnattVg-second_lv e2fsck 1.42.9 (28-Dec-2013) Pass 1: Checking inodes, blocks, and sizes Pass 2: Checking directory structure Pass 3: Checking directory connectivity Pass 4: Checking reference counts Pass 5: Checking group summary information /dev/mapper/BrinnattVg-second_lv: 17/2826240 files (0.0% non-contiguous), 198939/11304960 blocks [root@arm64v8 ~]# [root@arm64v8 ~]# resize2fs /dev/mapper/BrinnattVg-second_lv 10G resize2fs 1.42.9 (28-Dec-2013) Resizing the filesystem on /dev/mapper/BrinnattVg-second_lv to 2621440 (4k) blocks. The filesystem on /dev/mapper/BrinnattVg-second_lv is now 2621440 blocks long. [root@arm64v8 ~]#
- 查看一下挂载点里面的文件,实验完后,看还是不是完整的。
- 确保缩容后可以容纳所有数据。
- 不得在线缩容,必须卸载。
- 使用 e2fsck 检查文件系统一致性。
- 最后缩容文件系统边界到多大。
-
再收缩 lv。可以直接使用 "-L" 指定收缩容量,也可以使用 "-l" 指定收缩的 PE 数量。
[root@arm64v8 ~]# lvreduce -L 10G /dev/BrinnattVg/second_lv WARNING: Reducing active logical volume to 10.00 GiB. THIS MAY DESTROY YOUR DATA (filesystem etc.) Do you really want to reduce BrinnattVg/second_lv? [y/n]: y Size of logical volume BrinnattVg/second_lv changed from 43.12 GiB (2760 extents) to 10.00 GiB (640 extents). Logical volume BrinnattVg/second_lv successfully resized. [root@arm64v8 ~]#
- 发现有警告:可能会损毁你的数据。
- 如果在该 lv 下存储的实际数据大于收缩后的容量,那么肯定会损毁一部分数据,但是如果存储的数据小于收缩后的容量,那么就不会损毁任何数据,这是 lvm 无损修改分区大小的优点。
-
pvmove 移动 PE
上面过程已将 second_lv 从 43G 缩容至 10G,那么此时要移除 pv 的话,移除谁怎么移呢?
[root@arm64v8 ~]# pvdisplay | grep "PV Name\|Free" PV Name /dev/sda1 Free PE 0 PV Name /dev/sda2 Free PE 0 PV Name /dev/sda3 Free PE 4454 PV Name /dev/sda4 Free PE 6553 PV Name /dev/sda5 Free PE 6553 [root@arm64v8 ~]#
- 查看空闲的 PE 分布在 /dev/sda3、/dev/sda4 和 /dev/sda5 上,所以 /dev/sda2 并不能卸载。
- 那么现在需要做的事情是将 /dev/sda2 上的 PE 移到其他设备上,使 /dev/sda2 空闲出来。
使用 pvmove 命令,该命令的执行内部会涉及到不少步骤,所以可能会消耗点时间。
[root@arm64v8 ~]# pvmove /dev/sda2:0-4453 /dev/sda3 /dev/sda2: Moved: 0.00% /dev/sda2: Moved: 1.37% /dev/sda2: Moved: 2.81% /dev/sda2: Moved: 4.15% /dev/sda2: Moved: 5.59% /dev/sda2: Moved: 6.98% /dev/sda2: Moved: 8.42% /dev/sda2: Moved: 9.81% ...... /dev/sda2: Moved: 98.65% /dev/sda2: Moved: 100.00% [root@arm64v8 ~]# [root@arm64v8 ~]# pvdisplay | grep "PV Name\|Free" PV Name /dev/sda1 Free PE 0 PV Name /dev/sda2 Free PE 4454 PV Name /dev/sda3 Free PE 0 PV Name /dev/sda4 Free PE 6553 PV Name /dev/sda5 Free PE 6553 [root@arm64v8 ~]#
- 刚才 /dev/sda3 PE 空闲 4454个,现在把 /dev/sda2 上的 0-4453 共 4454 个 PE 移动到了 /dev/sda3,所以 /dev/sda3 上面已经没有空闲的 PE 了,而 /dev/sda2 空闲出 4454 个 PE。
再移动 /dev/sda2 上剩余的 PE 到 /dev/sda4 上,但此时应该先看看 /dev/sda2 上仍被占用的 PE 编号是哪些。
[root@arm64v8 ~]# pvdisplay -m /dev/sda2 --- Physical volume --- PV Name /dev/sda2 VG Name BrinnattVg PV Size <102.40 GiB / not usable 9.00 MiB Allocatable yes PE Size 16.00 MiB Total PE 6553 Free PE 4454 Allocated PE 2099 PV UUID rQv2z4-VKB8-3kFq-X3Lr-iaP7-donM-sWAx3N --- Physical Segments --- Physical extent 0 to 4453: FREE Physical extent 4454 to 6552: Logical volume /dev/BrinnattVg/first_lv Logical extents 10807 to 12905 [root@arm64v8 ~]#
- 从 Physical Segments 可以看出,还有 4454 to 6552 个 PE。
把 /dev/sda2 上剩余的 4454 to 6552 个 PE 移到 /dev/sda4 上去。
[root@arm64v8 ~]# pvmove /dev/sda2:4454-6552 /dev/sda4 /dev/sda2: Moved: 0.00% /dev/sda2: Moved: 2.95% /dev/sda2: Moved: 5.91% /dev/sda2: Moved: 8.91% /dev/sda2: Moved: 11.82% /dev/sda2: Moved: 14.82% ...... /dev/sda2: Moved: 96.76% /dev/sda2: Moved: 99.67% [root@arm64v8 ~]# [root@arm64v8 ~]# pvdisplay | grep "PV Name\|Free" PV Name /dev/sda1 Free PE 0 PV Name /dev/sda2 Free PE 6553 PV Name /dev/sda3 Free PE 0 PV Name /dev/sda4 Free PE 4454 PV Name /dev/sda5 Free PE 6553 [root@arm64v8 ~]#
查看 /dev/sda2 是否已经完全空闲了
[root@arm64v8 ~]# pvdisplay -m /dev/sda2 --- Physical volume --- PV Name /dev/sda2 VG Name BrinnattVg PV Size <102.40 GiB / not usable 9.00 MiB Allocatable yes PE Size 16.00 MiB Total PE 6553 Free PE 6553 Allocated PE 0 PV UUID rQv2z4-VKB8-3kFq-X3Lr-iaP7-donM-sWAx3N --- Physical Segments --- Physical extent 0 to 6552: FREE [root@arm64v8 ~]#
- 从结果来看,/dev/sda2 PE 已经完全空闲下来了。
-
从 vg 中移除 pv
将 /dev/sda2 从 BrinnattVg 中移除
[root@arm64v8 ~]# vgreduce BrinnattVg /dev/sda2 Removed "/dev/sda2" from volume group "BrinnattVg" [root@arm64v8 ~]#
-
移除该 pv
[root@arm64v8 ~]# pvremove /dev/sda2 Labels on physical volume "/dev/sda2" successfully wiped. [root@arm64v8 ~]# # 查看 /dev/sda2 已经移除了 [root@arm64v8 ~]# pvs PV VG Fmt Attr PSize PFree /dev/sda1 BrinnattVg lvm2 a-- 102.39g 0 /dev/sda3 BrinnattVg lvm2 a-- 102.39g 0 /dev/sda4 BrinnattVg lvm2 a-- 102.39g 69.59g /dev/sda5 BrinnattVg lvm2 a-- 102.39g 102.39g [root@arm64v8 ~]#