基于硬盘构建的RAID通常提供固定大小的存储空间。管理员在初期规划的存储空间很难适应业务的变化。如下图所示,部署初期可能三个业务所需要的存储空间大致相同,但随着运营的进行,应用2突然变成比较火爆,存储空间被快速使用,从而导致存储资源不够的风险。而应用1和应用3则不温不火,存储资源有很多浪费。
那么有没有一种技术可以动态的调整存储资源的大小,可以保证在业务需要数据量大的时候能够扩容,业务需要数据量减小的时候可以进行缩容?通过存储资源的动态调配,保证各个应用的存储空间有一定的空闲率,这样既保证了存储资源利用率,又避免单个应用存储资源耗尽的风险。
目前市面上的企业级存储系统都是具备这个功能的,在存储端称为LUN的扩容与缩容。如果我们的业务没有使用企业级存储,那就要借助主机端的软件来实现。在Linux操作系统中也有类似的功能,称为逻辑卷管理技术(Logical Volume Manager,简称LVM)。
LVM的逻辑架构和原理都比较简单,如下图是LVM涉及的主要概念及相互关系。最底层是我们的存储设备,通常是硬盘。当然,也可以是基于企业级存储映射过来的LUN。如果想使用LVM的功能,首先需要基于硬盘创建的物理卷,然后基于物理卷来创建卷组,最后在卷组上创建逻辑卷。
创建物理卷的过程相当于对硬盘进行了一个简单的格式化,此后,硬盘中会包含一些元数据信息,例如PE(Physical Extent)和UUID的信息。基于物理卷可以创建卷组,卷组可以理解为一个包含所有PE的大池子(Pool)。而后,在该卷组上就可以创建逻辑卷了,逻辑卷根据创建是的特性来使用卷组中的物理卷。组成逻辑卷的基本单元称为LE(Logical Extent),LE与PE有一定的对应关系,具体关系与逻辑卷的类型有关,我们后面会详细介绍。
基于上图,我们从下往上简要介绍一下LVM涉及的主要概念,希望大家能够对LVM能够有更加深入的理解。
- 物理卷(Physical Volume, PV):物理卷构建在块设备之上,这些块设备可以是机械硬盘、SSD、硬盘分区或者RAID。物理卷其实是在块设备上做了一个简单的格式化,在块设备的指定位置写入了一些元数据信息(后文会详细介绍这部分内容)。
- 物理块(Physical Extent, PE):物理卷被划分为若干个物理块,默认物理块的大小是4MB。物理块是LVM管理的最小数据单元。
- 卷组(Volume Group, VG): 卷组是一个抽象层,可以理解为企业级存储的存储池的概念,
- 逻辑卷(Logical Volume, LV):逻辑卷是提供给用户使用的卷,逻辑卷提供一个连续的线性空间,逻辑卷的空间来自物理卷。
- 逻辑块(Logical Extent, LE): 逻辑块是逻辑卷的最小组成单元,逻辑块的大小在创建卷组时确定。任何一个逻辑卷都是由若干个逻辑块构成。
创建一个简单的逻辑卷
接下来我们实例来进一步理解一下上述概念,我们会通过创建不同类型的逻辑卷来理解上述关系。为了能够实现上述操作,我们总共需要4块硬盘,每个硬盘大小为1GB。大多数电脑可能不能满足这个要求,我们可以通过虚拟机来完成操作实验。
首先需要基于硬盘来创建物理卷,创建物理卷很简单,我们可以通过如下命令创建一个物理卷。
pvcreate /dev/sdb
这里面我们没有使用额外的选项,直接在一个硬盘上创建了一个物理卷,是不是很简单!我们可以通过pvdisplay命令来看一下物理卷的详细信息,具体如下图所示。可以看到里面包含PE的大小、数量和剩余数量等信息,另外还包括一个UUID,这个UUID用于唯一表示这个物理卷。
我们这里一共准备了4块硬盘, 分别在其他3块硬盘(sdc、sdd和sde)执行相同的命令即可。完成物理卷的创建后,我们就可以创建卷组了,执行如下命令可以创建一个卷组。
vgcreate vg_test /dev/sdb /dev/sdc /dev/sdd /dev/sde
类似的,我们可以通过vgdisplay命令来查看卷组的详细信息。由于没有提供额外的参数,创建卷组命令使用的是默认参数。通过详细信息可以看出PE的大小是4MB,卷组的大小是3.98GB。卷组的大小之所以不是4GB是因为元数据占用了部分空间。每个硬盘大小是1GB,因此有255个PE,整个卷组有1020个PE。
卷组创建成功后,我们再看一下物理卷的详细信息。可以看到PE相关信息得到了更新。其中PE的大小是4MB,数量为255,而且包含所属卷组的信息。
卷组创建成功后,我们就可以基于卷组来创建逻辑卷了。我们这里创建一个最简单的逻辑卷---线性卷。线性卷中的LE与物理卷中的PE有一对一的线性对应关系。我们可以很容易的根据线性卷的偏移地址找到物理卷中的PE。如下命令是创建一个大小为100MB的线性卷。
lvcreate -L100 -n testlv vg_test
通过lvdisplay可以查看逻辑卷的详细信息,可以看到该逻辑卷有25个LE。25个4MB的LE构成了逻辑卷100MB的逻辑空间。
完成逻辑卷的创建后,我们再看一下物理卷的详细信息。可以看到sdb上使用了25个PE。消耗的PE的数量与逻辑卷的LE的数量是一致的,也就是说逻辑卷的LE与物理卷的PE有一一对应的关系。
在数据层面,此时逻辑卷的数据与物理卷的对应关系如下图所示。逻辑卷的25个LE与物理卷sdb的前25个PE对应,位置也是一致的。有兴趣的同学可以进一步做一些实验,比如向逻辑卷0、4M和8M偏移的地方分别写一些数据,然后在从物理卷对应的位置读取数据,以判断对应关系。需要注意的是,由于物理卷上有一些元数据,这些元数据会占用一些空间,所以PE的起始位置是1MB的地方,而非0。
对逻辑卷扩容
前文已述,逻辑卷的最重要的特性之一就是卷的容量可以动态调整。我们可以通过lvextend命令对逻辑卷扩容。通过下面命令可以将逻辑卷testlv扩容成200MB,此时该逻辑卷具有50LE,使用了50个PE。
lvextend --size 200 /dev/vg_test/testlv
大家可以再查看一下物理卷sdb的详情,可以看到此时已分配的PE的数量变成了50。该命令不仅仅可以在原有的物理卷扩容,也可以指定目的物理卷,比如下面命令:
lvextend --size 200 /dev/vg_test/testlv /dev/sdc
此时,新增加的100MB的容量所对应的PE是在sdc上面。整个逻辑卷与两个物理卷之间数据的对应关系如下图所示。其中逻辑卷的绿色部分的LE在物理卷sdb上,紫色部分的LE在物理卷sdc上面。
LVM的其他操作
除了上述的线性卷外,LVM还有很多其他特性,比如镜像卷、RAID卷和快照等特性。限于篇幅,本文不再一一赘述。这里以镜像卷为例再深入介绍一下。为了验证简单,我们在接下来的操作之前将前面的逻辑卷删除。
lvremove /dev/vg_test/testlv
接下来以镜像卷为例再深入介绍一下LVM的相关内容。所谓镜像卷,是指逻辑卷的数据会被同时放置到多个物理卷上。以两个物理卷的镜像卷为例,逻辑卷中的LE与物理卷PE之间的关系如下图所示。比如LE0的数据会同时存储在物理卷sdb的PE1和物理卷sdc的PE1上面。另外需要注意的是,LE0不一定对应着PE1,而是跟物理卷可以使用的PE相关。
我们实际操作一下,创建一个镜像卷。具体操作非常简单,命令如下所示:
lvcreate -L 100 -m1 -n m_lv vg_test /dev/sdb /dev/sdc
在上述命令中-L用于指定逻辑卷的大小,-m1表示创建一个镜像卷,-n用于指定逻辑卷的名称。后面跟的两个物理卷表示镜像卷将创建在着两个物理卷上。创建完成后,我们可以通过lvdisplay命令查看一下镜像卷的详情。
通过上图可以看出,逻辑卷占用的LE是25个,具备一个段(Segments)空间。大家可能会好奇,逻辑卷与物理卷的对应关系是怎么确定的?这部分内容我们后续会详细介绍,这里暂时不做介绍。
我们通过pvdisplay再看一下物理卷的详细信息,需要关注的是这里消耗的PE的数量是26,而非25。也就是说比逻辑卷的空间多使用了一个PE的空间。大家可以考虑一下为什么会多消耗一个PE。
至此,我们对LVM的做了一个简要的介绍,包括LVM中涉及的主要概念,逻辑卷的扩容和逻辑卷与物理卷的映射关系等。后面我们会步步深入,介绍LVM的更多细节。