第 6 章 Linux LVM 存储管理

作者: Brinnatt 分类: ARM64 Linux 基础精修 发布时间: 2022-01-20 22:08

LVM(Logical Volume Manager) 可以让分区变得弹性,可以随时随地的扩大和缩小分区大小,前提是该分区是 LVM 格式的。

LVM 需要使用的软件包为 lvm2,一般在 RHEL 系列发行版中都已经预安装了。

6.1、LVM 相关概念

  1. PV(Physical Volume) 即物理卷

    硬盘分区后(还未格式化为文件系统)使用 pvcreate 命令可以将分区创建为 pv,要求分区的 system ID 为 8e,即为 LVM 格式的系统标识符。

  2. VG(Volume Group) 即卷组

    将多个 PV 组合起来,使用 vgcreate 命令创建成卷组,这样卷组包含了多个 PV 就比较大了,相当于重新整合了多个分区后得到的磁盘。

    虽然 VG 是整合多个 PV 的,但是创建 VG 时会将 VG 所有的空间根据指定的 PE 大小划分为多个 PE,在 LVM 模式下的存储都以 PE 为单元,类似于文件系统的 Block。

  3. PE(Physical Extend)

    PE 是 VG 中的存储单元,实际存储的数据都是存储在这里面的。

  4. LV(Logical Volume)

    VG 相当于整合过的硬盘,那么 LV 就相当于分区,只不过该分区是通过 VG 来划分的。

    VG 中有很多 PE 单元,可以指定将多少个 PE 划分给一个 LV,也可以直接指定大小(如多少兆)来划分。

    划分为 LV 之后就相当于划分了分区,只需再对 LV 进行格式化即可变成普通的文件系统。

  5. LE(logical extent)

    PE 是物理存储单元,而 LE 则是逻辑存储单元,也即为 LV 中的逻辑存储单元,和 PE 的大小是一样的。从 VG 中划分 LV,实际上是从 VG 中划分 PE,只不过划分 LV 后它不再称为 PE,而是 LE。

LVM 之所以能够伸缩容量,其实现的方法就是将 LV 里空闲的 PE 移出,或向 LV 中添加空闲的 PE。

以上概念使用逻辑图表示如下:

LVM concept

6.2、LVM 写入机制

LV 是从 VG 中划分出来的,LV 中的 PE 很可能来自于多个 PV。在向 LV 存储数据时,有多种存储机制,其中两种是:

  1. 线性模式(linear):先写完来自于同一个 PV 的 PE,再写来自于下一个 PV 的 PE。
  2. 条带模式(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。

扩容的两个关键步骤如下:

  1. 使用 lvextend 或者 lvresize 添加更多的 pe 或容量到 lv 中
  2. 使用 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 两个命令。

严格按照以下步骤执行:

  1. 首先卸载设备并使用 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 检查文件系统一致性。
    • 最后缩容文件系统边界到多大。
  2. 再收缩 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 无损修改分区大小的优点。
  3. 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 已经完全空闲下来了。
  4. 从 vg 中移除 pv

    将 /dev/sda2 从 BrinnattVg 中移除

    [root@arm64v8 ~]# vgreduce BrinnattVg /dev/sda2 
     Removed "/dev/sda2" from volume group "BrinnattVg"
    [root@arm64v8 ~]# 
  5. 移除该 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 ~]#
标签云