1. 前言
不知道大家在使用 Linux 系统的时候是否遇到过某个目录空间不足的问题,尤其像在一些自动归档备份的环境里面,经常会由于数据的不断增长导致空间被爆。我曾经遇到过一个用户,Oracle 数据库直接装在了根目录下,后来因为归档日志太多,导致根目录被撑爆,系统直接重启后无法正常加载系统。当时我直接在救援模式下先删除了一些不必要的大文件,腾出一部分空间来保证系统可以正常重启,因为根目录使用了 LVM 卷进行挂载,我 SSH 连到系统以后直接加盘对 LVM 卷进行了扩容,顺便也清除了一波过期的归档日志,很快就恢复了用户的数据库环境,后面也建议用户更换了数据库路径。在那个时候,我就感觉大了 LVM 卷强大。
一般来说,除了一些特殊的业务需求,我习惯性都会使用 LVM 卷来挂载文件系统,它的好处就在于我可以动态的去管理目录空间,不需要担心空间扩容难甚至无法扩容的问题。LVM 全称为 Logical Volume Manager,即逻辑卷管理器。LVM 会根据物理存储生成逻辑上的卷组,以便创建逻辑存储卷,这样就比直接使用物理存储在很多方面提供了更大的灵活性,使用逻辑卷比直接使用物理存储时有以下优势:
- 更加灵活的容量管理;
- 在线数据重新定位;
- 更加便捷的设备明明;
- 磁盘条带化;
- 镜像卷;
- 卷快照。
接下来,我会结合 LVM 简易版的架构图以及常用的命令来做一个分享。
2. 浅谈 LVM 结构
如上图所示,从底层物理存储到上层系统的目录,并不是单纯的将某块磁盘或者某个磁盘分区进行格式化,然后挂载给系统目录去使用,而是隔了一道 LVM 层。
底层的裸盘,或者是磁盘分区,都可以被创建成为一个 PV(Physical Volume),而一个 VG(Volume Group) 至少由一个 PV 组成。此时我们可以将 VG 看成是一个大的存储池,我们可以根据实际需求,从 VG 池子里面创建一个甚至多个 LV(Logical Volume),此时的 LV 就和我们通常理解的磁盘或者分区类似。 接下来就是根据需要将 LV 格式化为对应的文件系统,并将其挂载到对应的挂载点(即目录)上去使用。根据需要,我们可以在系统层面创建一个乃至多个 VG。
这里面的 PE(Physical Extents)可以理解成一个物理块,它是 PV 中可以分配的最小单元,默认是 4MiB,当然我们在创建 VG 的时候可以通过 “-s” 参数去指定 PE 的大小。同理,LE(Logical Extents)可以理解成一个逻辑块,它是 LV 中可以分配的最小单元,在相同的 VG 中,LE 的大小和 PE 的大小是一致的,并且一一相对。
3. 创建并管理 LVM 卷
本次测试环境为一台安装了 CentOS 7.6 操作系统的虚拟机,除了 sda 以外另配置了4块 100 GB 的磁盘作为本次实验的测试盘。
3.1. 创建 LVM 卷
- 目标1: 使用 sdb 创建名为 lv-data1 的 LVM 卷并格式化为 ext4 格式挂载到 data1 目录;
- 目标2: 使用 sdc 创建名为 lv-data2 的 LVM 卷并格式化为 xfs 格式挂载到 data2 目录。
Step1
:分别使用 sdb 和 sdc 创建 PV。
[root@centos76-temp ~]# pvcreate /dev/sdb
Physical volume "/dev/sdb" successfully created.
[root@centos76-temp ~]# pvcreate /dev/sdc
Physical volume "/dev/sdc" successfully created.
Step2
:使用刚刚创建完成的两个 PV 分别创建对应的 VG。
[root@centos76-temp ~]# vgcreate vg-sdb /dev/sdb
Volume group "vg-sdb" successfully created
[root@centos76-temp ~]# vgcreate vg-sdc -s 16m /dev/sdc //通过“s”参数指定 VG 的 PE 大小(默认是 4MiB 大小)。
Volume group "vg-sdc" successfully created
Step3
:使用刚刚创建完成的两个 VG 分别创建对应的 LV。
[root@centos76-temp ~]# lvcreate -n lv-data1 -L 99G vg-sdb
Logical volume "lv-data1" created.
root@centos76-temp ~]# lvcreate -n lv-data2 -l 6399 vg-sdc
Logical volume "lv-data2" created.
注意事项1:
在创建 LV 时一般我们常用三种方式去分配 LV 的空间,一种是通过“L”参数直接指定 Size 来分配空间,另外一种是通过“l”参数指定 PE 的 Number 来分配空间,最后一种是通过“l”参数设置百分比来分配空间。
很多人在使用 Size 分配 LV 空间时可能会遇到下面这中情况:
[root@centos76-temp ~]# lvcreate -n lv-data1 -L 100G vg-sdb
Volume group "vg-sdb" has insufficient free space (25599 extents): 25600 required. //提示可用空间不足。
从报错信息大致可以理解为没有足够的空间去分配,至少需要 25600 extents,而当前只有 25599 extents。这里面的 extents 就是指 PE 的数量,可以通过“vgdisplay”命令进行查看,这个会在下文进一步进行说明。RedHat 官方有一段关于空间不足的解释,直译过来就是因为换算的方法不同导致了这个问题,原文如下:
You may get the error message “Insufficient free extents” when creating a logical volume when you think you have enough extents based on the output of the vgdisplay or vgs commands. This is because these commands round figures to 2 decimal places to provide human-readable output. To specify exact size, use free physical extent count instead of some multiple of bytes to determine the size of the logical volume.
这个时候我们可以稍微减小一点空间来进行处理,如下所示:
[root@centos76-temp ~]# lvcreate -n lv-data1 -L 99G vg-sdb
Logical volume "lv-data1" created.
注意事项2:
如果考虑是将整个磁盘的容量全部划分给 LV 卷,建议使用如下两种方式:
[root@centos76-temp ~]# lvcreate -n lv-data1 -l 100%FREE vg-sdb
Logical volume "lv-data1" created. //通过“100%FREE”参数将空间全部进行分配。
[root@centos76-temp ~]# lvcreate -n lv-data1 -l 25599 vg-sdb
Logical volume "lv-data1" created. //通过指定所有 PE 数量将空间全部进行分配。
还可以通过 mm%VG
来指定 VG 容量的百分比给 LV 分配空间,如下所示:
[root@centos76-temp ~]# lvcreate -n lv-data1 -l 50%VG vg-sdb
Logical volume "lv-data1" created.
Step4
:将上面两个 LV 卷分别格式化为 ext4 和 xfs 文件系统类型。
[root@centos76-temp ~]# mkfs.ext4 /dev/vg-sdb/lv-data1
[root@centos76-temp ~]# mkfs.xfs /dev/vg-sdc/lv-data2
Step5
:创建两个挂载点并进行挂载。
[root@centos76-temp ~]# mkdir /data1 /data2
[root@centos76-temp ~]# mount /dev/mapper/vg--sdb-lv--data1 /data1
[root@centos76-temp ~]# mount /dev/mapper/vg--sdc-lv--data2 /data2
Step6
:如果需要设置开机自动挂载,需要编辑 fstab 文件添加挂载条目。
[root@centos76-temp ~]# echo '/dev/mapper/vg--sdb-lv--data1 /data1 ext4 defaults 0 0' >> /etc/fstab
[root@centos76-temp ~]# echo '/dev/mapper/vg--sdc-lv--data2 /data2 xfs defaults 0 0' >> /etc/fstab
[root@centos76-temp ~]# mount -a
[root@centos76-temp ~]# df -h |grep data
/dev/mapper/vg--sdb-lv--data1 98G 61M 93G 1% /data1
/dev/mapper/vg--sdc-lv--data2 100G 33M 100G 1% /data2
3.2. 查询 LVM 卷
3.2.1. 查询磁盘、逻辑卷与挂载点的关系
通常会使用 lsblk
命令查看系统所有磁盘的分区信息,使用 df -h
命令查看已经挂载的信息。另外,lvm 卷通常会有两种表达方式,一种是在 /dev/mapper
路径下,另外一种则是在 /dev
路径下,具体如下所示:
[root@centos76-temp ~]# ll /dev/mapper/
总用量 0
lrwxrwxrwx 1 root root 7 10月 19 11:55 centos-root -> ../dm-0
lrwxrwxrwx 1 root root 7 10月 19 11:55 centos-swap -> ../dm-1
crw------- 1 root root 10, 236 10月 19 11:55 control
lrwxrwxrwx 1 root root 7 10月 27 14:40 vg--sdb-lv--data1 -> ../dm-2
lrwxrwxrwx 1 root root 7 10月 27 14:40 vg--sdc-lv--data2 -> ../dm-3
[root@centos76-temp ~]# ls -l /dev/ |grep vg
crw------- 1 root root 10, 63 10月 19 11:55 vga_arbiter
drwxr-xr-x 2 root root 60 10月 27 14:36 vg-sdb
drwxr-xr-x 2 root root 60 10月 27 14:34 vg-sdc
3.2.2. 查询 PV 的信息
一般会使用 pvs
和 pvscan
查询 PV 的简要信息,使用 pvdisplay
查看所有 PV 的详细信息,具体如下所示:
[root@centos76-temp ~]# pvs
PV VG Fmt Attr PSize PFree
/dev/sda2 centos lvm2 a-- <99.51g 0
/dev/sdb vg-sdb lvm2 a-- <100.00g 1020.00m
/dev/sdc vg-sdc lvm2 a-- 99.98g 0
[root@centos76-temp ~]# pvscan
PV /dev/sda2 VG centos lvm2 [<99.51 GiB / 0 free]
PV /dev/sdb VG vg-sdb lvm2 [<100.00 GiB / 1020.00 MiB free]
PV /dev/sdc VG vg-sdc lvm2 [99.98 GiB / 0 free]
Total: 3 [<299.49 GiB] / in use: 3 [<299.49 GiB] / in no VG: 0 [0 ]
[root@centos76-temp ~]# pvdisplay /dev/sdb /dev/sdc
--- Physical volume ---
PV Name /dev/sdb //PV 名称。
VG Name vg-sdb //VG 名称。
PV Size 100.00 GiB / not usable 4.00 MiB //PV 大小。
Allocatable yes
PE Size 4.00 MiB //物理块大小。
Total PE 25599 // PE 总数。
Free PE 255 // 空闲 PE 数(这部分还可以进行分配或者拿来扩容)。
Allocated PE 25344 //已经分配出去的 PE 数。
PV UUID kHcw8Z-XuIg-iTM3-bc01-KnkV-DnvK-neXPXS
--- Physical volume ---
PV Name /dev/sdc
VG Name vg-sdc
PV Size 100.00 GiB / not usable 16.00 MiB
Allocatable yes (but full)
PE Size 16.00 MiB
Total PE 6399
Free PE 0
Allocated PE 6399
PV UUID d09koR-PrEc-5O9O-q7mf-dseN-DscA-lqCWU4
3.2.3. 查询 VG 的信息
一般会使用 vgs
查询 VG 的简要信息,使用 vgdisplay
查看所有 VG 的详细信息,具体如下所示:
[root@centos76-temp ~]# vgs
VG #PV #LV #SN Attr VSize VFree
centos 1 2 0 wz--n- <99.51g 0
vg-sdb 1 1 0 wz--n- <100.00g 1020.00m
vg-sdc 1 1 0 wz--n- 99.98g 0
[root@centos76-temp ~]# vgdisplay vg-sdb vg-sdc
--- Volume group ---
VG Name vg-sdb //VG 名称。
System ID
Format lvm2
Metadata Areas 1
Metadata Sequence No 22
VG Access read/write
VG Status resizable
MAX LV 0
Cur LV 1
Open LV 1
Max PV 0
Cur PV 1
Act PV 1
VG Size <100.00 GiB //VG 大小。
PE Size 4.00 MiB //PE 大小。
Total PE 25599 //总 PE 数。
Alloc PE / Size 25344 / 99.00 GiB //已分配出去的 PE 数。
Free PE / Size 255 / 1020.00 MiB // 剩余可分配的 PE 数。
VG UUID zdAJ5z-m3ME-ABvW-Ps0Z-OSqk-lTNB-blaXBW
--- Volume group ---
VG Name vg-sdc
System ID
Format lvm2
Metadata Areas 1
Metadata Sequence No 2
VG Access read/write
VG Status resizable
MAX LV 0
Cur LV 1
Open LV 1
Max PV 0
Cur PV 1
Act PV 1
VG Size 99.98 GiB
PE Size 16.00 MiB
Total PE 6399
Alloc PE / Size 6399 / 99.98 GiB
Free PE / Size 0 / 0
VG UUID 2X6EYR-d1uv-N5IU-CNPe-hey3-uVRy-QQpqGB
3.2.4. 查询 LV 的信息
一般会使用 lvs
查询 LV 的简要信息,使用 lvdisplay
查看所有 LV 的详细信息,具体如下所示:
[root@centos76-temp ~]# lvs
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
root centos -wi-ao---- <91.51g
swap centos -wi-ao---- 8.00g
lv-data1 vg-sdb -wi-ao---- 99.00g
lv-data2 vg-sdc -wi-ao---- 99.98g
[root@centos76-temp ~]# lvdisplay /dev/vg-sdb/lv-data1 /dev/vg-sdc/lv-data2
--- Logical volume ---
LV Path /dev/vg-sdb/lv-data1 //LV 的路径。
LV Name lv-data1 //LV 的名称。
VG Name vg-sdb //VG 的名称。
LV UUID 75ZMZ9-1uxz-IIbG-L6vI-mhIX-rhuI-HCMi90
LV Write Access read/write
LV Creation host, time centos76-temp, 2021-10-27 14:36:00 +0800
LV Status available //LV 的状态。
# open 1
LV Size 99.00 GiB //LV 的容量。
Current LE 25344 //LV 所属的 PE 数量。
Segments 1
Allocation inherit
Read ahead sectors auto
- currently set to 8192
Block device 253:2
--- Logical volume ---
LV Path /dev/vg-sdc/lv-data2
LV Name lv-data2
VG Name vg-sdc
LV UUID sGlBsw-oyV7-RUup-FAvT-Wtez-7MvW-EYAc82
LV Write Access read/write
LV Creation host, time centos76-temp, 2021-10-27 14:34:28 +0800
LV Status available
# open 1
LV Size 99.98 GiB
Current LE 6399
Segments 1
Allocation inherit
Read ahead sectors auto
- currently set to 8192
Block device 253:3
3.3. 扩容 LVM 卷
注意事项:
一般来说扩容操作是不需要卸载挂载点的,而且扩容操作一般也不会破坏对应目录下的文件。但是事无绝对,对于非常重要的生产系统,在做类似的操作时建议先做数据备份,以防万一,毕竟数据无价。另外,在设计一些目录空间时,可以根据现有的数据量以及增长趋势提前做好规划,能避免这些操作就尽可能避免。
3.3.1. 利用 VG 剩余空间进行扩容
本节会将 sdd 和 sde 两块磁盘放到一个 VG 里面,创建一个 lvtest 的逻辑卷,并将整个 VG 一半的空间分配给 lvtest 卷,然后模拟空间不足,将 VG 剩余的空间全部分配给 lvtest 逻辑卷。
Step1
:创建 PV。
[root@centos76-temp ~]# pvcreate /dev/sdd /dev/sde
Physical volume "/dev/sdd" successfully created.
Physical volume "/dev/sde" successfully created.
Step2
:创建 VG。
[root@centos76-temp ~]# vgcreate vgtest /dev/sdd /dev/sde
Volume group "vgtest" successfully created
Step3
:创建 LV。
[root@centos76-temp ~]# lvcreate -n lvtest -l 50%VG vgtest
Logical volume "lvtest" created.
Step4
:格式化为 xfs 文件系统。
[root@centos76-temp ~]# mkfs.xfs /dev/mapper/vgtest-lvtest
Step5
:创建挂载点并进行挂载。
[root@centos76-temp ~]# mkdir /datatest
[root@centos76-temp ~]# mount /dev/mapper/vgtest-lvtest /datatest/
Step6
:创建一个测试文本并计算出 md5 值(目的是为了验证扩容后文件是否被破坏)。
[root@centos76-temp ~]# for i in {1..10000}; do echo Number $i >> /datatest/test.txt; done
[root@centos76-temp ~]# md5sum /datatest/test.txt
acde7363d9d0e818625ec58497771b8e /datatest/test.txt
Step7
:检查 vgtest 资源使用情况,发现有剩余空间可以进行分配。
[root@centos76-temp ~]# vgdisplay vgtest
--- Volume group ---
VG Name vgtest
System ID
Format lvm2
Metadata Areas 2
Metadata Sequence No 2
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 199.99 GiB
PE Size 4.00 MiB
Total PE 51198
Alloc PE / Size 25599 / <100.00 GiB //已经分配出去的空间(或者 PE 数)。
Free PE / Size 25599 / <100.00 GiB //空闲资源(或者剩余可以分配的 PE 数)。
VG UUID eQqmob-CSpF-ddm9-ofMy-R3qV-0Ryk-9sJfgn
Step8
:扩容 LV 空间。
一般来说,我们可以指定将 LV 扩展
多少容量,也可以指定将 LV 扩展到
多少容量,还有一种比较彻底的做法是将剩余的空间全部分配给 LV。下面我将针对这三种做法依次将 vgtest 的剩余空间全部分配给 lvtest 逻辑卷。
[root@centos76-temp ~]# lvextend -L +20G /dev/vgtest/lvtest //将 lvtest 扩展 20 GiB 容量(即新增 20 GiB空间)。
Size of logical volume vgtest/lvtest changed from <100.00 GiB (25599 extents) to <120.00 GiB (30719 extents).
Logical volume vgtest/lvtest successfully resized.
[root@centos76-temp ~]# lvs
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
root centos -wi-ao---- <91.51g
swap centos -wi-ao---- 8.00g
lv-data1 vg-sdb -wi-ao---- 99.00g
lv-data2 vg-sdc -wi-ao---- 99.98g
lvtest vgtest -wi-ao---- <120.00g //可以看到空间扩展了 20 GiB。
[root@centos76-temp ~]# lvextend -L 150G /dev/vgtest/lvtest //将 lvtest 扩展到 150 GiB 容量(即直接指定最终要扩展到的容量)。
Size of logical volume vgtest/lvtest changed from <120.00 GiB (30719 extents) to 150.00 GiB (38400 extents).
Logical volume vgtest/lvtest successfully resized.
[root@centos76-temp ~]# lvs
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
root centos -wi-ao---- <91.51g
swap centos -wi-ao---- 8.00g
lv-data1 vg-sdb -wi-ao---- 99.00g
lv-data2 vg-sdc -wi-ao---- 99.98g
lvtest vgtest -wi-ao---- 150.00g //可以看到空间扩展到 150 GiB。
[root@centos76-temp ~]# lvextend -l +100%FREE /dev/vgtest/lvtest //将剩余空间全部分配 lvtest 卷(暴力美学,不直接全给,我比较喜欢这一种做法)。
Size of logical volume vgtest/lvtest changed from 150.00 GiB (38400 extents) to 199.99 GiB (51198 extents).
Logical volume vgtest/lvtest successfully resized.
[root@centos76-temp ~]# lvs
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
root centos -wi-ao---- <91.51g
swap centos -wi-ao---- 8.00g
lv-data1 vg-sdb -wi-ao---- 99.00g
lv-data2 vg-sdc -wi-ao---- 99.98g
lvtest vgtest -wi-ao---- 199.99g //可以看到空间已经扩展到了近 200 GiB。
[root@centos76-temp ~]# vgdisplay vgtest
--- Volume group ---
VG Name vgtest
System ID
Format lvm2
Metadata Areas 2
Metadata Sequence No 5
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 199.99 GiB
PE Size 4.00 MiB
Total PE 51198
Alloc PE / Size 51198 / 199.99 GiB
Free PE / Size 0 / 0 //此时可以看到当前 VG 已经没有空闲资源进行分配了。
VG UUID eQqmob-CSpF-ddm9-ofMy-R3qV-0Ryk-9sJfgn
Step9
:调整文件系统空间。
在 Step8
中我们扩展了 LV 的空间,但是细心的你一定会发现,上面经历了3个阶段最终将 VG 的剩余空间全部分配给了 lvtest 卷,但是其所对应挂载的文件系统容量是没有改变的,因此,针对不同格式的文件系统,我们需要使用相对应的命令去进行调整。
[root@centos76-temp ~]# lvs |grep lvtest
lvtest vgtest -wi-ao---- 199.99g //lvtest 容量已经变为 200 GiB。
[root@centos76-temp ~]# df -h |grep datatest
/dev/mapper/vgtest-lvtest 100G 33M 100G 1% /datatest //对应文件系统容量还是 100 GiB。
[root@centos76-temp ~]# mount |grep datatest //查询到要调整的文件系统为 xfs 类型。
/dev/mapper/vgtest-lvtest on /datatest type xfs (rw,relatime,attr2,inode64,noquota)
[root@centos76-temp ~]# xfs_growfs /dev/mapper/vgtest-lvtest //针对 xfs 类型调整文件系统。
[root@centos76-temp ~]# df -h |grep datatest
/dev/mapper/vgtest-lvtest 200G 33M 200G 1% /datatest //文件系统空间(或者说目录空间)已调成为 200 GiB。
Step10
:验证扩容操作是否会破坏文件。
[root@centos76-temp ~]# md5sum /datatest/test.txt
acde7363d9d0e818625ec58497771b8e /datatest/test.txt //文件 MD5 校验值与扩容前一致,表示文件没有被破坏。
3.3.2. 当前 VG 空间不足如何扩容
由于上面已经演示了 xfs 文件系统类型如何进行扩容,接下来将演示 ext4 文件系统类型的扩容,目前来说,用的比较多的文件系统类型也就是这两种了。
在上文我们创建了 lv-data1 逻辑卷并挂载到了 data1 目录下,那么接下来我们将 sdd 磁盘空间扩容到 vg-data1 里面去,以此来模拟当前 VG 空间不足借助新增磁盘或者分区来实现 LVM 的扩容。
Step1
:明确需要扩容的 VG 和 LV 名称,以及使用哪块磁盘来进行扩容。
[root@centos76-temp ~]# df -h |grep data1
/dev/mapper/vg--sdb-lv--data1 98G 61M 93G 1% /data1 //明确 lv-data1 挂载到了 data1 目录下。
[root@centos76-temp ~]# mount |grep data1
/dev/mapper/vg--sdb-lv--data1 on /data1 type ext4 (rw,relatime,data=ordered) //明确文件系统是 ext4 类型。
[root@centos76-temp ~]# pvdisplay |grep -B2 "vg-sdb" //明确 lv-data1 所属 VG 仅由 sdb 构成。
--- Physical volume ---
PV Name /dev/sdb
VG Name vg-sdb
[root@centos76-temp ~]# vgdisplay vg-sdb //查看 lv-data1 所属 VG 的详细信息。
--- Volume group ---
VG Name vg-sdb
System ID
Format lvm2
Metadata Areas 1
Metadata Sequence No 22
VG Access read/write
VG Status resizable
MAX LV 0
Cur LV 1
Open LV 1
Max PV 0
Cur PV 1
Act PV 1
VG Size <100.00 GiB
PE Size 4.00 MiB
Total PE 25599
Alloc PE / Size 25344 / 99.00 GiB
Free PE / Size 255 / 1020.00 MiB //由此来看还有很小的一部分空间可以分=分配出去。
VG UUID zdAJ5z-m3ME-ABvW-Ps0Z-OSqk-lTNB-blaXBW
Step2
:使用 sdd 创建一个 PV 扩容到 VG 里面去。
[root@centos76-temp ~]# pvcreate /dev/sdd //创建 PV。
Physical volume "/dev/sdd" successfully created.
[root@centos76-temp ~]# vgextend vg-sdb /dev/sdd //将创建的 PV 扩容到 VG 里面去。
Volume group "vg-sdb" successfully extended
[root@centos76-temp ~]# vgs
VG #PV #LV #SN Attr VSize VFree
centos 1 2 0 wz--n- <99.51g 0
vg-sdb 2 1 0 wz--n- 199.99g 100.99g //总容量近 200G,空闲 100G。
vg-sdc 1 1 0 wz--n- 99.98g 0
Step3
:将 VG 剩余空间全部分配给 LV。
[root@centos76-temp ~]# lvextend -l +100%FREE /dev/vg-sdb/lv-data1
Size of logical volume vg-sdb/lv-data1 changed from 99.00 GiB (25344 extents) to 199.99 GiB (51198 extents).
Logical volume vg-sdb/lv-data1 successfully resized.
Step4
:调整文件系统空间。
[root@centos76-temp ~]# resize2fs /dev/vg-sdb/lv-data1
resize2fs 1.42.9 (28-Dec-2013)
Filesystem at /dev/vg-sdb/lv-data1 is mounted on /data1; on-line resizing required
old_desc_blocks = 13, new_desc_blocks = 25
The filesystem on /dev/vg-sdb/lv-data1 is now 52426752 blocks long.
[root@centos76-temp ~]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/centos-root 92G 8.8G 83G 10% /
devtmpfs 1.9G 0 1.9G 0% /dev
tmpfs 1.9G 0 1.9G 0% /dev/shm
tmpfs 1.9G 13M 1.9G 1% /run
tmpfs 1.9G 0 1.9G 0% /sys/fs/cgroup
/dev/loop0 4.3G 4.3G 0 100% /mnt/cdrom
/dev/sda1 497M 172M 326M 35% /boot
tmpfs 378M 4.0K 378M 1% /run/user/42
tmpfs 378M 32K 378M 1% /run/user/0
/dev/sr0 4.3G 4.3G 0 100% /run/media/root/CentOS 7 x86_64
/dev/mapper/vg--sdb-lv--data1 197G 60M 188G 1% /data1 //文件系统(目录)空间已调整。
/dev/mapper/vg--sdc-lv--data2 100G 33M 100G 1% /data2
[root@centos76-temp ~]# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 100G 0 disk
├─sda1 8:1 0 500M 0 part /boot
└─sda2 8:2 0 99.5G 0 part
├─centos-root 253:0 0 91.5G 0 lvm /
└─centos-swap 253:1 0 8G 0 lvm [SWAP]
sdb 8:16 0 100G 0 disk
└─vg--sdb-lv--data1 253:2 0 200G 0 lvm /data1
sdc 8:32 0 100G 0 disk
└─vg--sdc-lv--data2 253:3 0 100G 0 lvm /data2
sdd 8:48 0 100G 0 disk
└─vg--sdb-lv--data1 253:2 0 200G 0 lvm /data1
sde 8:64 0 100G 0 disk
sr0 11:0 1 4.3G 0 rom /run/media/root/CentOS 7 x86_64
loop0 7:0 0 4.3G 0 loop /mnt/cdrom
3.4. 缩减 LVM 卷
注意事项1:
一般来说缩减操作是非常少见的,这一点不论是针对磁盘扩容,还是一些虚拟化场景里面像 CPU 和内存资源的调整一样。你会发现,往往做完减配以后,轻则程序无法运行或者出 BUG,严重点的直接系统崩溃。所以很多时候在非必要的情况下,我不会建议用户去做缩减操作,尤其是比较重要的业务系统环境。
注意事项2:
即使迫不得已要进行缩减操作,目前也只能对 ext4 文件系统进行空间缩减,不支持对 xfs 文件系统进行缩减操作
。该操作被 RedHat 认为是复杂且具备风险的操作,并且认为这样的案例不会太多,具体大家可以参考红帽官方 KB 《How to reduce XFS file system》。如果一定要对 xfs 文件系统进行缩减操作,则需要借助 xfsdump
和 xfsrestore
工具来实现,本文不做过多描述,有兴趣大家可以去了解下。
Step1
:使用四块磁盘构建一个 VG 并分别创建两个 LV。
[root@centos76-temp ~]# pvcreate /dev/sd[b,c,d,e] //创建 PV。
Physical volume "/dev/sdb" successfully created.
Physical volume "/dev/sdc" successfully created.
Physical volume "/dev/sdd" successfully created.
Physical volume "/dev/sde" successfully created.
[root@centos76-temp ~]# vgcreate vgtest /dev/sd[b,c,d,e] //创建 VG。
Volume group "vgtest" successfully created
[root@centos76-temp ~]# lvcreate -n lvmysql -l 50%VG vgtest //使用一半空间创建 lvmysql 逻辑卷。
Logical volume "lvmysql" created.
[root@centos76-temp ~]# lvcreate -n lvoracle -l 100%FREE vgtest //将剩下的所有空间创建 lvoracle 逻辑卷。
Logical volume "lvoracle" created.
[root@centos76-temp ~]# lvs //查看所有 LVM 卷的信息。
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
root centos -wi-ao---- <91.51g
swap centos -wi-ao---- 8.00g
lvmysql vgtest -wi-a----- 199.99g
lvoracle vgtest -wi-a----- 199.99g
Step2
:使用上面两个 LV 分别挂载文件系统并模拟一份数据文件。
[root@centos76-temp ~]# mkfs.ext4 /dev/vgtest/lvmysql //格式化为 ext4 文件系统。
[root@centos76-temp ~]# mkfs.xfs /dev/vgtest/lvoracle //格式化为 xfs 文件系统。
[root@centos76-temp ~]# mkdir -p /data/{mysql,oracle} //创建两个挂载点。
[root@centos76-temp ~]# mount /dev/mapper/vgtest-lvmysql /data/mysql/ //挂载文件系统。
[root@centos76-temp ~]# mount /dev/mapper/vgtest-lvoracle /data/oracle/
[root@centos76-temp ~]# for i in {1..10000}; do echo Number $i >> /data/mysql/mysql.txt; done //创建测试数据。
[root@centos76-temp ~]# for i in {1..10000}; do echo Number $i >> /data/oracle/oracle.txt; done
[root@centos76-temp ~]# md5sum /data/mysql/mysql.txt /data/oracle/oracle.txt //计算 MD5 校验值。
acde7363d9d0e818625ec58497771b8e /data/mysql/mysql.txt
acde7363d9d0e818625ec58497771b8e /data/oracle/oracle.txt
Step3
:模拟缩减 mysql 的空间。
1)首先卸载文件系统:
[root@centos76-temp ~]# umount /data/mysql/ //卸载挂载点。
2)其次检查当前 LVM 卷是否有坏块:
[root@centos76-temp ~]# e2fsck -f /dev/vgtest/lvmysql //这一步不执行无法进行下一步操作。
e2fsck 1.42.9 (28-Dec-2013)
第一步: 检查inode,块,和大小
第二步: 检查目录结构
第3步: 检查目录连接性
Pass 4: Checking reference counts
第5步: 检查簇概要信息
/dev/vgtest/lvmysql: 12/13107200 files (0.0% non-contiguous), 870954/52426752 blocks
3)然后先调整文件系统空间:
[root@centos76-temp ~]# resize2fs -f /dev/vgtest/lvmysql 100g //表示将文件系统空间调整为 100G,并不是指回收的空间大小,切记不要弄混。
resize2fs 1.42.9 (28-Dec-2013)
Resizing the filesystem on /dev/vgtest/lvmysql to 26214400 (4k) blocks.
The filesystem on /dev/vgtest/lvmysql is now 26214400 blocks long.
4)最后收缩 LVM 卷空间:
[root@centos76-temp ~]# lvreduce -L 100g /dev/vgtest/lvmysql //将 LVM 卷空间调整到 100G(即要和上面最终文件系统的空间大小保持一致)。
WARNING: Reducing active logical volume to 100.00 GiB.
THIS MAY DESTROY YOUR DATA (filesystem etc.)
Do you really want to reduce vgtest/lvmysql? [y/n]: y //输入“y”表示接受缩减操作。
Size of logical volume vgtest/lvmysql changed from 199.99 GiB (51198 extents) to 100.00 GiB (25600 extents).
Logical volume vgtest/lvmysql successfully resized.
5)重新挂载文件系统:
[root@centos76-temp ~]# mount /dev/mapper/vgtest-lvmysql /data/mysql/
Step4
:检查调整后的 LVM 卷空间和文件系统空间。
[root@centos76-temp ~]# lvs
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
root centos -wi-ao---- <91.51g
swap centos -wi-ao---- 8.00g
lvmysql vgtest -wi-ao---- 100.00g //可以发现 lvmysql 逻辑卷空间从近 200G 变为了 100G。
lvoracle vgtest -wi-ao---- 199.99g
[root@centos76-temp ~]# df -h |grep data
/dev/mapper/vgtest-lvoracle 200G 33M 200G 1% /data/oracle
/dev/mapper/vgtest-lvmysql 99G 61M 94G 1% /data/mysql //目录空间对应发生改变。
[root@centos76-temp ~]# vgdisplay vgtest
--- Volume group ---
VG Name vgtest
System ID
Format lvm2
Metadata Areas 4
Metadata Sequence No 4
VG Access read/write
VG Status resizable
MAX LV 0
Cur LV 2
Open LV 2
Max PV 0
Cur PV 4
Act PV 4
VG Size 399.98 GiB
PE Size 4.00 MiB
Total PE 102396
Alloc PE / Size 76798 / 299.99 GiB
Free PE / Size 25598 / 99.99 GiB //此时可以看到 VG 获得了 100G 左右的空闲资源(可以为其它 LVM 卷扩容了)。
VG UUID 8mdFC6-69Yu-oN6U-Z4rJ-hYtJ-tujq-utHo4g
3.5. 删除 LVM 卷
Step1
:确认要删除的 LV 卷。
[root@centos76-temp ~]# df -h |grep datatest
/dev/mapper/vgtest-lvtest 200G 33M 200G 1% /datatest
[root@centos76-temp ~]# lvs |grep lvtest
lvtest vgtest -wi-ao---- 199.99g //确定删除 lvtest 逻辑卷。
Step2
:卸载挂载点并删除 LVM 卷。
[root@centos76-temp ~]# umount /datatest/ //如果不卸载在删除时会提示当前 LVM 卷有文件系统正在使用,是无法删除的。
[root@centos76-temp ~]# lvremove -f vgtest/lvtest //使用“f”参数表示强制删除,如果不加该参数会需要用户输入“y”或“n”来确认是否进行删除操作。
Logical volume "lvtest" successfully removed
Step3
:关闭并删除 VG。
[root@centos76-temp ~]# vgchange -a n vgtest //关闭 VG,属于比较安全的方式去删除 VG(将“n”改为“y”表示激活 VG)。
0 logical volume(s) in volume group "vgtest" now active
[root@centos76-temp ~]# vgremove -f vgtest //使用“f”参数表示强制删除,如果不加该参数会需要用户输入“y”或“n”来确认是否进行删除操作。
Volume group "vgtest" successfully removed
Step4
:删除 PV。
[root@centos76-temp ~]# pvremove /dev/sdd /dev/sde
Labels on physical volume "/dev/sdd" successfully wiped.
Labels on physical volume "/dev/sde" successfully wiped.
Step5
:清除磁盘数据(保证磁盘为新盘可以重新投入使用)。
[root@centos76-temp ~]# dd if=/dev/zero of=/dev/sdd bs=1M count=1024 oflag=direct
[root@centos76-temp ~]# dd if=/dev/zero of=/dev/sde bs=1M count=1024 oflag=direct
3.6. 如何从 VG 中删除一个 PV
注意事项:
当 VG 中的 PV 其 Total PE 不等于 Free PE 数
时,意味着此时这个 PV 上还是有数据分布的,因此我们不可以对其进行删除操作。换而言之,如果我们要删除一个 PV,前提是这个 PV 可以被释放。一般当 VG 空闲资源比较多,或者我们手动去缩减 LVM 卷的空间以此达到释放 VG 资源的时候,才可以进行 PV 的删除操作。
Step1
:查看目标 VG 当前由几个 PV 组成(当前没有 PV 可以删除)。
[root@centos76-temp ~]# pvdisplay |grep -E 'volume|PV Name|VG Name|Total PE|Free PE'
--- Physical volume ---
PV Name /dev/sda2
VG Name centos
Total PE 25474
Free PE 0
--- Physical volume ---
PV Name /dev/sdb
VG Name vgtest
Total PE 25599
Free PE 0
--- Physical volume ---
PV Name /dev/sdc
VG Name vgtest
Total PE 25599
Free PE 25598
--- Physical volume ---
PV Name /dev/sdd
VG Name vgtest
Total PE 25599
Free PE 0
--- Physical volume ---
PV Name /dev/sde
VG Name vgtest
Total PE 25599
Free PE 0
Step2
:考虑将 lvmysql 卷缩减空间以此来释放 VG 资源。
[root@centos76-temp ~]# umount /data/mysql/ //卸载挂载点。
[root@centos76-temp ~]# e2fsck -f /dev/vgtest/lvmysql //检查档期 LVM 卷是否有坏块。
[root@centos76-temp ~]# resize2fs -f /dev/vgtest/lvmysql 10g //将文件系统空间缩减到 10G。
[root@centos76-temp ~]# lvreduce -L 10g /dev/vgtest/lvmysql //同步缩减 LVM 卷到 10G。
[root@centos76-temp ~]# mount /dev/mapper/vgtest-lvmysql /data/mysql/ //重新挂载 mysql 目录。
[root@centos76-temp ~]# lvs
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
root centos -wi-ao---- <91.51g
swap centos -wi-ao---- 8.00g
lvmysql vgtest -wi-a----- 10.00g //此时可以看到 lvmysql 卷空间为 10G。
lvoracle vgtest -wi-ao---- 199.99g
[root@centos76-temp ~]# df -h |grep data
/dev/mapper/vgtest-lvoracle 200G 33M 200G 1% /data/oracle
/dev/mapper/vgtest-lvmysql 9.8G 37M 9.2G 1% /data/mysql //对应目录空间大小也发生改变。
Step3
:再次查询 VG 中是否有 PV 可以被删除。
[root@centos76-temp ~]# pvdisplay |grep -E 'volume|PV Name|VG Name|Total PE|Free PE'
--- Physical volume ---
PV Name /dev/sda2
VG Name centos
Total PE 25474
Free PE 0
--- Physical volume ---
PV Name /dev/sdb
VG Name vgtest
Total PE 25599
Free PE 23039
--- Physical volume ---
PV Name /dev/sdc //发现 sdc 的 “Total PE” 和 “ Free PE”一致(该 PV 可以被删除)。
VG Name vgtest
Total PE 25599
Free PE 25599
--- Physical volume ---
PV Name /dev/sdd
VG Name vgtest
Total PE 25599
Free PE 0
--- Physical volume ---
PV Name /dev/sde
VG Name vgtest
Total PE 25599
Free PE 0
Step4
:从 VG 中删除 PV。
[root@centos76-temp ~]# vgreduce vgtest /dev/sdc
Removed "/dev/sdc" from volume group "vgtest"
Step5
:通过检查可以发现 VG 中已经没有 “/dev/sdc” 这个 PV 了。
[root@centos76-temp ~]# pvdisplay |grep -B2 'vgtest'
--- Physical volume ---
PV Name /dev/sdb
VG Name vgtest
--
--- Physical volume ---
PV Name /dev/sdd
VG Name vgtest
--
--- Physical volume ---
PV Name /dev/sde
VG Name vgtest
Step6
:移除 PV。
[root@centos76-temp ~]# pvremove /dev/sdc
Step7
:清除磁盘数据(此时 sdc 可以投入其他测试或生产)。
[root@centos76-temp ~]# dd if=/dev/zero of=/dev/sdc bs=1M count=1024 oflag=direct
记录了1024+0 的读入
记录了1024+0 的写出
1073741824字节(1.1 GB)已复制,31.7033 秒,33.9 MB/秒
[root@centos76-temp ~]# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 100G 0 disk
├─sda1 8:1 0 500M 0 part /boot
└─sda2 8:2 0 99.5G 0 part
├─centos-root 253:0 0 91.5G 0 lvm /
└─centos-swap 253:1 0 8G 0 lvm [SWAP]
sdb 8:16 0 100G 0 disk
└─vgtest-lvmysql 253:2 0 10G 0 lvm /data/mysql
sdc 8:32 0 100G 0 disk
sdd 8:48 0 100G 0 disk
└─vgtest-lvoracle 253:3 0 200G 0 lvm /data/oracle
sde 8:64 0 100G 0 disk
└─vgtest-lvoracle 253:3 0 200G 0 lvm /data/oracle
sr0 11:0 1 4.3G 0 rom /run/media/root/CentOS 7 x86_64
loop0 7:0 0 4.3G 0 loop /mnt/cdrom
4. 常用命令汇总
4.1. PV 相关命令
【创建一个 PV:】
pvcreate <Disk|Partition> //可以直接使用裸磁盘或者分区创建 PV,并且可以指定多个磁盘或者分区同时创建 PV。
【移除一个 PV:】
pvremove <Disk|Partition>
【查询 PV 的简要信息:】
pvs
pvscan
【查询所有 PV 的详细信息:】
pvdisplay
【查询指定 PV 的详细信息:】
pvdisplay <PV Name> //后面可以接多个 PV 进行查询。
4.2. VG 相关命令
【创建一个 VG:】
vgcreate <VG Name> <PV Name> //后面可以同时接多个 PV 表示由这些个 PV 共同构建一个 VG。
【指定 PE 大小来创建一个 VG:】
vgcreate <VG Name> -s <PE Size> <PV Name>
【移除一个 VG:】
vgremove -f <VG Name> //使用“f”参数表示强制移除。
【从 VG 中移除指定的可移除的 PV(缩减 VG 空间):】
vgreduce <VG Name> <PV Name>
【向 VG 中添加指定的 PV(扩容 VG 空间):】
vgextend <VG Name> <PV Name>
【查询 VG 的简要信息:】
vgs
【查询所有 VG 的详细信息:】
pvdisplay
【查询指定 PV 的详细信息:】
pvdisplay <VG Name> //后面可以接多个 VG 进行查询。
【激活或者关闭指定的 VG:】
vgchange -a <y or n> <VG Name> //接“y”表示激活,反之“n”表示关闭。
4.3. LV 相关命令
【通过指定空间大小来创建 LV:】
lvcreate -n <LV Name> -L <指定卷容量如:100G> <VG Name>
【通过指定 PE 数量来创建 LV:】
lvcreate -n <LV Name> -l <指定 PE 数如:16384> <VG Name>
【通过指定 VG 空间的百分比来创建 LV:】
lvcreate -n <LV Name> -l <指定VG容量的百分比如:50%VG> <VG Name> //“50%VG”里面 VG 是固定的,只需要修改前面的百分比即可。
【使用 VG 全部空间来创建 LV:】
lvcreate -n <LV Name> -l 100%FREE <VG Name>
【删除一个 LV:】
lvremove -f <VG Name/LV Name> //使用“f”参数表示强制删除。
【将 LV 扩展到指定空间大小:】
lvextend -L <扩展后的容量> <LV Path> //这里的“LV Path”是指 LV 的绝对路径,如“/dev/vgtest/lvtest”。
【基于 LV 当前空间容量增加指定空间大小:】
lvextend -L +<新增的容量> <LV Path> //注意容量前面有个“+”号,且这里的“LV Path”也是指 LV 的绝对路径,如“/dev/vgtest/lvtest”。
【将 VG 剩余空间资源全部分配给 LV:】
lvextend -l +100%FREE <LV Path> //这里的“LV Path”是指 LV 的绝对路径,如“/dev/vgtest/lvtest”。
【缩减 LV 的空间到指定大小:】
lvreduce -L <指定将 LVM 卷空间缩减到多少> <LV Path> ////这里的空间是缩减后的空间而不是变化量,且“LV Path”是指 LV 的绝对路径,如“/dev/vgtest/lvmysql”。
4.4. resize2fs & xfs_growfs
【扩容 LV 卷后刷新 xfs 文件系统空间:】
xfs_growfs <LV Path> //这里的“LV Path”是指 LV 的绝对路径,如“/dev/mapper/vgtest-lvtest”。
【扩容 LV 卷后刷新 ext4 文件系统空间:】
resize2fs <LV Path> //这里的“LV Path”是指 LV 的绝对路径,如“/dev/mapper/vgtest-lvtest”。
【动态调整 ext4 文件系统的空间(缩减文件系统空间):】
resize2fs -f <LV Path> <指定将文件系统空间缩减到多少> //这里的空间是缩减后的空间而不是变化量,且“LV Path”是指 LV 的绝对路径,如“/dev/vgtest/lvmysql”。
5. 总结
本篇博客主要是针对 Linux LVM 卷的创建、删除和维护做了简单的介绍。实际上,关于 LVM 卷的知识点还有很多,包括像快照卷,以及不同条带化下 LVM 卷读写性能的差异等等。由于能力有限,目前也只能对一些常用场景和命令做一个分享,如有不当之处,欢迎大家及时指正。