Linux LVM 磁盘管理

发布于 2023-12-20
Linux-LVM 磁盘管理 1. LVM简介

Linux-LVM 磁盘管理

1. LVM简介

LVM(Logical Volume Manager)逻辑卷管理器,是一种磁盘管理技术,它将一个或多个物理磁盘组合成一个逻辑卷,用户可以在逻辑卷上创建文件系统,就像在普通磁盘上创建文件系统一样。LVM的主要优点是可以在不停机的情况下对磁盘进行扩容,缩容,快照等操作。

简单来说,就是 LVM 可以很方便的对硬盘进行扩容,缩容操作。

2. LVM的基本概念

LVM 有几个重要概念,从上到下依次为:

  • PV(Physical Volume) 物理卷,可以是硬盘,也可以是分区
  • VG(Volume Group) 卷组,由一个或多个物理卷组成,可以理解为硬盘池。
  • LV(Logical Volume) 逻辑卷,由卷组分出来的逻辑磁盘,可以理解为虚拟硬盘。最终也是将它挂载到文件系统上。
  • PE(Physical Extent) 物理区块,物理卷和逻辑卷的最小单位,一般为4M。
  • LE(Logical Extent) 逻辑区块,逻辑卷的最小单位,一般为4M。

PV、VG、LV的关系如下图所示:

3. LVM的基本操作

3.1. 创建物理卷 PV

首先可以使用 fdisk -l 或者 lsblk 查看当前系统的磁盘信息,如下图所示 (lsblk):

lsblkList block devices 的缩写。

  ~  lsblk
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
sda      8:0    0   10G  0 disk 
sdb      8:16   0   40G  0 disk 
├─sdb1   8:17   0   39G  0 part /
├─sdb2   8:18   0    1K  0 part 
└─sdb5   8:21   0  975M  0 part [SWAP]
sr0     11:0    1  628M  0 rom  

可以看到当前系统有两块磁盘,sda 和 sdb,sda 为 10G,sdb 为 40G,sda 上没有分区,sdb1 为系统根目录,sdb5 为交换分区。

这里我们使用 sda 创建一个物理卷 PV,使用 pvcreate 命令,如下所示:

  ~  sudo pvcreate /dev/sda
  Physical volume "/dev/sda" successfully created.

使用 pvdisplay 命令查看物理卷信息,如下所示:

  ~  pvdisplay
  "/dev/sda" is a new physical volume of "10.00 GiB"
  --- NEW Physical volume ---
  PV Name               /dev/sda
  VG Name               
  PV Size               10.00 GiB
  Allocatable           NO
  PE Size               0   
  Total PE              0
  Free PE               0
  Allocated PE          0
  PV UUID               B6J2T7-qV44-6gJq-vMWB-Aev8-xsQP-psPd3u

可以看到,sda 已经创建为物理卷 PV,但是还没有分配给任何卷组 VG。

除了可直接对设备创建 PV,还可以对分区,也就是说允许一个硬盘创建两个分区,其中一个进行 PV,一个不进行,甚至两个分区可所属不同的 PV。

3.2. 创建卷组 VG

使用 vgcreate 命令创建卷组 VG,如下所示:

  ~  vgcreate vg1 /dev/sda
  Volume group "vg1" successfully created

使用 vgdisplay 命令查看卷组信息,如下所示:

  ~  vgdisplay            
  --- Volume group ---
  VG Name               vg1
  System ID             
  Format                lvm2
  Metadata Areas        1
  Metadata Sequence No  1
  VG Access             read/write
  VG Status             resizable
  MAX LV                0             # 最大逻辑卷数量,0 为无限制
  Cur LV                0             # 当前逻辑卷数量
  Open LV               0             # 当前打开的逻辑卷数量
  Max PV                0             # 最大物理卷数量,0 为无限制
  Cur PV                1             # 当前物理卷数量
  Act PV                1             # 活动物理卷数量
  VG Size               <10.00 GiB    # 整个 VG 的容量大小
  PE Size               4.00 MiB      # 每个 PE 的大小
  Total PE              2559          # 总共有多少个 PE
  Alloc PE / Size       0 / 0         # 已经分配的 PE / 大小
  Free  PE / Size       2559 / <10.00 GiB # 剩余可分配的 PE / 大小
  VG UUID               PpCCuU-slml-5fF0-YxJe-I6bk-3rS0-3ePNyq

主要可以看到,卷组 VG 的名称为 vg1,卷组大小为 10G,PE 大小为 4M,总共有 2559 个 PE,当前没有分配给任何逻辑卷 LV。

再通过 pvdisplay 命令查看物理卷信息,如下所示:

  ~  pvdisplay
  --- Physical volume ---
  PV Name               /dev/sda
  VG Name               vg1
  PV Size               10.00 GiB / not usable 4.00 MiB
  Allocatable           yes 
  PE Size               4.00 MiB
  Total PE              2559
  Free PE               2559
  Allocated PE          0
  PV UUID               B6J2T7-qV44-6gJq-vMWB-Aev8-xsQP-psPd3u

这次可以看到,VG Name 已经显示为 vg1,说明物理卷已经分配给了卷组。

3.3. 创建逻辑卷 LV

使用 lvcreate 命令创建逻辑卷 LV,如下所示:

  ~  lvcreate -L 5G -n lv1 vg1
  Logical volume "lv1" created.

其中 -L 为逻辑卷大小,-n 为逻辑卷名称,vg1 为逻辑卷所在的卷组。(也可以使用 -l 参数指定 PE 数量,如 -l 1280)

使用 lvdisplay 命令查看逻辑卷信息,如下所示:

  ~  lvdisplay
  --- Logical volume ---
  LV Path                /dev/vg1/lv1
  LV Name                lv1
  VG Name                vg1
  LV UUID                sy8J15-Tzuw-1J8P-UCqc-0gbF-wdHl-L8Zmfu
  LV Write Access        read/write
  LV Creation host, time debian, 2023-12-18 10:53:05 +0800
  LV Status              available
  # open                 0
  LV Size                5.00 GiB
  Current LE             1280
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           254:0

3.4. 创建文件系统

使用 mkfs.ext4 命令创建文件系统,如下所示:

  ~  mkfs.ext4 /dev/vg1/lv1
mke2fs 1.47.0 (5-Feb-2023)
Creating filesystem with 1310720 4k blocks and 327680 inodes
Filesystem UUID: a52d69bd-1b39-41ee-a669-104e6dbec1ae
Superblock backups stored on blocks: 
	32768, 98304, 163840, 229376, 294912, 819200, 884736

Allocating group tables: done                            
Writing inode tables: done                            
Creating journal (16384 blocks): done
Writing superblocks and filesystem accounting information: done

3.5. 挂载文件系统

在挂载文件系统前,需要创建一个挂载点,也就是一个空的目录,我这里使用 /mnt 作为挂载点,然后使用 mount 命令挂载文件系统,如下所示:

mkdir /mnt
mount /dev/vg1/lv1 /mnt

然后通过 df -h 命令查看挂载情况,如下所示:

  ~  df -h 
文件系统             大小  已用  可用 已用% 挂载点
udev                 3.9G     0  3.9G    0% /dev
tmpfs                791M  768K  790M    1% /run
/dev/sdb1             39G   14G   23G   38% /
tmpfs                3.9G     0  3.9G    0% /dev/shm
tmpfs                5.0M     0  5.0M    0% /run/lock
tmpfs                791M     0  791M    0% /run/user/0
/dev/mapper/vg1-lv1  4.9G   24K  4.6G    1% /mnt

可以看到,逻辑卷已经挂载到了 /mnt 目录下。然后再通过 lsblk 命令查看磁盘信息,如下所示:

  ~  lsblk
NAME      MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
sda         8:0    0   10G  0 disk 
└─vg1-lv1 254:0    0    5G  0 lvm  /mnt
sdb         8:16   0   40G  0 disk 
├─sdb1      8:17   0   39G  0 part /
├─sdb2      8:18   0    1K  0 part 
└─sdb5      8:21   0  975M  0 part [SWAP]
sr0        11:0    1  628M  0 rom  

如果现在是临时挂载,重启后会失效,如果要永久挂载,需要修改 /etc/fstab 文件,添加如下内容:

/dev/vg1/lv1 /mnt ext4 defaults 0 0

3.6. 扩容逻辑卷 LV

我们的 /dev/sda 磁盘大小为 10G,但是我们只使用了 5G,还有 5G 的空间没有使用,这时候我们就可以对逻辑卷进行扩容,使用 lvextend 命令扩容逻辑卷,如下所示:

  ~  lvextend -r -L +1G /dev/vg1/lv1 
  Size of logical volume vg1/lv1 changed from 5.00 GiB (1280 extents) to 6.00 GiB (1536 extents).
  Logical volume vg1/lv1 successfully resized.

其中 -r 为自动缩容文件系统,不需要手动执行 resize2fs, -L +1G 为扩容 1G,如果要扩容到 10G,可以使用 -L 10G

然后再通过 df -h 命令查看挂载情况,如下所示:

  ~  df -h
文件系统             大小  已用  可用 已用% 挂载点
udev                 3.9G     0  3.9G    0% /dev
tmpfs                791M  768K  790M    1% /run
/dev/sdb1             39G   14G   23G   38% /
tmpfs                3.9G     0  3.9G    0% /dev/shm
tmpfs                5.0M     0  5.0M    0% /run/lock
tmpfs                791M     0  791M    0% /run/user/0
/dev/mapper/vg1-lv1  5.9G   24K  5.6G    1% /mnt

3.7. 缩容逻辑卷 LV

缩容要复杂一些,步骤如下:

  1. 卸载文件系统:umount /mnt
  2. 检查文件系统:e2fsck -f /dev/vg1/lv1, -f 为强制进行检查
  3. 缩小逻辑卷至 5G:lvreduce -r -L 5G /dev/vg1/lv1,其中 -r 为自动缩容文件系统,不需要手动执行 resize2fs。如果想要缩小到可用空间的最小值,可以使用 -l -1 参数,如 lvreduce -r -l -1 /dev/vg1/lv1
  4. 再次检查文件系统:e2fsck -f /dev/vg1/lv1
  5. 挂载文件系统:mount /dev/vg1/lv1 /mnt
  6. 检查文件系统大小:df -h

其中使用 lvreduce 命令缩容逻辑卷时,有以下两种方式:

  • -L -1G 缩容 1G,如原来为 6G,缩容后为 5G
  • -L 1G 缩容至 1G,如原来为 6G,缩容后为 1G

如果想要缩容至可用空间的最小值,可以先通过 resize2fs -P /dev/vg1/lv1 查看预估的最小值,如:

  ~  resize2fs -P /dev/vg1/lv1                  

resize2fs 1.47.0 (5-Feb-2023)
Estimated minimum size of the filesystem: 573865

这里返回的 573865 的单位是块 (block),查看每个块的大小可通过命令:tune2fs -l /dev/vg1/lv1 | grep "Block size",如:

~   tune2fs -l /dev/vg1/lv1 | grep "Block size"
Block size:               4096

这里返回的 4096 的单位是字节,通过计算 $573865 * 4096 = 2350551040 / 1024 / 1024 / 1024$ 可得约 2.18912G。为了安全,向上取整,可缩容为 2.19G2.2G

3.8. 扩容卷组 VG

如我们现在的空间不够了,新加了一块 10G 的硬盘, 通过 lsblk 命令查看到新加的硬盘为 /dev/sdc

然后我们先将 /dev/sdc 创建为物理卷 PV,然后将这个物理卷添加到先前创建的卷组 vg1 中(也可以创建一个新的卷组),如下所示:

pvcreate /dev/sdc
vgextend vg1 /dev/sdc

这样现在 vg1 的大小就变成了 20G。

3.9. 缩容卷组 VG

如我们觉得硬盘/分区有太多空闲,想去掉一块硬盘/分区,或者想更换硬盘(去掉旧的 PV 再添加新的 PV),可以进行缩容,但为了保证数据不丢失,需要先让卷组中有足够的空间来把要删除的 PV 中的数据迁移出去,然后再移除 PV。

如我们想要从 vg1 中移除 /dev/sda,步骤如下:

  1. 检查卷组是否有足够的剩余空间可用于迁移数据,如果没有则需要减少分配给 LV 的空间或者扩容当前 VG。
  2. 执行 pvmove vg1 /dev/sda 来从 vg1 上移除 /dev/sda。如果未进行第一步的话,这里会提示 Physical volume "/dev/sda" still in use
  3. 根据需要选择是否执行 pvremove /dev/sda 将它从 PV 中移除(如果不再使用,则需要执行这一步)
  4. 使用 vgdisplay 检查 vg 大小是否变化

3.10 删除 LV VG PV

删除 LV:

lvremove /dev/vg1/lv1

删除 VG:

vgremove vg1

删除 PV:

pvremove /dev/sda

4. LVM 快照

4.1 简介

LVM 快照是一种特殊的逻辑卷,它是对原始逻辑卷的一个快照,刚创建快照时,其实快照卷中并没有存储原始逻辑卷的数据,只有当原始逻辑卷的数据发生变化时,才会复制原始逻辑卷被修改的原数据到快照中,这样原始逻辑卷被修改,但对应的快照卷记录了修改前的数据,这样就可以通过快照卷恢复到修改前的状态。 还需要注意的是快照卷的大小,建议快照卷的大小和原始逻辑卷的大小一样,如果快照卷的大小小于原始逻辑卷的大小,当原始逻辑卷的数据发生变化较多的时,可能没有空间来存储原始逻辑卷的原数据。大于原始逻辑卷的大小也是没有意义的,因为快照卷只记录原始逻辑卷的原数据,肯定永远都不会超过原始逻辑卷的大小。

4.2 创建快照

创建快照的命令为:

lvcreate -s [-L <size>] -n SNAP_VOLUME [ -p|--permission rw|r ] SOURCE_VOLUME_PATH

其中 -s 表示为快照卷,-L 表示快照卷的大小,-n 表示快照卷的名称,-p 表示快照卷的权限,r 表示只读,rw 表示读写,SOURCE_VOLUME_PATH 表示原始逻辑卷的路径。

如:

lvcreate -s -L 5G -n lv1_snap -p r /dev/vg1/lv1

下面是一个示例:

  ~  lvcreate -L 5g -n lv1 vg1                      
WARNING: ext4 signature detected on /dev/vg1/lv1 at offset 1080. Wipe it? [y/n]: y
  Wiping ext4 signature on /dev/vg1/lv1.
  Logical volume "lv1" created.
  ~  mkfs.ext4 /dev/vg1/lv1       
mke2fs 1.47.0 (5-Feb-2023)
Creating filesystem with 1310720 4k blocks and 327680 inodes
Filesystem UUID: 8a413a29-644e-40dc-906a-dee174d81202
Superblock backups stored on blocks: 
	32768, 98304, 163840, 229376, 294912, 819200, 884736

Allocating group tables: done                            
Writing inode tables: done                            
Creating journal (16384 blocks): done
Writing superblocks and filesystem accounting information: done 

  ~  mount /dev/vg1/lv1 /mnt      
  ~  echo "test" > /mnt/1.txt                     
  ~  lvcreate -L 5G -n lv1_snap -p r -s /dev/vg1/lv1
  Logical volume "lv1_snap" created.
  ~  mount /dev/vg1/lv1_snap /mnt2                  
mount: /mnt2: WARNING: source write-protected, mounted read-only.
  ~  df -h
文件系统                  大小  已用  可用 已用% 挂载点
udev                      3.9G     0  3.9G    0% /dev
tmpfs                     791M  888K  790M    1% /run
/dev/sdc1                  39G   26G   11G   71% /
tmpfs                     3.9G     0  3.9G    0% /dev/shm
tmpfs                     5.0M     0  5.0M    0% /run/lock
tmpfs                     791M     0  791M    0% /run/user/0
/dev/mapper/vg1-lv1       4.9G   28K  4.6G    1% /mnt
/dev/mapper/vg1-lv1_snap  4.9G   28K  4.6G    1% /mnt2
  ~  echo "test123123123" > /mnt/1.txt
  ~  echo "test" > /mnt/2.txt                             
  ~  ls -l /mnt 
总计 24
-rw-r--r-- 1 root root    14 12月21日 10:34 1.txt
-rw-r--r-- 1 root root     5 12月21日 10:34 2.txt
drwx------ 2 root root 16384 12月21日 10:32 lost+found
  ~  ls -l /mnt2                      
总计 20
-rw-r--r-- 1 root root     5 12月21日 10:33 1.txt
drwx------ 2 root root 16384 12月21日 10:32 lost+found
  ~  cat /mnt/1.txt 
test123123123
  ~  cat /mnt2/1.txt
test

可以看到,我们创建了一个逻辑卷 lv1,然后挂载到 /mnt 目录,并将文本内容 "test" 写入到了 /mnt/1.txt,然后创建了一个快照 lv1_snap,挂载到 /mnt2 目录,这时修改了 /mnt/1.txt 的内容为 "test123123123",然后再次查看 /mnt/1.txt 和 /mnt2/1.txt 的内容,可以看到 /mnt/1.txt 的内容已经发生了变化,而 /mnt2/1.txt 的内容还是 "test",这是因为快照卷记录了 /mnt/1.txt 的原数据,所以 /mnt2/1.txt 的内容还是 "test"。同时,我们还创建了一个 /mnt/2.txt 文件,这个文件只会出现在 /mnt 目录下,而不会出现在 /mnt2 目录下,因为快照卷只记录了原始逻辑卷的原数据,而不会记录原始逻辑卷新增的数据。

注意快照不能用于替代备份,因为快照卷只记录了原始逻辑卷修改后的原数据,当原始逻辑卷或所属卷组损坏时,快照卷也会损坏。

4.3 还原快照

还原快照的命令为:

lvconvert --merge SOURCE_SNAPSHOT_VOLUME_PATH

其中 SOURCE_SNAPSHOT_VOLUME_PATH 为快照卷的路径。使用该命令后,快照卷会被删除,原始逻辑卷会恢复到快照卷创建时的状态

5. LVM 诊断

5.1. 查看各个 PV 占用情况

使用 pvdisplay -m 命令查看各个 PV 占用情况,如下所示:

  ~  pvdisplay -m
  --- Physical volume ---
  PV Name               /dev/sda
  VG Name               vg1
  PV Size               10.00 GiB / not usable 4.00 MiB
  Allocatable           yes (but full)
  PE Size               4.00 MiB
  Total PE              2559
  Free PE               0
  Allocated PE          2559
  PV UUID               Ly2wh9-c8iU-h2Gn-4REY-ioZJ-ykJG-uysyAC
   
  --- Physical Segments ---
  Physical extent 0 to 2558:
    Logical volume	/dev/vg1/lv1
    Logical extents	0 to 2558
   
  --- Physical volume ---
  PV Name               /dev/sdc
  VG Name               vg1
  PV Size               10.00 GiB / not usable 4.00 MiB
  Allocatable           yes 
  PE Size               4.00 MiB
  Total PE              2559
  Free PE               510
  Allocated PE          2049
  PV UUID               yfRAu7-EX5S-nlQL-YcdH-N7N1-Layf-QJ2ivo
   
  --- Physical Segments ---
  Physical extent 0 to 2048:
    Logical volume	/dev/vg1/lv1
    Logical extents	2559 to 4607
  Physical extent 2049 to 2558:
    FREE

也可以使用 pvscan 命令查看,如下所示:

  ~  pvscan      
  PV /dev/sda   VG vg1             lvm2 [<10.00 GiB / 0    free]
  PV /dev/sdc   VG vg1             lvm2 [<10.00 GiB / 1.99 GiB free]
  Total: 2 [19.99 GiB] / in use: 2 [19.99 GiB] / in no VG: 0 [0   ]

5.2. 查看各个 VG/VL 占用情况

pvdisplay -m 命令一样,只是命令前的 pv 换成 vglv