主要内容
什么是逻辑卷管理(LVM)
传统的硬盘都是基于分区划分的,很容易出现的问题是:应该划分多少空间给某个分区?分区空间给多了容易出现浪费,给少了不够用,以后扩展太麻烦。LVM就是为了解决这个问题而出现的,它的优点是可以动态调整空间的容量。
LVM面向的是多个硬盘,或者单个硬盘的多个分区,在这个基础上创造一个逻辑抽象层,从而对这些硬盘或分区容量进行管理,达到灵活调整空间的目的。
LVM架构
了解LVM架构之前,需要先说一下几个概念:PV、VG和LV。
- PV:全称Physical Volume,它是LVM的最底层结构。PV可以是分区,也可以是整个硬盘,但建议使用整个硬盘作为一个PV。
- VG:全称Volume Group,多个PV组成一个VG。
- LV:全称Logical Volume,一个LV由一个或者多个VG组成,LV是整个逻辑卷管理的最上层,我们使用的文件系统从这一层产生,也是通过这一层达到灵活调整各个文件系统的容量的目的。
它们之间的关系可以从下图看出
Physical Extends(PE)
实际上,除了上面三个可以“看得见”的概念外,还有一个比较重要的概念,这个概念比PV还要底层,那就是PE(Physical Extends)。上图中没有出现这个概念,原因在于,PE是作为一个最小储存单元出现的,它的作用类似于硬盘分区时所设置的block大小,也就是说,LV最终有多少可以使用的容量,由这个PE决定,在Centos7中,PE的默认值为4m,假如一个500G的硬盘,它的PE数量就是500*1024/4。
动态调整空间原理
LVM架构中,可以被扩展的分别是VG层和LV层,但是LV层的扩展是以VG层为基础的,因为LV层的空间是从VG层中创建出来的,如果LV层空间不足需要被扩展,那么VG层必须有未被使用的空间(Free Space)。如下图
上图中,假如原来VG的容量是PV1+PV2的容量,也就是400m,一旦这400m分配完毕,最终LV的容量就等于VG的容量,如果以后LV要做扩容,就必须先扩展VG(加入PV3),然后LV就可以利用PV3的容量(200m)来做扩展。
相关命令
在进行LVM实操之前,需要了解一些命令,从pv到lv的每一层的操作,例如创建、移除、扩展等,Linux都提供相关的命令。
pv层命令
- pvs:显示physical volume的相关信息(摘要信息)
- pvdisplay:显示physical volume的相关属性
- pvscan:列出所有的physical volume,类似pvs
- pvcreate:创建physical volume
vg层命令
- vgs:显示volume group的相关信息
- vgdisplay:显示volume group的相关属性
- vgscan:列出所有volume group
- vgcreate:创建volume group
- vgextend:把physical volume添加到指定的volume group
lv层命令
- lvs:显示logical volume的相关信息
- lvdisplay:显示logical volume的相关属性
- lvscan:列出所有的logical volume
- lvcreate:创建logical volume
- lvextend:向指定logical volume添加空间
很明显,每一次的命令都和它们各自层的名称相关,例如pv层命令以pv开头,vg层命令以vg开头。上面列出的并非所有的命令,只是最常用的命令,每一个命令都可以使用参数--help
获得帮助信息。
LVM实操
在基本了解LVM之后,就可以进行实际操作,不过在此之前,请确保磁盘有多余的空间。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
[root@study ~]# gdisk -l /dev/sda GPT fdisk (gdisk) version 0.8.6 Partition table scan: MBR: protective BSD: not present APM: not present GPT: present Found valid GPT with protective MBR; using GPT. Disk /dev/sda: 104857600 sectors, 50.0 GiB Logical sector size: 512 bytes Disk identifier (GUID): 7875497F-C4CF-4E90-B93A-3C2DF18C3B74 Partition table holds up to 128 entries First usable sector is 34, last usable sector is 104857566 Partitions will be aligned on 2048-sector boundaries Total free space is 35639229 sectors (17.0 GiB) Number Start (sector) End (sector) Size Code Name 1 2048 6143 2.0 MiB EF02 2 6144 2103295 1024.0 MiB 0700 3 2103296 65026047 30.0 GiB 8E00 4 65026048 67123199 1024.0 MiB 8300 Linux filesystem 5 67123200 69220351 1024.0 MiB 0700 Microsoft basic data |
通过上面的命令可以知道,磁盘中还有17G的可用空间,由于磁盘使用的是gpt分区格式,所以使用gdisk
命令,如果使用的是mbr分区格式,可改用fdisk
命令。
创建PV
这个例子中使用分区作为PV,但建议用整个硬盘作为一个PV,在创建pv的时候,分区和整个硬盘有点不一样,使用分区为PV,创建分区的时候需要把分区类型设置为Linux LVM(8E00),而整个硬盘则不需要这样的设置。下面的例子以上面图2为范本创建的,因此,先创建3个200m的PV(但要先把3个LVM类型的分区创建出来):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
[root@study ~]# gdisk -l /dev/sda GPT fdisk (gdisk) version 0.8.6 Partition table scan: MBR: protective BSD: not present APM: not present GPT: present Found valid GPT with protective MBR; using GPT. Disk /dev/sda: 104857600 sectors, 50.0 GiB Logical sector size: 512 bytes Disk identifier (GUID): 7875497F-C4CF-4E90-B93A-3C2DF18C3B74 Partition table holds up to 128 entries First usable sector is 34, last usable sector is 104857566 Partitions will be aligned on 2048-sector boundaries Total free space is 34410429 sectors (16.4 GiB) Number Start (sector) End (sector) Size Code Name 1 2048 6143 2.0 MiB EF02 2 6144 2103295 1024.0 MiB 0700 3 2103296 65026047 30.0 GiB 8E00 4 65026048 67123199 1024.0 MiB 8300 Linux filesystem 5 67123200 69220351 1024.0 MiB 0700 Microsoft basic data 6 69220352 69629951 200.0 MiB 8E00 Linux LVM 7 69629952 70039551 200.0 MiB 8E00 Linux LVM 8 70039552 70449151 200.0 MiB 8E00 Linux LVM |
3个Linux LVM分区准备就绪,接下来就可以创建PV,使用两个PV组成一个VG,另一个PV备用:
1 2 3 4 |
[root@study ~]# pvcreate /dev/sda{6,7,8} Physical volume "/dev/sda6" successfully created. Physical volume "/dev/sda7" successfully created. Physical volume "/dev/sda8" successfully created. |
上面的命令同时创建3个PV,也可以一个一个创建。创建好可以使用pvs或pvscan查看:
1 2 3 4 5 6 |
[root@study mnt]# pvscan PV /dev/sda3 VG centos lvm2 [30.00 GiB / 14.00 GiB free] PV /dev/sda6 lvm2 [200.00 MiB] PV /dev/sda8 lvm2 [200.00 MiB] PV /dev/sda7 lvm2 [200.00 MiB] Total: 4 [<30.59 GiB] / in use: 1 [30.00 GiB] / in no VG: 3 [600.00 MiB] |
显示1个VG使用中,3个没有加入VG,名为centos的PV,也就是 /dev/sda3是在系统安装过程中创建的。
创建VG
PV准备好,就可以用PV建立一个VG。
1 2 3 4 5 6 |
[root@study ~]# vgcreate vgdemo /dev/sda{6,7} <-- 这一行使用前面创建的pv建立一个VG Volume group "vgdemo" successfully created [root@study ~]# vgs VG #PV #LV #SN Attr VSize VFree centos 1 3 0 wz--n- 30.00g 14.00g vgdemo 2 0 0 wz--n- 392.00m 392.00m |
通过一行简单的命令,就创建了名为vgdemo的VG,通过vgdisplay可以获得更详细的信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
[root@study mnt]# vgdisplay vgdemo --- Volume group --- VG Name vgdemo 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 392.00 MiB PE Size 4.00 MiB Total PE 98 Alloc PE / Size 0 / 0 Free PE / Size 98 / 392.00 MiB VG UUID Ucrz5o-GDZG-JJrK-dPVP-AU6G-iRge-psFTQa |
可见Alloc PE / Size都是0,因为目前还没有LV从这个VG创建出来。
创建LV
创建LV是我们的最终目的,Linux文件系统就是从LV层创建的。我们即将利用上面的VG创建两个LV,并建立两个文件系统,分别是/mnt/storage和/mnt/backup。
建立两个LV
1 2 3 4 |
[root@study ~]# lvcreate -l 50%FREE vgdemo -n lvstorage Logical volume "lvstorage" created. [root@study ~]# lvcreate -l 100%FREE vgdemo -n lvbackup Logical volume "lvbackup" created. |
如果建立的过程中出现警告,选择y即可。上面第一条命令的意思是:利用vgdemo的50%可用空间创建一个名为lvstorage的LV;第二条命令则是:利用vgdemo的100%可用空间创建名为lvbackup的LV。
到这里为止,LV已经创建完毕,vgdemo的所有空间也已经用尽。剩下的就是使用这两个LV建立文件系统
建立文件系统
下面两个命令各自完成后都会输出一些格式化信息,为了简化排版,这些输出不在此列出。
1 2 |
[root@study ~]# mkfs.xfs /dev/vgdemo/lvstorage [root@study ~]# mkfs.xfs /dev/vgdemo/lvbackup |
文件系统创建后还不能用,因为还没有挂载点,接下来的工作就是创建它们的挂载点。
1 2 3 |
[root@study ~]# mkdir /mnt/storage; mkdir /mnt/backup [root@study ~]# mount /dev/vgdemo/lvstorage /mnt/storage [root@study ~]# mount /dev/vgdemo/lvbackup /mnt/backup |
到这一步,一个可用的文件系统就完成了,使用df
命令查看它们是否已经正确挂载。
1 2 3 4 5 6 7 8 9 10 11 12 |
[root@study ~]# df -H Filesystem Size Used Avail Use% Mounted on /dev/mapper/centos-root 11G 6.7G 4.1G 63% / devtmpfs 940M 0 940M 0% /dev tmpfs 956M 0 956M 0% /dev/shm tmpfs 956M 9.5M 946M 1% /run tmpfs 956M 0 956M 0% /sys/fs/cgroup /dev/sda2 1.1G 425M 639M 40% /boot /dev/mapper/centos-home 5.4G 464M 4.9G 9% /home tmpfs 192M 33k 192M 1% /run/user/1000 /dev/mapper/vgdemo-lvstorage 203M 11M 192M 6% /mnt/storage /dev/mapper/vgdemo-lvbackup 203M 11M 192M 6% /mnt/backup |
扩展空间容量
假如有一天,文件系统/mnt/storage的空间不足需要扩展,那么只需要使用lvextend
命令即可达到目的。但是我们说过,要扩展LV,VG层必须有可用的空间,但是前面创建两个LV的时候已经使用了VG层的所有空间,因此要扩展LV,必须先扩展VG层,VG层的扩展只需要添加PV即可解决,使用的命令是vgextend
。
扩展VG层
从一开始的时候,我们划分了三个LVM分区,分别建立了三个PV,两个用来建立VG(/dev/sda6和/dev/sda7),一个作为后备使用(/dev/sda8)。现在,可以使用/dev/sda8来扩展这个VG。扩展VG之前先看一下它的信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
[root@study ~]# vgdisplay vgdemo --- Volume group --- VG Name vgdemo System ID Format lvm2 Metadata Areas 2 Metadata Sequence No 3 VG Access read/write VG Status resizable MAX LV 0 Cur LV 2 Open LV 2 Max PV 0 Cur PV 2 Act PV 2 VG Size 392.00 MiB PE Size 4.00 MiB Total PE 98 Alloc PE / Size 98 / 392.00 MiB Free PE / Size 0 / 0 VG UUID Ucrz5o-GDZG-JJrK-dPVP-AU6G-iRge-psFTQa |
所有的98个PE已经全部分配完毕,Free PE为0,正如我们所说的,所有空间都已经被LV使用了。现在开始扩展这个VG:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
[root@study ~]# vgextend vgdemo /dev/sda8 Volume group "vgdemo" successfully extended [root@study ~]# vgdisplay vgdemo --- Volume group --- VG Name vgdemo System ID Format lvm2 Metadata Areas 3 Metadata Sequence No 4 VG Access read/write VG Status resizable MAX LV 0 Cur LV 2 Open LV 2 Max PV 0 Cur PV 3 Act PV 3 VG Size 588.00 MiB PE Size 4.00 MiB Total PE 147 Alloc PE / Size 98 / 392.00 MiB Free PE / Size 49 / 196.00 MiB VG UUID Ucrz5o-GDZG-JJrK-dPVP-AU6G-iRge-psFTQa |
经过扩展之后的VG,可用的PE数量变成了49(196m),VG扩展完成,接下来就是为LV扩容。
扩展LV
我们扩展的LV目标是/dev/vgdemo/lvstorage,详细命令如下
1 2 3 4 5 6 7 8 9 10 11 12 13 |
[root@study ~]# lvextend -l +100%FREE -r /dev/vgdemo/lvstorage Size of logical volume vgdemo/lvstorage changed from 196.00 MiB (49 extents) to 392.00 MiB (98 extents). Logical volume vgdemo/lvstorage successfully resized. meta-data=/dev/mapper/vgdemo-lvstorage isize=512 agcount=4, agsize=12544 blks = sectsz=512 attr=2, projid32bit=1 = crc=1 finobt=0 spinodes=0 data = bsize=4096 blocks=50176, imaxpct=25 = sunit=0 swidth=0 blks naming =version 2 bsize=4096 ascii-ci=0 ftype=1 log =internal bsize=4096 blocks=855, version=2 = sectsz=512 sunit=0 blks, lazy-count=1 realtime =none extsz=4096 blocks=0, rtextents=0 data blocks changed from 50176 to 100352 |
命令的意思是:用vgdemo的100%可用空间扩展文件系统/dev/vgdemo/lvstorage。-r
参数的作用是:扩展LV的同时把文件系统也一起扩展。如果不添加这个参数,只会扩展LV,文件系统不受影响。需要注意的是:xfs格式文件系统只能被扩展,而不能被收缩。
如果在扩展LV的时候忘记添加-r
参数,那么需要另外使用xfs_growfs
命令扩展文件系统。例如:
1 2 |
[root@study ~]# lvextend -l +50%FREE /dev/vgdemo/lvstorage [root@study ~]# xfs_growfs /mnt/storage |
上面的第一条命令中,由于没有添加-r
参数,挂载点/mnt/storage所在的文件系统不会受到影响,那么我们就要使用xfs_growfs
手动扩展文件系统,这就是第二条命令的目的。
移除PV
如果要把PV从一个VG中移除,请先确定这个PV设备没有PE被使用。可以使用pvdisplay命令查看,如果Allocated PE不为0,则这个PV不能被移除。要移除正在使用中的PV,需要先释放这个PV的空间,可以使用pvmove
命令。例如:
1 2 |
#pvmove source target pvmove /dev/sda6 |
如果pvmove不添加目标地址参数,则目标由pvmove自行选择。
pvmove命令把源pv的空间移到目标pv,如果系统没有足够空间的pv,则pvmove命令执行失败。
一旦pv的Allocated PE为0,这个pv就可以使用vgreduce命令从vg中移除。例如:
1 2 |
#vgreduce vgname pvname vgreduce centos /dev/sda6 |
移除LVM设备
移除LVM设备需要以下几个步骤:
- 第一,把挂载点的文件系统取消挂载(umount)
- 第二,把LV层的激活状态取消[非必须](lvchange)
- 第三,移除LV层(lvremove)
- 第四,取消VG层的激活状态[非必须](vgchange)
- 第五,移除VG层(vgremove)
- 第六,移除PV
其中第二步是非必须的,如果当前的LV处于活动状态,使用lvremove移除的时候,系统会询问是否移除当前活动的logical volume,选yes即可。
1 2 3 |
[root@study ~]# lvremove /dev/vgdemo/lvstorage /dev/vgdemo/lvbackup [root@study ~]# vgremove vgdemo [root@study ~]# pvremove /dev/sda{6,7,8} |
最后,把不需要的分区删掉即可。
LVM快照
快照也是一种LV,它的类型就是snapshot,之前我们创建的LV也有类型,只不过是默认的的类型,就是linear(线性LV)。快照的作用是保存指定LV(这个指定的LV叫做origin,或者源LV)某个时刻的一种状态(源LV里面有什么文件),当某天已创建快照的LV丢失了文件,就可以通过快照找回。但是快照有别于备份,快照与备份是两个不同的概念,不能混淆。
快照的特点是,它保存的是源LV某个时刻的状态,任何在快照拍摄之后所创建的文件都不会被快照保存,因此快照拍摄后创建的文件丢失了无法利用快照找回,也就是说快照并不会自动更新它的状态。
另一个特点是,快照创建的速度非常快,因为它保存的只是源LV中的元数据(metadata),例如文件列表,元数据中并不保存文件的实际内容。那么,既然它不保存文件的内容,以后文件丢失它是根据什么恢复的呢?很简单,就是copy on wirte(cow) 技术,当源LV中的文件被改动的时候,它才会实际上被复制到快照中,采用这种技术,快照的容量就可以小于源LV的容量。不过,这就有新的问题产生:快照创建之后的一段时间,源LV继续写入文件,当源LV的所有文件大小(total size)大于快照容量的时候,快照就会自动失效,且里面的文件无法找回,所以,如果源LV文件系统是经常变更的,建议快照的容量和源LV一样大。
创建快照
创建快照也是使用lvcreate
命令,不过必须带上-s
参数,还要指定源LV。
1 2 3 |
[root@study ~]# lvcreate -l 100%FREE -n lvdemosnap -s /dev/vgdemo/lvdemo Using default stripesize 64.00 KiB. Logical volume "lvdemosnap" created. |
上面的命令用vgdemo(VG)剩余的所有空间为/dev/vgdemo/lvdemo (LV)创建了一个快照。然后,就可以用lvs命令查看:
1 2 3 4 5 6 7 |
[root@study ~]# lvs LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert home centos -wi-ao---- 5.00g root centos -wi-ao---- 10.00g swap centos -wi-ao---- 1.00g lvdemo vgdemo owi-aos--- 132.00m lvdemosnap vgdemo swi-a-s--- 60.00m lvdemo 0.03 |
可以看到,lvdemosnap快照的总空间是60m,而源LV(orgin)的总空间是132m。快照也是LV,因此它也可以挂载出来,挂载后使用df
命令查看(如果使用xfs文件格式,挂载的时候需要使用nouuid参数)
1 2 3 4 5 6 7 8 9 10 11 12 13 |
[root@study ~]# mount -o nouuid /dev/vgdemo/lvdemosnap /srv/snapshot1/ [root@study ~]# df Filesystem 1K-blocks Used Available Use% Mounted on /dev/mapper/centos-root 10475520 6507400 3968120 63% / devtmpfs 917240 0 917240 0% /dev tmpfs 932992 0 932992 0% /dev/shm tmpfs 932992 9252 923740 1% /run tmpfs 932992 0 932992 0% /sys/fs/cgroup /dev/sda2 1038336 414620 623716 40% /boot /dev/mapper/centos-home 5232640 452744 4779896 9% /home tmpfs 186600 36 186564 1% /run/user/1000 /dev/mapper/vgdemo-lvdemo 131748 124696 7052 95% /srv/lvm /dev/mapper/vgdemo-lvdemosnap 131748 124696 7052 95% /srv/snapshot1 |
df显示lvdemo和它的快照lvdemosnap的资料是一摸一样的(实际上并不是)。实际上快照使用了多少空间,可以使用lvdisplay
命令观察
1 2 3 4 5 |
[root@study ~]# lvdisplay /dev/vgdemo/lvdemosnap --- Logical volume --- [部分内容省略] Allocated to snapshot 3.37% [部分内容省略] |
由于是新创建的快照,这个时候只有元数据,只使用了不到4%(3.37%)。
测试快照
我们先看一下拍照拍摄的时候源LV中的文件:
1 2 3 4 5 6 |
[root@study ~]# ls -lh /srv/lvm total 45M -rw-r--r--. 1 root root 20M Feb 2 16:16 file1 -rw-r--r--. 1 root root 5.0M Feb 2 16:07 file2 -rw-r--r--. 1 root root 10M Feb 2 16:07 file3 -rw-r--r--. 1 root root 10M Feb 2 16:13 file4 |
都是一些测试用的文件,现在我们尝试删除file1(大小是20M),然后再使用lvdisplay命令观察
1 2 3 4 5 6 |
[root@study ~]# rm /srv/lvm/file1 [root@study ~]# lvdisplay /dev/vgdemo/lvdemosnap --- Logical volume --- [省略部分内容] Allocated to snapshot 36.88% [省略部分内容] |
使用量变成了36.88%,也就是说,当我们删除源LV中的file1文件的时候,该文件才会被同时复制到快照中保存,这就是copy on write。
现在,我们再尝试往源LV中写入超过60M的文件(超过快照总空间)
1 2 3 4 5 6 7 8 9 10 11 |
[root@study ~]# dd if=/dev/zero of=/srv/lvm/bigfile bs=1M count=30 30+0 records in 30+0 records out 31457280 bytes (31 MB) copied, 0.267537 s, 118 MB/s [root@study ~]# lvs LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert home centos -wi-ao---- 5.00g root centos -wi-ao---- 10.00g swap centos -wi-ao---- 1.00g lvdemo vgdemo owi-aos--- 132.00m lvdemosnap vgdemo swi-I-s--- 60.00m lvdemo 100.00 |
注意swi-I-s—这一串字符中的I(Invalid),意思是该快照已经无效。也可以使用lvdisplay或者dmsetup命令获取更详细的信息:
1 2 3 4 5 6 7 8 9 |
[root@study ~]# dmsetup status vgdemo-lvdemo-real: 0 196608 linear vgdemo-lvdemo-real: 196608 73728 linear vgdemo-lvdemosnap: 0 270336 snapshot Invalid vgdemo-lvdemosnap-cow: 0 122880 linear vgdemo-lvdemo: 0 270336 snapshot-origin centos-home: 0 10485760 linear centos-swap: 0 2097152 linear centos-root: 0 20971520 linear |
命令输出的第三行:snapshot Invalid,证明快照确实无效了,无效的快照不能再使用,必须被移除。
从快照恢复文件
因为快照可以挂载成文件系统,因此,可以像使用普通目录一样,把文件从快照直接复制到指定位置。也可以使用lvconvert
命令,配合--merge
参数,该命令会把快照中的文件恢复到源LV中。不过恢复之前必须确保源LV和快照都没有被挂载,如果有挂载,请先使用umount把它们卸下。
1 2 3 4 5 |
[root@study normal]# umount /srv/lvm [root@study normal]# umount /srv/snapshot1/ [root@study normal]# lvconvert --merge /dev/vgdemo/lvdemosnap Merging of volume vgdemo/lvdemosnap started. lvdemo: Merged: 100.00% |
一旦文件恢复完毕,快照就会自动被删除。
如果恢复文件的时候没有卸载源LV和快照,则lvconvert命令会有下面的提示信息:
1 2 3 |
[root@study normal]# lvconvert --merge /dev/vgdemo/lvdemosnap Can't merge until origin volume is closed. Merging of snapshot vgdemo/lvdemosnap will occur on next activation of vgdemo/lvdemo. |
如果出现这种情况,文件会在下次lvdemo被激活的时候被恢复。因此,我们可以这样做
- 第一步:把源LV和快照卸下
- 第二部:取消源LV的激活状态
- 第三部:重新激活源LV
具体命令如下:
1 2 3 4 |
[root@study normal]# umount /srv/lvm [root@study normal]# umount /srv/snapshot1/ [root@study normal]# lvchange -a n /dev/vgdemo/lvdemo #取消源LV激活状态 [root@study normal]# lvchange -a y /dev/vgdemo/lvdemo #重新激活源LV |
如果没有其他错误提示,表示文件恢复成功。