关于 Linux LVM 的使用


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 的信息

一般会使用 pvspvscan 查询 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 文件系统进行缩减操作,则需要借助 xfsdumpxfsrestore 工具来实现,本文不做过多描述,有兴趣大家可以去了解下。

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 卷读写性能的差异等等。由于能力有限,目前也只能对一些常用场景和命令做一个分享,如有不当之处,欢迎大家及时指正。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

方先森有点懒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值