Linux 磁盘管理之 LVM 原理与操作

沈维燕 · 2019-07-19

📢 本文章同步自作者的语雀知识库,请点击这里阅读原文。

LVM ( Logical V olume Manager, 逻辑卷管理器) 是 Linux 环境下对硬盘分区进行管理的一种机制,开创这项技术的初衷是为了解决传统硬盘分区创建后不易更改其大小的弱点。对于传统硬盘分区进行强制扩容和缩小技术理论上虽然是可行的,但却有可能造成数据的丢失,LVM 逻辑卷管理器技术能够将多块硬盘进行卷组合并,让用户不必关心设备底层的架构和布局,拿来即用。

LVM 逻辑卷管理器是在磁盘分区和文件系统之间添加的逻辑层,它提供了一个抽象的卷组,可以使得多块硬盘进行卷组合并,让用户不必关心物理硬盘设备的底层结构,从而实现对分区的灵活动态调整。

LVM 逻辑卷管理器的技术结构如图 2 所示,刘遄老师来举个吃货的例子帮助同学们理解吧,比如家里想吃馒头但面粉不够了,妈妈分别从隔壁老王家、老李家、老张家借来一些面粉,蒸出馒头后大家一起来吃,首先咱们需要将这些面粉(物理卷 PV,Physical Volume)合并成一个大面团(卷组 VG,Volume Group),然后把这一大团面再分割成一个个小馒头(逻辑卷 LV,Logical Volume),每个小馒头的重量必须是每勺面粉(基本单元 PE,Physical Extent)的倍数。物理卷是处于逻辑卷管理器中最底层的资源,可以理解成是物理硬盘、硬盘分区或者RAID 磁盘阵列组都可以,而卷组是建立在物理卷之上的,一个卷组中可以包含多个物理卷,当然在卷组创建之后也可以继续向其中添加新的物理卷,而逻辑卷是建立于卷组之上的,将卷组中空闲的资源建立出新的逻辑卷,并且逻辑卷建立后可以动态的扩展或缩小空间,这也就是 LVM 逻辑卷管理器的核心理念。(第7章 使用RAID与LVM磁盘阵列技术

常用命令

部署 LVM 逻辑卷管理器需要依次对对物理卷、卷组和逻辑卷的逐个配置,常见的命令分别包括有:

功能/命令 物理卷管理 卷组管理 逻辑卷管理
扫描 pvscan vgscan lvscan
建立 pvcreate vgcreate lvcreate
显示 pvdisplay vgdisplay lvdisplay
删除 pvremove vgremove lvremove
缩小 vgreduce lvreduce
缩小 vgreduce lvreduce

实战展示

阿里云 ECS 扩充 4T 磁盘,并挂载。

物理硬盘

新增两个物理硬盘 vdb(2199.0 GB),vdc(2199.0 GB)。 为接下来 做LVM 做准备。

[root@iZ88qg9l425Z ~]# fdisk -l

Disk /dev/vda: 42.9 GB, 42949672960 bytes
255 heads, 63 sectors/track, 5221 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00078f9c

   Device Boot      Start         End      Blocks   Id  System
/dev/vda1   *           1        5222    41940992   83  Linux

Disk /dev/vdb: 2199.0 GB, 2199023255552 bytes
16 heads, 63 sectors/track, 4260880 cylinders
Units = cylinders of 1008 * 512 = 516096 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000


Disk /dev/vdc: 2199.0 GB, 2199023255552 bytes
16 heads, 63 sectors/track, 4260880 cylinders
Units = cylinders of 1008 * 512 = 516096 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000

硬盘分区

对添加的物理硬盘进行分区,这里先对 /dev/vdc 进行处理,完成后对 /dev/vdb 进行同样的处理。

[root@iZ88qg9l425Z ~]# fdisk /dev/vdc
Device contains neither a valid DOS partition table, nor Sun, SGI or OSF disklabel
Building a new DOS disklabel with disk identifier 0x4613ad5e.
Changes will remain in memory only, until you decide to write them.
After that, of course, the previous content won't be recoverable.

Warning: invalid flag 0x0000 of partition table 4 will be corrected by w(rite)

WARNING: The size of this disk is 2.2 TB (2199023255552 bytes).
DOS partition table format can not be used on drives for volumes
larger than (2199023255040 bytes) for 512-byte sectors. Use parted(1) and GUID 
partition table format (GPT).


WARNING: DOS-compatible mode is deprecated. It's strongly recommended to
         switch off the mode (command 'c') and change display units to
         sectors (command 'u').

Command (m for help): p

Disk /dev/vdc: 2199.0 GB, 2199023255552 bytes
16 heads, 63 sectors/track, 4260880 cylinders
Units = cylinders of 1008 * 512 = 516096 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x4613ad5e

   Device Boot      Start         End      Blocks   Id  System

Command (m for help): n     # 创建新分区
Command action
   e   extended      # e 为逻辑分区
   p   primary partition (1-4)      # p 为主分区
Select (default p): p
Partition number (1-4): 1    # 由于是新盘我们输入1来分第一个主分区,共可以分4个主分区
First sector (1-4260880, default 1):  # 选择该分区的起始磁盘数,如无特殊需求强烈建议选择默认,也就是1来分区(可直接按回车)
Using default value 1
Last cylinder, +cylinders or +size{K,M,G} (1-4260880, default 4260880):  # 定义该分区的大小,如果按默认(按回车)即是使用全部可用存储额,如分一个 1G 的空间,输入 +1024m
Using default value 4260880

Command (m for help): t   # 改变分区标识符
Selected partition 1
Hex code (type L to list codes): 8e       
Changed system type of partition 1 to 8e (Linux LVM)

Command (m for help): p

Disk /dev/vdc: 2199.0 GB, 2199023255552 bytes
16 heads, 63 sectors/track, 4260880 cylinders
Units = cylinders of 1008 * 512 = 516096 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x4613ad5e

   Device Boot      Start         End      Blocks   Id  System
/dev/vdc1               1     4260880  2147483488+  8e  Linux LVM

Command (m for help): w    # 写入分区
The partition table has been altered!

Calling ioctl() to re-read partition table.
Syncing disks.
[root@iZ88qg9l425Z ~]#

创建 PV

在新建的分区上创建 PV 物理卷,这里先对 /dev/vdc 进行处理,完成后需要对 /dev/vdb 进行同样的处理。

[root@iZ88qg9l425Z ~]# pvcreate /dev/vdc1
  Physical volume "/dev/vdc1" successfully created
[root@iZ88qg9l425Z ~]# pvs
  PV         VG   Fmt  Attr PSize PFree
  /dev/vdc1       lvm2 a--  2.00t 2.00t
[root@iZ88qg9l425Z ~]# pvdisplay 
  "/dev/vdc1" is a new physical volume of "2.00 TiB"
  --- NEW Physical volume ---
  PV Name               /dev/vdc1
  VG Name               
  PV Size               2.00 TiB
  Allocatable           NO
  PE Size               0   
  Total PE              0
  Free PE               0
  Allocated PE          0
  PV UUID               83IQY3-Z7O0-kicK-xIbJ-ZmUW-AlOF-ENUAp6
   
[root@iZ88qg9l425Z ~]# fdisk -l

Disk /dev/vda: 42.9 GB, 42949672960 bytes
255 heads, 63 sectors/track, 5221 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00078f9c

   Device Boot      Start         End      Blocks   Id  System
/dev/vda1   *           1        5222    41940992   83  Linux

Disk /dev/vdb: 2199.0 GB, 2199023255552 bytes
16 heads, 63 sectors/track, 4260880 cylinders
Units = cylinders of 1008 * 512 = 516096 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000


Disk /dev/vdc: 2199.0 GB, 2199023255552 bytes
16 heads, 63 sectors/track, 4260880 cylinders
Units = cylinders of 1008 * 512 = 516096 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x4613ad5e

   Device Boot      Start         End      Blocks   Id  System
/dev/vdc1               1     4260880  2147483488+  8e  Linux LVM

对 /dev/vdc、/dev/vdb 进行同样的操作(硬盘分区、创建 PV)后查看已有的物理卷。

[root@iZ88qg9l425Z ~]# pvdisplay 
  "/dev/vdb1" is a new physical volume of "2.00 TiB"
  --- NEW Physical volume ---
  PV Name               /dev/vdb1
  VG Name               
  PV Size               2.00 TiB
  Allocatable           NO
  PE Size               0   
  Total PE              0
  Free PE               0
  Allocated PE          0
  PV UUID               YMNnk1-sdi5-zyhj-coI5-hwBJ-Kofw-2BLE58
   
  "/dev/vdc1" is a new physical volume of "2.00 TiB"
  --- NEW Physical volume ---
  PV Name               /dev/vdc1
  VG Name               
  PV Size               2.00 TiB
  Allocatable           NO
  PE Size               0   
  Total PE              0
  Free PE               0
  Allocated PE          0
  PV UUID               83IQY3-Z7O0-kicK-xIbJ-ZmUW-AlOF-ENUAp6

把 PV 加入到 VG

将所有的新建的 PV 加入名为 vgdate 的卷组 (Volume Group) 中。

[root@iZ88qg9l425Z ~]# vgcreate vgdata /dev/vdb1 /dev/vdc1
  Volume group "vgdata" successfully created
[root@iZ88qg9l425Z ~]# vgs
  VG     #PV #LV #SN Attr   VSize VFree
  vgdata   2   0   0 wz--n- 4.00t 4.00t
[root@iZ88qg9l425Z ~]# vgdisplay 
  --- Volume group ---
  VG Name               vgdata
  System ID             
  Format                lvm2
  Metadata Areas        2
  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                2
  Act PV                2
  VG Size               4.00 TiB
  PE Size               4.00 MiB
  Total PE              1048574
  Alloc PE / Size       0 / 0   
  Free  PE / Size       1048574 / 4.00 TiB
  VG UUID               QafGYd-s0HW-6Wrx-pr6v-1fnR-mvpB-zrZ0md

创建 LV 逻辑卷

创建名为 lvdata 的 LV 逻辑卷。

[root@iZ88qg9l425Z ~]# lvcreate -l 1048574 -n lvdata vgdata
  Logical volume "lvdata" created

格式化并挂载

对 LV 逻辑卷进行格式化,然后挂载。

[root@iZ88qg9l425Z ~]# mkfs.ext4 -c /dev/vgdata/lvdata   # 对分区使用 ext4 格式化,-c 参数要先检测磁盘坏道
mke2fs 1.41.12 (17-May-2010)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
268435456 inodes, 1073739776 blocks
53686988 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=4294967296
32768 block groups
32768 blocks per group, 32768 fragments per group
8192 inodes per group
Superblock backups stored on blocks: 
    32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208, 
    4096000, 7962624, 11239424, 20480000, 23887872, 71663616, 78675968, 
    102400000, 214990848, 512000000, 550731776, 644972544

Writing inode tables: done                            
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 32 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.
[root@iZ88qg9l425Z ~]# mkdir /disk1
[root@iZ88qg9l425Z ~]# mount /dev/vgdata/lvdata /disk1/
[root@iZ88qg9l425Z ~]# df -Th
Filesystem           Type   Size  Used Avail Use% Mounted on
/dev/vda1            ext4    40G  3.6G   34G  10% /
tmpfs                tmpfs  3.9G     0  3.9G   0% /dev/shm
/dev/mapper/vgdata-lvdata
                     ext4   4.0T  195M  3.8T   1% /disk1
[root@iZ88qg9l425Z ~]#

参考资料