LVM2 简介

简介

LVM2(Logical Volume Manager,Version:2)是LVM的第二个版本。LVM是一种Linux核心所提供的逻辑卷管理(Logical volume management)功能,它在硬盘的硬盘分区之上,又创建一个逻辑层,以方便对系统分区进行管理。

目的

使系统分区更加方便,灵活,可以在不丢失数据的情况下对系统分区进行扩容及收缩。(但因为数据由软件层控制,所以一旦丢失就难以找回,所以业界对于此分区方式一直存在争议。)

概念

先来看一张概念图(来自wiki):

LVM

PE:Physical Extent,组成LVM的最小单位,大小可由指定VG指定。

PV:Physical Volume,组成VG的物理卷单位,从物理分区进行创建。

VG:Volume Group,由PV组成的卷组,可通过PV的增加和缩减来改变容量,是创建逻辑分区的基石。

LV:Logical Volume,我们的主角逻辑分区,在VG上创建,在一定条件下可自由改变容量。

实现

PV管理工具:

1
2
3
4
5
6
7
8
9
10
11
12
13
[hzz@magedu ~]$ pv
pvchange pvcreate pvmove pvresize pvscan
pvck pvdisplay pvremove pvs
[hzz@magedu ~]$ pv

# 查看PV

pvs:简要PV信息显示
pvdisplay:显示PV的详细信息

# 创建PV

pvcreate /dev/DEVICE(分区类型必须为:8e)

VG管理工具:

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
[hzz@magedu ~]$ vg
vgcfgbackup vgconvert vgextend vgmknodes vgs
vgcfgrestore vgcreate vgimport vgreduce vgscan
vgchange vgdisplay vgimportclone vgremove vgsplit
vgck vgexport vgmerge vgrename
[hzz@magedu ~]$ vg

# 查看VG

vgs:简要VG信息显示
vgdisplay:显示VG的详细信息

# 创建VG

vgcreate [-s [kKmMgGtTpPeE]] VolumeGroupName PhysicalDevicePath [PhysicalDevicePath...]

-s 为指定PE大小。

# 扩展VG

vgextend VolumeGroupName PhysicalDevicePath [PhysicalDevicePath...]

# 缩减VG

vgreduce VolumeGroupName PhysicalDevicePath [PhysicalDevicePath...](减掉PV前要先使用pvmove转移数据)

LV管理工具:

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
[hzz@magedu ~]$ lv
lvchange lvextend lvmconfig lvmpolld lvremove lvscan
lvconvert lvm lvmdiskscan lvmsadc lvrename
lvcreate lvmchange lvmdump lvmsar lvresize
lvdisplay lvmconf lvmetad lvreduce lvs
[hzz@magedu ~]$ lv

# 查看LV

lvs:简要LV信息显示
lvdisplay:显示LV的详细信息

# 创建LV

lvcreate -L [mMgGtT] -n NAME VolumeGroup

# 扩展LV

lvextend -L [+][mMgGtT] /dev/VG_NAME/LV_NAME

# 缩减LV

lvreduce -L [-][mMgGtT] /dev/VG_NAME/LV_NAME

# 注意

由于LVM的最小单位是PE,所以LV的大小受PE的大小限制,可能无法完全精确。

注意:

VG和LV的缩减必须遵循规律进行。比如VG缩减前,必须先用pvmove进行pv的数据转移,才可以移除pv;LV缩减前,必须先umount分区,待缩减成功后再mount分区。PV,VG,LV相当于一个金字塔形结构,上层扩充和缩减的容量,必须以下层的已使用量为参考。

示例

使用三块5G的磁盘创建一个PE大小为4M的VG,并创建5G的LV用于挂载到/tmp/lvm-test目录。

创建分区:

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
[hzz@magedu ~]$ sudo fdisk /dev/sdb

The device presents a logical sector size that is smaller than
the physical sector size. Aligning to a physical sector (or optimal
I/O) size boundary is recommended, or performance may be impacted.
欢迎使用 fdisk (util-linux 2.23.2)。

更改将停留在内存中,直到您决定将更改写入磁盘。
使用写入命令前请三思。


命令(输入 m 获取帮助):n
Partition type:
p primary (0 primary, 0 extended, 4 free)
e extended
Select (default p):
Using default response p
分区号 (1-4,默认 1):
起始 扇区 (2048-10485759,默认为 2048):
将使用默认值 2048
Last 扇区, +扇区 or +size{K,M,G} (2048-10485759,默认为 10485759):
将使用默认值 10485759
分区 1 已设置为 Linux 类型,大小设为 5 GiB

命令(输入 m 获取帮助):t
已选择分区 1
Hex 代码(输入 L 列出所有代码):8e
已将分区“Linux”的类型更改为“Linux LVM”

命令(输入 m 获取帮助):w
The partition table has been altered!

Calling ioctl() to re-read partition table.
正在同步磁盘。
[hzz@magedu ~]$ sudo fdisk /dev/sdc

The device presents a logical sector size that is smaller than
the physical sector size. Aligning to a physical sector (or optimal
I/O) size boundary is recommended, or performance may be impacted.
欢迎使用 fdisk (util-linux 2.23.2)。

更改将停留在内存中,直到您决定将更改写入磁盘。
使用写入命令前请三思。


命令(输入 m 获取帮助):n
Partition type:
p primary (0 primary, 0 extended, 4 free)
e extended
Select (default p):
Using default response p
分区号 (1-4,默认 1):
起始 扇区 (2048-10485759,默认为 2048):
将使用默认值 2048
Last 扇区, +扇区 or +size{K,M,G} (2048-10485759,默认为 10485759):
将使用默认值 10485759
分区 1 已设置为 Linux 类型,大小设为 5 GiB

命令(输入 m 获取帮助):t
已选择分区 1
Hex 代码(输入 L 列出所有代码):8e
已将分区“Linux”的类型更改为“Linux LVM”

命令(输入 m 获取帮助):w
The partition table has been altered!

Calling ioctl() to re-read partition table.
正在同步磁盘。
[hzz@magedu ~]$ sudo fdisk /dev/sdd

The device presents a logical sector size that is smaller than
the physical sector size. Aligning to a physical sector (or optimal
I/O) size boundary is recommended, or performance may be impacted.
欢迎使用 fdisk (util-linux 2.23.2)。

更改将停留在内存中,直到您决定将更改写入磁盘。
使用写入命令前请三思。


命令(输入 m 获取帮助):n
Partition type:
p primary (0 primary, 0 extended, 4 free)
e extended
Select (default p):
Using default response p
分区号 (1-4,默认 1):
起始 扇区 (2048-10485759,默认为 2048):
将使用默认值 2048
Last 扇区, +扇区 or +size{K,M,G} (2048-10485759,默认为 10485759):
将使用默认值 10485759
分区 1 已设置为 Linux 类型,大小设为 5 GiB

命令(输入 m 获取帮助):t
已选择分区 1
Hex 代码(输入 L 列出所有代码):8e
已将分区“Linux”的类型更改为“Linux LVM”

命令(输入 m 获取帮助):w
The partition table has been altered!

Calling ioctl() to re-read partition table.
正在同步磁盘。
[hzz@magedu ~]$

创建PV:

此处要注意,如果磁盘曾经做过RAID,需要复用的话,在删除RAID后需要清理超级块,否则会出现“Device /dev/sdb1 not found (or ignored by filtering).”报错无法加载。(我就被坑了一晚上。)

1
sudo mdadm --misc --zero-superblock /dev/sdb

删除软RAID过程详见《Linux RAID简介》

如果是使用当前磁盘的其他分区创建,则直接pvcreate /dev/sda3就可以了,但是如果是跨磁盘创建,执行pvcreate的时候也有可能会报错“Device /dev/sdb1 not found (or ignored by filtering).”。此时要经过以下预处理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 查看sdb设备号

[hzz@magedu ~]$ cat /proc/partitions|grep sdb1|awk '{print $1}'
8
[hzz@magedu ~]$

# 查看这个设备号对应的驱动类型

[hzz@magedu ~]$ cat /proc/devices|grep -w 8
8 sd
[hzz@magedu ~]$

# 将设备驱动号和设备类型加入到/etc/lvm/lvm.conf中

[hzz@magedu ~]$ sudo su -
[root@magedu ~]# echo 'types = [ "sd", 8 ]' >> /etc/lvm/lvm.conf # 这里只是快速添加,建议打开文件添加到具体位置
[root@magedu ~]# exit
登出
[hzz@magedu ~]$

经过以上处理后,就能愉快地创建PV了。

1
2
3
4
5
6
7
8
9
10
11
12
13
[hzz@magedu ~]$ sudo pvcreate /dev/sdb1
Physical volume "/dev/sdb1" successfully created.
[hzz@magedu ~]$ sudo pvcreate /dev/sdc1
Physical volume "/dev/sdc1" successfully created.
[hzz@magedu ~]$ sudo pvcreate /dev/sdd1
Physical volume "/dev/sdd1" successfully created.
[hzz@magedu ~]$ sudo pvs
PV VG Fmt Attr PSize PFree
/dev/sda2 cl lvm2 a-- 63.00g 4.00m
/dev/sdb1 lvm2 --- 5.00g 5.00g
/dev/sdc1 lvm2 --- 5.00g 5.00g
/dev/sdd1 lvm2 --- 5.00g 5.00g
[hzz@magedu ~]$

创建VG:

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
[hzz@magedu ~]$ sudo vgcreate -s 4M myvg /dev/sdb1 /dev/sdc1 /dev/sdd1
Volume group "myvg" successfully created
[hzz@magedu ~]$ sudo vgdisplay myvg
--- Volume group ---
VG Name myvg
System ID
Format lvm2
Metadata Areas 3
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 3
Act PV 3
VG Size 14.99 GiB
PE Size 4.00 MiB
Total PE 3837
Alloc PE / Size 0 / 0
Free PE / Size 3837 / 14.99 GiB
VG UUID 9khJeI-oHyN-9UK6-tgmR-k4QI-rTl7-gBxcx0

[hzz@magedu ~]$

创建LV

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[hzz@magedu ~]$ sudo lvcreate -L 5G -n mylv myvg
Logical volume "mylv" created.
[hzz@magedu ~]$ sudo lvdisplay /dev/myvg/mylv
--- Logical volume ---
LV Path /dev/myvg/mylv
LV Name mylv
VG Name myvg
LV UUID 1KVUhb-pNIy-Mrbh-g1Yf-5mVS-YtL5-tu98yj
LV Write Access read/write
LV Creation host, time magedu, 2017-04-28 11:00:18 +0800
LV Status available
# open 0
LV Size 5.00 GiB
Current LE 1280
Segments 2
Allocation inherit
Read ahead sectors auto
- currently set to 8192
Block device 253:3

[hzz@magedu ~]$

格式化LV并挂载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[hzz@magedu ~]$ sudo mkfs.xfs /dev/myvg/mylv
meta-data=/dev/myvg/mylv isize=512 agcount=4, agsize=327680 blks
= sectsz=4096 attr=2, projid32bit=1
= crc=1 finobt=0, sparse=0
data = bsize=4096 blocks=1310720, 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=4096 sunit=1 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0
[hzz@magedu ~]$ sudo mkdir -p /tmp/lvm-test
[hzz@magedu ~]$ sudo mount /dev/myvg/mylv /tmp/lvm-test
[hzz@magedu ~]$ df -h|grep lvm-test
/dev/mapper/myvg-mylv 5.0G 33M 5.0G 1% /tmp/lvm-test
[hzz@magedu ~]$

创建快照

LVM可以给系统创建一个快照,由于使用了写入时复制(copy-on-write) 策略,相比传统的备份更有效率。 初始的快照只有关联到实际数据的inode的实体链接(hark-link)而已。只要实际的数据没有改变,快照就只会包含指向数据的inode的指针,而非数据本身。一旦你更改了快照对应的文件或目录,LVM就会自动拷贝相应的数据,包括快照所对应的旧数据的拷贝和你当前系统所对应的新数据的拷贝。这样的话,只要你修改的数据(包括原始的和快照的)不超过2G,你就可以只使用2G的空间对一个有35G数据的系统创建快照。

通俗点来说,就是新建一个逻辑分区(snap01),并创建指定逻辑分区(vg0-pv)所有文件的硬连接。当LVM检测到vg0-pv上有文件变化时,便拷贝vg0-pv上变化文件的旧文件到snap01,确保snap01上所指向的文件,都是创建snap01时的版本。

因为snap01上只保留了vg0-pv上被更改的文件,其他的都是硬连接,所以其空间可设置成比vg0-pv小。具体制定标准要预估vg0-pv上文件变化的数量决定,在条件允许的情况下建议创建成和vg0-pv一样的大小。

注意:snap01vg0-pv必须在同一个VG中,确保vg0-pv所在VG有足够的空间。

创建快照操作:

1
lvcreate -L [mMgGtT] -p r -s -n snapshot_lv_name original_lv_name

示例:创建/dev/myvg/mylv的快照,要求大小为5G,挂载为/tmp/lvm-test-snap。

1
2
3
4
5
6
[hzz@magedu ~]$ sudo lvcreate -L 5G -p r -s -n mylv-snap /dev/myvg/mylv
Using default stripesize 64.00 KiB.
Logical volume "mylv-snap" created.
[hzz@magedu ~]$ sudo mkdir -p /tmp/lvm-test-snap
[hzz@magedu ~]$ sudo mount -r /dev/myvg/mylv-snap /tmp/lvm-test-snap
[hzz@magedu ~]$

更多参考

就这样,LVM2介绍完了,更多关于LVM的使用,可参考Arch Linux文档上的一篇文章:LVM