有时候我们会面临这样一个窘境:分区内的数据快速增长,分区剩余空间几乎不够用了。这个时候你可能得想办法找个更大的硬盘或者分区,把数据挪过去,费时费力。有时候分区一开始分大了,很多空间又浪费了。
是否有这样一种机制,能够允许分区空间能够进行弹性伸缩呢?
这就是我们本节要介绍的主角:LVM(Logical Volume Manager)
如上所述,LVM可以理解为一种空间可以弹性调整的分区。在学习LVM之前,需要介绍一些与LVM有关的专有名词。
PV:物理卷
制作LVM的第一步,就是制作LVM的物理卷(PV)。LVM的物理卷可以是分区、磁盘等块设备文件。物理卷中最小的存储单位称为PE。PE默认的大小是4M
VG:卷组
一个或多个PV做成一个组,这就是卷组(VG)。逻辑卷的空间都是从卷组分配而来的。
对于LVM1来说一个VG最多包含65534个PE,也就是说,默认的VG最大容量为4M*65534约为256G,如果你想要更大,那么设置PV的时候,将PE的大小调大即可。(PE大小重新调整需要重建VG)
LVM2(目前centos7默认的版本),VG没有了PE数量的限制。
LV:逻辑卷
从VG中取出一定的空间,进行LVM格式的分区,就构成了逻辑卷。同一个LV可能使用了多个PV中的空间
PV、VG、LV之间的关系:
分区或者硬盘被制作成PV,PV的最小存储单元是PE。将多个零散的PV整合起来构成VG,再从VG上划空间给LV。当LV想扩容的时候,就从VG里面再取一些PE过来。想缩容的时候,就将LV里的PE还一部分给VG。(尽量不要去尝试缩容,可能会导致数据丢失或文件系统损坏)
这三者的关系如下图:
我在虚拟机上加了两块虚拟硬盘,供此次实验使用:
[root@localhost ~]# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 20G 0 disk
├─sda1 8:1 0 1G 0 part /boot
└─sda2 8:2 0 19G 0 part
├─centos-root253:0 0 17G 0lvm /
└─centos-swap253:1 0 2G 0lvm [SWAP]
sdb 8:16 0 20G 0 disk
sdc 8:32 0 20G 0 disk
sr0 11:0 1 906M 0 rom
[root@localhost ~]#
与pv相关的命令
pvcreate DEVICE:将分区或磁盘创建成PV
pvscan:查找当前系统上的PV
pvdisplay:显示目前系统上PV的状态。
pvremove:移除PV,使分区不再具有PV属性
举例:
sdb裸盘制成PV,sdc分出一个5G大小的分区制成PV,查看PV相关信息。
首先对sdc进行分区
[root@localhost ~]# fdisk /dev/sdc
Welcome to fdisk (util-linux 2.23.2).
Changes will remain in memory only, untilyou decide to write them.
Be careful before using the write command.
Device does not contain a recognizedpartition table
Building a new DOS disklabel with diskidentifier 0xa8ca5dfd.
Command (m for help): n
Partition type:
p primary (0 primary, 0extended, 4 free)
e extended
Select (default p): p
Partition number (1-4, default 1):
First sector (2048-41943039, default 2048):
Using default value 2048
Last sector, +sectors or +size{K,M,G} (2048-41943039,default 41943039): +5G
Partition 1 of type Linux and of size 5 GiBis set
Command (m for help): p
Disk /dev/sdc: 21.5 GB, 21474836480 bytes,41943040 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes /512 bytes
I/O size (minimum/optimal): 512 bytes / 512bytes
Disk label type: dos
Disk identifier: 0xa8ca5dfd
Device Boot Start End Blocks Id System
/dev/sdc1 2048 10487807 5242880 83 Linux
此处最好把ID改为8e,便于其他管理员了解其用途。(不改不会影响使用,但它就像代码的注释,我们作为创建者,应该尽量对后来的维护者友好一点)
Command (m for help): t
Selected partition 1
Hex code (type L to list all codes): 8e
Changed type of partition 'Linux' to 'LinuxLVM'
Command (m for help): p
Disk /dev/sdc: 21.5 GB, 21474836480 bytes,41943040 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes /512 bytes
I/O size (minimum/optimal): 512 bytes / 512bytes
Disk label type: dos
Disk identifier: 0xa8ca5dfd
Device Boot Start End Blocks Id System
/dev/sdc1 2048 10487807 5242880 8e Linux LVM
Command (m for help): w
The partition table has been altered!
Calling ioctl() to re-read partition table.
Syncing disks.
[root@localhost ~]#
确认新建分区是否已经被内核识别
[root@localhost ~]# cat /proc/partitions | grep sdc1
8 33 5242880 sdc1
[root@localhost ~]#
创建PV
[root@localhost ~]# pvcreate /dev/sdb
Physical volume "/dev/sdb" successfully created.
[root@localhost ~]# pvcreate /dev/sdc1
Physical volume "/dev/sdc1" successfully created.
[root@localhost ~]#
查看PV相关信息
[root@localhost ~]# pvscan
PV/dev/sda2 VG centos lvm2 [<19.00 GiB / 0 free]
PV/dev/sdc1 lvm2 [5.00GiB]
PV/dev/sdb lvm2[20.00 GiB]
Total: 3 [<44.00 GiB] / in use: 1 [<19.00 GiB] / in no VG: 2[25.00 GiB]
[root@localhost ~]# pvdisplay
---Physical volume ---
PVName /dev/sda2
VGName centos
PVSize <19.00 GiB / notusable 3.00 MiB
Allocatable yes (butfull)
PESize 4.00 MiB
Total PE 4863
Free PE 0
Allocated PE 4863
PVUUID KmbaCs-HXsh-k66M-jnw1-bW4r-MFe8-KPI3Go
"/dev/sdc1" is a new physical volume of "5.00 GiB"
---NEW Physical volume ---
PVName /dev/sdc1
VGName
PVSize 5.00 GiB
Allocatable NO
PESize 0
Total PE 0
Free PE 0
Allocated PE 0
PVUUID Jbdlqs-6mDm-tdxO-yTD0-YUk6-doN9-PCd0YK
"/dev/sdb" is a new physical volume of "20.00 GiB"
---NEW Physical volume ---
PVName /dev/sdb
VGName
PVSize 20.00 GiB
Allocatable NO
PESize 0
Total PE 0
Free PE 0
Allocated PE 0
PVUUID pgyh4y-3XJb-Nxmn-B3iP-6W2d-vvyQ-HWiicZ
创建与管理VG
创建VG
vgcreate [options] VGname PV1 PV2 …
常见选项:
-s 指定PE大小
-t,--test 测试,并不真的创建
-v 显示详细信息
查找系统上是否有VG存在:vgscan
显示vg的详细信息:vgdisplay VGNAME
往VG里添加额外的PV:vgextend DEVICE
从VG中移除PV(谨慎使用):vgreduce DEVICE
删除VG:vgremove VGNAME
举例:
创建VG,将sdb和sdc1两个PV加入其中
[root@localhost ~]# vgcreate vgpool1/dev/sdb /dev/sdc1
Volume group "vgpool1" successfully created
[root@localhost ~]#
[root@localhost ~]# vgscan
Reading volume groups from cache.
Found volume group "centos" using metadata type lvm2
Found volume group "vgpool1" using metadata type lvm2
[root@localhost ~]# vgdisplay vgpool1
---Volume group ---
VGName vgpool1
System ID
Format lvm2
Metadata Areas 2
Metadata Sequence No 1
VGAccess read/write
VGStatus resizable
MAXLV 0
CurLV 0
Open LV 0
MaxPV 0
CurPV 2
ActPV 2
VGSize 24.99 GiB
PESize 4.00 MiB
Total PE 6398
Alloc PE / Size 0 / 0
Free PE / Size 6398 / 24.99 GiB
VGUUID yTpx8x-z3ic-JWY2-BPTv-T5rg-NIKr-sz4LeY
[root@localhost ~]#
可以看到我们得到了一个24.99G,名为vgpool1的VG,PE大小是4M
此时回过头去看PV会发现它也有了VG归属
[root@localhost ~]# pvdisplay /dev/sdb | grep VG
VGName vgpool1
[root@localhost ~]#
LV相关的管理命令:
以下列出相关管理命令,按需展开说明。更详细的用法可参见man手册
lvcreate:创建LV
lvscan:查询系统上已有的LV
lvdisplay:显示LV的详细信息
lvextend:扩容LV
lvreduce:缩容LV
lvremove:删除LV
lvresize:调整LV的大小
创建LV:
lvcreate -L SIZE [LV_NAME] VGNAME
举例:
在刚刚创建的VG上创建一个12G的LV。
[root@localhost ~]# lvdisplay /dev/vgpool1 /lvol0
---Logical volume ---
LVPath /dev/vgpool1/lvol0
LVName lvol0
VGName vgpool1
LVUUID gSHOYK-qPsM-Et4R-r5lP-Fs43-waYr-TGk3yZ
LVWrite Access read/write
LVCreation host, time localhost.localdomain, 2018-08-29 10:27:06 -0400
LVStatus available
#open 0
LVSize 20.00 GiB
Current LE 5120
Segments 2
Allocation inherit
Read ahead sectors auto
-currently set to 8192
Block device 253:2
[root@localhost ~]#
至此,LV创建完成,我们创建了一个名为lvol0的LV。对应设备文件/dev/vgpool1/lvol0,我们在其上建立文件系统并挂载之后即可使用。
[root@localhost ~]# mkdir /mnt/lvmpool0_mount
[root@localhost ~]# mkfs.xfs /dev/vgpool1/lvol0
meta-data=/dev/vgpool1/lvol0 isize=512 agcount=4, agsize=1310720 blks
= sectsz=512 attr=2, projid32bit=1
= crc=1 finobt=0, sparse=0
data = bsize=4096 blocks=5242880,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@localhost ~]# mount /dev/vgpool1/lvol0 /mnt/lvmpool0_mount/
[root@localhost ~]#
[root@localhost ~]# df -h | grep lvol0
/dev/mapper/vgpool1-lvol0 20G 33M 20G 1% /mnt/lvmpool0_mount
此时该逻辑卷就能够被使用了。
这是相对底层和复杂的原理了,与LVM的实现原理有关。幸运的是我们无需去通读源码,下面简单介绍一点点点点,免得你发现太多疑问。
VG创建完毕后,你会发现/dev下会多出一个与VG同名的目录。
创建完LV之后,你会发现该VG目录下,会多出来一个文件,这个文件其实不是设备文件,而是一个软链接,指向一个设备文件。
[root@localhost mapper]# ll /dev/vgpool1/
total 0
lrwxrwxrwx. 1 root root 7 Aug 29 23:38lvol0 -> ../dm-2
lrwxrwxrwx. 1 root root 7 Aug 29 23:38snap_lv0 -> ../dm-5
这就是Device Mapper(设备映射机制)在作祟。
系统中所有的设备映射可以到/dev/mapper目录下查看
[root@localhost mapper]# ll /dev/mapper/
total 0
lrwxrwxrwx. 1 root root 7 Aug 29 08:11 centos-root -> ../dm-0
lrwxrwxrwx. 1 root root 7 Aug 29 08:11 centos-swap -> ../dm-1
crw-------. 1 root root 10, 236 Aug 2908:11 control
lrwxrwxrwx. 1 root root 7 Aug 29 23:38 vgpool1-lvol0 ->../dm-2
lrwxrwxrwx. 1 root root 7 Aug 29 23:38 vgpool1-lvol0-real ->../dm-3
lrwxrwxrwx. 1 root root 7 Aug 29 23:38 vgpool1-snap_lv0 ->../dm-5
lrwxrwxrwx. 1 root root 7 Aug 29 23:38 vgpool1-snap_lv0-cow-> ../dm-4
/dev下的dm-1,2,3,4,5才是真正的块设备文件。
暂时了解到这种程度即可。
下一节为大家介绍LVM的扩容与快照机制
关注本公众号获取每日更新