Linux 基础知识 - LVM 逻辑卷管理器介绍



(一图胜千言)
背景
我们在使用 Linux 的时候,经常会遇到如下问题:
/var/log、/var/lib/docker 等都会使用磁盘分区或者独立磁盘来管理容量和性能,但是不同集群规模,需要的容量是不一样的,硬盘设备容量不足时,往往就需要做迁移等操作;
容器在不同节点上运行的时候,为了保证 volume 映射的一致性,需要使用 mount bind 来让某一路径是同一的。
数据盘在使用的过程中,有些用得多,有些用得少,最终十几块硬盘可能会出现若干空间浪费(总空间足够,但是分散在各个硬盘上,无法整合使用);
幸运的是 Linux 提供的逻辑盘卷管理(LVM,LogicalVolumeManager)机制就是一个不错的解决方案。
LVM 简介
LVM 是逻辑卷管理(Logical Volume Manager)的简称,它是 Linux 环境下对磁盘分区进行管理的一种机制。LVM通过在硬盘和文件系统之间添加一个逻辑层,来为文件系统屏蔽下层硬盘分区布局,提高硬盘分区管理的灵活性。
使用LVM管理硬盘的基本过程如下:
将硬盘创建为物理卷。
将多个物理卷组合成卷组。
在卷组中创建逻辑卷。
在逻辑卷之上创建文件系统。
通过 LVM 管理硬盘之后,文件系统不再受限于硬盘的大小,可以分布在多个硬盘上,也可以动态扩容。
LVM 历史
当然,LVM并不是最新技术,早在UNIX操作系统时代,在像HP、IBM AIX上就可以看到VM的身影,作为IBM的旗舰产品,AIX很早就支持了动态逻辑分区(DVM),当然,它的DVM设计是比较厉害的,此后在AIX 5L中,重构了UNIX内核,增加了逻辑卷管理(LVM)和日志文件系统(JFS)等功能。使之AIX更加强大。在各种商业UNIX系统中,譬如AIX、 HP-UNIX、Tru64 UNIX等系统中,逻辑卷管理已经被广泛采用,成为了事实上的一个标准。
LVM 的功能于 2.3 内核发展中版本纳入支持。2001年1月,Linux2.4.0内核发布,开始正式支持逻辑卷管理,使得 Linux 新内核更适应服务器的应用。以前版本的 Linux 必须要在内核上打上相应的补丁才能实现 LVM 功能。现在我们看到从 RHEL 9.0 开始已经在内核级支持LVM。因此,我们可以使用 LVM 帮助我们更加有效地管理磁盘。要注意的是LVM有两个版本,分别是 LVM 1 与LVM 2,相关工具与设定方式会有些差异性。LVM 1命令只能在2.4内核上工作。当运行2.6内核时,不能使用LVM 1命令。
关于更多关于LVM 2的信息,请参阅/usr/share/doc/lvm2*/WHATS_NEW。一个完整的LVM 2命令被安装在/usr/sbin/下。在/usr/无效的启动环境中,每个命令前需要加上/sbin/lvm.static(例如,/sbin /lvm.static vgchange -ay)。在/usr有效的环境中,不再需要在每个命令前加上lvm(例如,/usr/sbin/lvm vgchage –ay变为/usr/sbin/vgchange -ay)。新的LVM2命令(例如,/usr/sbin/vgchange –ay和/sbin/lvm.static vgchange –ay)会检测你是否在运行2.4内核。如果是,它会调用旧的LVM 1命令。
基本概念
物理存储介质(The physical media):指系统的物理存储设备,如硬盘,系统中为/dev/hda、/dev/sda等等,是存储系统最低层的存储单元。
物理卷(Physical Volume,PV):指硬盘分区或从逻辑上与磁盘分区具有同样功能的设备(如RAID),是LVM的基本存储逻辑块。物理卷包括一个特殊的标签,该标签默认存放在第二个 512 字节扇区,但也可以将标签放在最开始的四个扇区之一。该标签包含物理卷的随机唯一识别符(UUID),记录块设备的大小和LVM元数据在设备中的存储位置。
卷组(Volume Group,VG):由物理卷组成,屏蔽了底层物理卷细节。可在卷组上创建一个或多个逻辑卷且不用考虑具体的物理卷信息。
逻辑卷(Logical Volume,LV):卷组不能直接用,需要划分成逻辑卷才能使用。逻辑卷可以格式化成不同的文件系统,挂载后直接使用。
物理块(Physical Extent,PE):物理卷以大小相等的“块”为单位存储,块的大小与卷组中逻辑卷块的大小相同。
逻辑块(Logical Extent,LE):逻辑卷以“块”为单位存储,在一卷组中的所有逻辑卷的块大小是相同的。
LVM 命令一览
PV 命令
命令 描述
pvcreate 将物理分区建成为PV
pvscan 搜索当前系统里任何具有PV的磁盘
pvdisplay 显示当前系统上的PV状态
pvremove 将PV属性删除,让该分区不具有PV属性
partprobe 这个命令可以让核心立刻读入最新的分区表而不必重新引导

VG 命令
命令 描述
vgcreate 创建 VG
vgscan 搜索系统上面是否有VG存在
vgdisplay 显示当前系统上的VG状态
vgextend 在VG内增加额外的PV
vgreduce 在VG内删除PV
vgchange 设置VG是否启动(active)
vgremove 删除一个VG

LV 命令
命令 描述
lvcreate 建立LV
lvscan 查询系统上的LV
lvdisplay 显示系统上的LV状态
lvextend 在LV里增加容量
lvreduce 在LV里减少容量
lvremove 删除一个LV
lvresize 对LV进行容量大小的调整

汇总
操作 PV VG LV
搜索(scan) pvscan vgscan lvscan
建立(create) pvcreate vgcreate lvcreate
列出(display) pvdisplay vgdisplay lvdisplay
增加(extend)
vgextend lvextend
减少(reduce)
vgreduce lvreduce
删除(remove) pvremove vgremove lvremove
改变容量(resize)
vgresize

上手操作
对于本次实践演练,我们构建了一个具有 40G 根存储(不重要)和三个大小为 5G 的外部磁盘的虚拟机,这些磁盘的大小可以是任意的。
安装 lvm2
CentOS 上安装:
sudo yum install -y lvm2创建物理卷
我们可以使用原始的未分区磁盘或分区本身创建物理卷。我们使用pvcreate命令创建物理卷:
sudo pvcreate /dev/sdcPhysical volume "/dev/sdc" successfully created.
接下来我将 /dev/sdd 分成相等的两部分。我们可以使用 cfdisk、parted 或者 fdisk ,它们都可以用来完成这项工作。
lsblk -o name,size,fstype | grep sddsdd 5G ├─sdd1 2.5G └─sdd2 2.5G
我们继续创建两个物理卷:
pvcreate /dev/sdd1 /dev/sdd2 Physical volume "/dev/sdd1" successfully created. Physical volume "/dev/sdd2" successfully created.
列出可用的物理卷
我们可以使用三个命令来获取可用物理卷的列表:pvscan、pvs和pvdisplay:
sudo pvscan PV /dev/sdc lvm2 [5.00 GiB] PV /dev/sdd1 lvm2 [2.50 GiB] PV /dev/sdd2 lvm2 [<2.50 GiB] Total: 3 [<10.00 GiB] / in use: 0 [0 ] / in no VG: 3 [<10.00 GiB]
sudo pvs PV VG Fmt Attr PSize PFree /dev/sdc lvm2 --- 5.00g 5.00g /dev/sdd1 lvm2 --- 2.50g 2.50g /dev/sdd2 lvm2 --- <2.50g <2.50g
sudo pvdisplay "/dev/sdc" is a new physical volume of "5.00 GiB" --- NEW Physical volume --- PV Name /dev/sdc VG Name PV Size 5.00 GiB Allocatable NO PE Size 0 Total PE 0 Free PE 0 Allocated PE 0 PV UUID SzSkdD-xKYa-4y7P-teyU-481p-uiQ8-qieMJJ "/dev/sdd1" is a new physical volume of "2.50 GiB" --- NEW Physical volume --- PV Name /dev/sdd1 VG Name PV Size 2.50 GiB Allocatable NO PE Size 0 Total PE 0 Free PE 0 Allocated PE 0 PV UUID 553Iy4-JJ21-LfIw-udtO-j9Cd-7gFS-iXXFVS "/dev/sdd2" is a new physical volume of "<2.50 GiB" --- NEW Physical volume --- PV Name /dev/sdd2 VG Name PV Size <2.50 GiB Allocatable NO PE Size 0 Total PE 0 Free PE 0 Allocated PE 0 PV UUID bf7ghn-QkPm-EUdp-GdyW-shMG-5sMn-VhNtYB
删除物理卷
我们可以使用以下命令删除物理卷 pvremove。就像一样 pvcreate,只需将设备(初始化为物理卷)传递给 pvremove 命令即可。
我将从 /dev/sdd2 列表中删除:
sudo pvremove /dev/sdd2 Labels on physical volume "/dev/sdd2" successfully wiped.
查看当前的物理卷:
sudo pvs PV VG Fmt Attr PSize PFree /dev/sdc lvm2 --- 5.00g 5.00g /dev/sdd1 lvm2 --- 2.50g 2.50g
我们可以看到,/dev/sdd2 已经被删除了。
卷组
卷组是物理卷的集合。它是 LVM 中的下一个抽象级别。卷组是组合多个原始存储设备的存储容量的存储池。
创建卷组
卷组是使用该 vgcreate 命令创建的。第一个参数 vgcreate 是要为该卷组指定的名称,其余参数是要支持存储池的物理卷的列表。
sudo vgcreate lvm_tutorial /dev/sdc /dev/sdd1 Volume group "lvm_tutorial" successfully created
列出卷组
列出卷组与列出物理卷类似,您可以使用具有不同详细级别的不同命令vgdisplay、vgscan和vgs。
sudo vgs VG #PV #LV #SN Attr VSize VFree lvm_tutorial 2 0 0 wz--n- 7.49g 7.49g
sudo vgscan Found volume group "lvm_tutorial" using metadata type lvm2
sudo vgdisplay --- Volume group --- VG Name lvm_tutorial 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 7.49 GiB PE Size 4.00 MiB Total PE 1918 Alloc PE / Size 0 / 0 Free PE / Size 1918 / 7.49 GiB VG UUID LYVE9P-vY0G-OAW6-an8q-yfBx-rrB1-YU61m1
列出附加到卷组的物理卷
我们可以使用以下命令列出连接到特定卷组的所有物理卷:
sudo pvdisplay -S vgname=lvm_tutorial -C -o pv_name PV /dev/sdc /dev/sdd1
我们可以获得物理卷的计数:
sudo vgdisplay -S vgname=lvm_tutorial -C -o pv_count #PV 3
扩展卷组
扩展卷组意味着向卷组添加额外的物理卷。
sudo vgextend lvm_tutorial /dev/sdd2 Physical volume "/dev/sdd2" successfully created. Volume group "lvm_tutorial" successfully extended
我们之前将物理卷 /dev/sdd2 删除了,所以在执行 vgextend 之前必须重新创建物理卷 /dev/sdd2。
再次查看卷组,以确定是否满足期望:
sudo pvdisplay -S vgname=lvm_tutorial -C -o pv_name PV /dev/sdc /dev/sdd1 /dev/sdd2

卷组缩容
卷组缩容意味着删除卷组的一个或多个物理卷。
sudo vgreduce lvm_tutorial /dev/sdc /dev/sdd1 Removed "/dev/sdc" from volume group "lvm_tutorial" Removed "/dev/sdd1" from volume group "lvm_tutorial"
如果卷组上有任何已经创建出来的逻辑卷,则我们无法简单删除物理卷。
再次检查:
sudo pvdisplay -S vgname=lvm_tutorial -C -o pv_name PV /dev/sdd2
为了后续的实验,需要再次加回来:
sudo vgextend lvm_tutorial /dev/sdc /dev/sdd1
删除卷组
我们可以使用 vgremove 来删除卷组:
sudo vgremove lvm_tutorial
(先不要执行该命令,因为我们还需要进行实验)
逻辑卷
逻辑卷就像一个分区,但它不是位于原始磁盘之上,而是位于卷组之上。我们可以,
使用任何文件系统格式化逻辑卷;
将其 mount 到文件系统中的任何位置。
创建逻辑卷
逻辑卷是使用该lvcreate命令创建的。常用的语法如下所示,
sudo lvcreate -L <size> -n <lvname> <vgname>
其中:
该-L选项针对新逻辑卷的大小,可以使用任何以“GB”、“MB”或“KB”结尾的整数。例如“1GB”;
该-n选项用于命名该逻辑卷;
卷组的名称。
因此,在为逻辑卷提供大小时,请确保卷组具有可用空间。
sudo lvcreate -L 5GB -n lv1 lvm_tutorial Logical volume "lv1" created.
逻辑卷上的常见操作
创建后,我们可以在路径中找到逻辑卷/dev/<vgname>/<lvname>。例如,在我们的例子中,卷的位置为:/dev/lvm_tutorial/lv1:
ls -l /dev/lvm_tutorial/lv1 lrwxrwxrwx 1 root root 7 May 17 02:09 /dev/lvm_tutorial/lv1 -> ../dm-0
我们可以像使用任何分区一样使用它,例如用ext4格式化:
sudo mkfs.ext4 /dev/lvm_tutorial/lv1
接下来我们可以将其 mount 到当前目录结构中的某个位置,例如/mnt:
sudo mount -t ext4 /dev/lvm_tutorial/lv1 /mnt
调整逻辑卷大小
我们可以使用命令扩展逻辑卷 lvextend 并使用命令减小其大小 lvreduce。或者我们可以使用单个命令 lvresize 来完成这两项任务。
首先我检查一下可用空间:
sudo vgs -S vgname=lvm_tutorial -o vg_free VFree <4.99g
查看 mount 信息:
mount | grep '/mnt'/dev/mapper/lvm_tutorial-lv1 on /mnt type ext4 (rw,relatime)
调整卷大小:
sudo lvresize -L +2GB lvm_tutorial/lv1
一般语法如下:
lvresize -L [+|-][Size] <vgname>/<lvname>
后面的符号 + 或 --L取决于您是否要分别尝试增大或减小卷大小。
卷大小增加后,文件系统也必须调整大小。对于 ext4,要使用的命令是resize2fs:
sudo resize2fs /dev/lvm_tutorial/lv1resize2fs 1.45.5 (07-Jan-2020)Filesystem at /dev/lvm_tutorial/lv1 is mounted on /mnt; on-line resizing requiredold_desc_blocks = 1, new_desc_blocks = 1The filesystem on /dev/lvm_tutorial/lv1 is now 1835008 (4k) blocks long.
并非所有文件系统都支持热调整大小,Ext4 和 XFS 是受支持的文件系统之一。
注意:XFS 文件系统可以支持扩容,但是不支持缩容。
删除逻辑卷
我们可以使用以下 lvremove 命令删除逻辑卷:
sudo lvremove lvm_tutorial/lv1Do you really want to remove and DISCARD active logical volume lvm_tutorial/lv1? [y/n]: y Logical volume "lv1" successfully removed
总结
关于缩容这块我们另外再讨论。此外 LVM 还依赖 device mapper,这部分我们也另外写文章讨论。
参考
《RHEL 逻辑卷管理器管理》
https://access.redhat.com/documentation/zh-cn/red_hat_enterprise_linux/7/html/logical_volume_manager_administration/index
《OpenEuler 使用LVM管理硬盘》https://docs.openeuler.org/zh/docs/20.03_LTS_SP4/docs/Administration/%E4%BD%BF%E7%94%A8LVM%E7%AE%A1%E7%90%86%E7%A1%AC%E7%9B%98.html
到顶部