LVM常用命令

LVM管理指令索引

物理卷

  • pvcreate:初始化磁盘或分区以供LVM使用
  • pvdisplay:显示物理卷的属性
  • pvmove:移动物理extent
  • pvremove:删除物理卷
  • pvresize:调整LVM2使用的磁盘或分区的大小
  • pvs:报告物理卷的信息
  • pvscan:扫描物理卷的所有磁盘

卷组

  • vgcreate:创建卷组
  • vgdisplay:显示卷组属性
  • vgextend:向VG中添加PV,从而扩展VG
  • vgreduce:通过删除一个或多个PV来缩减卷组
  • vgremove:删除卷组
  • vgrename:重命名卷组
  • vgs:报告卷组的信息
  • vgscan:扫描卷组的所有磁盘

逻辑卷

  • lvcreate:在指定卷组中创建逻辑卷
  • lvdisplay:显示逻辑卷的属性
  • lvextend:扩展逻辑卷的大小
  • lvreduce:减小逻辑卷的大小
  • lvremove:删除逻辑卷
  • lvrename:重命名逻辑卷
  • lvresize:调整逻辑卷的大小
  • lvs:报告有关逻辑卷的信息
  • lvscan:扫描(所有磁盘)的逻辑卷

实施LVM存储

GPT(fdisk在CentOS7中可以支持GPT,但仅出于测试阶段)

  1. 准备磁盘设备(可以使用整块磁盘,RAID阵列,SAN磁盘,磁盘分区)

    在将物理设备用于LVM之前,使用parted,gdisk,fdisk等创建分区,以便用于LVM。应当将其类型设置为:

    • 对于GPT分区,设置为Linux LVM

    • 对于MBR分区,设置为0x8e

    • 此外,使用partprobe向内核注册新分区,或者udevadm settle

    1
    2
    3
    4
    5
    6
    7
    # 在/dev/sdb上创建一个主分区,起使位置1MB(从2048扇区开始),结束位置800MB
    parted –s /dev/sdb mkpart primary 1MB 800MB

    # 将/dev/sdb上的第一个分区设置为LVM类型
    parted –s /dev/sdb set 1 lvm on

    # 注意:如果使用mpathx设备,则创建pv时使用的设备名为mpathx1

    示例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    # parted
    # 在/dev/sdb上创建两个用于LVM的256MB的分区
    parted -s /dev/sdb mklabel gpt
    parted -s /dev/sdb mkpart primary xfs 1MB 257MB
    parted -s /dev/sdb mkpart primary xfs 258MB 514MB
    parted -s /dev/sdb set 1 lvm on
    parted -s /dev/sdb set 2 lvm on
    udevadm settle # udevadm settle作用类似于partprobe,用于向内核注册新的分区

    # 其他分区形式
    parted -s /dev/sdb mkpart primary xfs 1MB 100%
    parted -s /dev/sdb mkpart primary xfs 2048s 100%
    parted -s /dev/sdb mkpart primary xfs 0% 100%
    1
    2
    3
    4
    5
    6
    7
    8
    # fdisk
    fdisk /dev/sdx
    p #打印分区表
    g #创建空的GPT分区表
    n #创建新的分区
    t #更改磁盘ID为31(LVM)
    w #写入更改
    partprobe(立即生效-刷新分区表,向内核注册新的分区)
  2. 第二步:创建PV

    使用pvcreate将分区或整块磁盘设备标记为PV。pvcreate将物理设备若干固定大小的物理区块(PE),如果要在一条命令中标记多个设备,则使用空格分隔:

    1
    2
    3
    4
    5
    6
    7
    8
    # PV,将物理磁盘打标签,以便可用于LVM管理
    pvcreate /dev/sdb1 /dev/sdb2

    # 其他命令:
    pvscan:扫描当前系统中已经被PV标记的磁盘
    pvdisplay:PV状态
    pvs
    pvremove
  3. 第三步:创建VG

    使用vgcreate将一个或多个PV组合成一个VG。一个VG在功能上类似于一块硬盘。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # VG-使用打了PV标记的物理磁盘创建磁盘组
    vgcreate vgname1 /dev/sdb1 /dev/sdb2

    # 其他命令
    vgscan,vgdisplay,vgremove,vgs
    vgextend:在VG内添加PV磁盘 vgextend vgname /dev/sdx
    vgreduce:在VG内删除PV磁盘
    vgchange:设置VG是否active

    # 注意:VG最大容量与PE数量有关,PE最多65534个,但PE大小不固定,默认4MB
  4. 第四步:创建LV-在VG中创建逻辑卷组

    lvcreate可根据VG中的可用物理区块PE来创建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
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
       # lvcreate命令至少需要以下选项:
    -n:指定lv名称
    -L:以字节为单位的大小
    # or
    -l:以PE数量为单位的选项

    # 固定大小
    lvcreate –L 700M –n lvname1 vgname1 # 指定大小
    lvcreate -L x[MB|GB] -n lvname VGNAME

    lvcreate -l total_PE -n lvname VGNAME # 指定PE数量
    # 如果需要使用VG中的全部空间,则需要先查询VG中的PE数量,以PE数量来创建LV
    # 百分比大小
    lvcreate -l 100%FREE -n lvname VGNAME
    lvcreate -l +100%FREE -n lvname VGNAME (增加)

    # 如果需要使用VG中的全部空间,则需要先查询VG中的PE数量,以PE数量来创建LV
    lvcreate -l total_PE -n lvname VGNAME
    lvcreate -l +100%FREE -n lvname VGNAME(+表示增加)

    # 其他命令
    lvscan,lvdisplay,lvextend(扩展),lvreduce(缩小),lvremove,lvresize(扩展或缩小),lvs



    # LV设备文件名称:不同的工具可能使用不同的名称:
    `/dev/vgname/lvname`:传统lv设备文件名
    `/dev/mapper/vgname-lvname`:内核设备映射文件名

    5. 格式化

    ```sh
    # 分区格式化
    LV卷设备会同时出现在/dev/vgname目录和/dev/mapper/目录,已测试的情况是,这两个目录中的设备均可用于格式化挂载使用。

    # 注意:
    如果PV设备使用的时/dev/sdbx(即已经分区过的磁盘)那么后续无需再次针对LV进行分区,格式化后也不会在LV名字后面产生分区数字
    如果PV设备使用的时未分区设备,则需要针对LV卷进行分区,此时LV卷设备名称后将会添加分区编号

    # 查看分区
    cat /proc/partitions

    # 格式化命令
    mkfs -t ext4
    mkfs.ext4 等价于 mke2fs -t ext4
    mkfs.xfs
    # 再次格式化需要加上-f参数

    mke2fs 无法格式化为xfs,但可使用-b参数指定块大小

PV管理

删除无用PV

该操作将从分区(或磁盘)中删除PV元数据,完成后,分区或磁盘可以重新分配或格式化使用。

1
pvremove /dev/sdb1 [/dev/sdb2]

注意:如果是需要替换PV,则需要先将该PV中的数据移走。参见更换PV物理磁盘

PV扩容

所谓PV扩容就是扩磁盘或分区的大小。

当使用一整块裸磁盘创建PV并创建LV使用时,后续对这块裸磁盘扩容后,你无法在这个磁盘上创建分区,然后再去创建PV,这个时候就需要使用pvresize命令自动扩容了。

在这种情况下扩展PV后,使用该PV的VG的容量也会自动扩展,==后面只需要再手动扩容LV即可==

将PV同步物理磁盘的容量为最新大小:

1
pvresize /dev/mapper/mpathx

将PV调整为指定大小:

1
pvresize –setphysicalvolumesize 20G /dev/mapper/mpathx

以测试模式执行

1
pvresize -t /dev/mapper/mpathx

VG管理

删除无用VG

删除后,VG中的物理卷会被释放,可用于分配给系统中的现有VG或创建新的VG

1
vgremove vgname

扩展和缩小VG

使用pvcreatevgextend扩展VG,并使用vgdisplay验证结果;

  • 使用pvmove和vgreduce缩减VG;

  • 使用lvextend扩展LV;

  • 使用xfs_growfs调整XFS文件系统大小;

  • 使用resize2fs调整ext4文件系统大小。

扩展VG

通过添加额外的物理卷来为VG增加更多磁盘空间,这种做法称为扩展VG

1
2
3
4
5
6
7
8
9
10
11
# 准备物理设备并创建pv
parted –s /dev/vdb mkpart primary 1027MB 1539MB
parted –s /dev/vdb set 3 lvm on
udevadm settle
pvcreate /dev/vdb3

# 扩展vg
vgextent vgname /dev/vdb3

# 验证vg扩展
vgdisplay

缩减VG

未使用的PV可以从VG中删除,这种做法称为缩减VG。首先使用pvmove将数据从一个pv上的区块移动到vg中的其他pv上。通过这种方式还可以将新磁盘添加到现有VG,然后将数据从较旧或较慢的磁盘移动到新磁盘,并将旧磁盘从VG中删除。并且可以在LV正在使用的情况下执行这些操作。

  1. 移动物理区块PE

    使用pvmove pv_device_name将需要删除的pv中的所有物理区块PE都重新放置到vg中的其他pv上。其他pv中必须有足够的空闲区块来满足此操作。仅当VG中剩余PV上存在足够的空闲区块时,才能执行此操作。

    1
    2
    # 例如,移除/dev/vdb3
    #pvmove /dev/vdb3

    警告:在执行pvmove之前,应当备份vg中的所有lv上存储的数据,因为中途一旦意外断电,将会导致vg状态不一致,从而导致数据丢失。

  2. 缩减vg

    使用vgreduce vgname pv_device_name从vg中删除pv

    1
    2
    # 从vgname1中删除/dev/vdb3这个pv
    vgreduce vgname1 /dev/vdb3

LV管理

删除无用LV

删除lv之后,PE块会被释放,可用于vg中现有的lv或新lv

1
2
umount LV
lvremove /dev/vgname/lvname

lvresize

可以使用lvresize代替lvexted lvreduce

区别在于lvextend只能增加一个体积的大小,而lvresize可以增加或减小它的大小。
这使lvresize功能更强大但更危险。
如果不经意地减小卷的大小而没有先减小其中包含的文件系统的大小,则该文件系统很可能会受到不可挽回的损害。
对于与此处描述的情况类似的情况,lvextend建议使用此方法,因为这样就不可能出现这种类型的错误。

1
2
# 增加指定的大小
lvresize -L +500M /dev/vg/lv

扩容LV

  1. 检查VG当前可用空间

    检查Free PE/Size,如果不具有足够的空闲空间,则应当先扩展VG

    1
    vgdisplay vgname
  2. 扩展LV

    1
    2
    3
    4
    5
    6
    7
    8
    lvextend –L +300M /dev/vg01/lv01
    # 以上指令将lv01的大小增加300M,+号表示将现有大小增加300M,如果没有+号,则定义lv的最终大小。
    lvextend –l +100%free /dev/vg01/lv01
    # 以上则增加所有空闲空间

    # lvextend和lvcreate一样存在不同的方法来指定大小:
    -l:以PE数量作为参数单位,可以指定百分比
    -L:以MB,GB作为参数单位

缩小LV

==XFS文件系统不支持直接缩小,只有ext4可以==

详情参见LVM笔记文档。

更改LV状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@oradb2 ~]# lvscan
ACTIVE '/dev/vg_oracle/lv_oracle' [35.99 GiB] inherit
ACTIVE '/dev/centos_cos1/swap' [2.00 GiB] inherit
ACTIVE '/dev/centos_cos1/root' [<17.00 GiB] inherit
[root@oradb2 ~]# lvdisplay

# lvscan遇到lv状态为inactive,则:
Lvchange –ay /dev/gfsvg/gfs # 激活LV

Lvchange –an halvm_vg/ha_lv
# -an:停用逻辑组,但是必须依赖CLVM和rgmanager进程,使用群集中的故障转移策略来激活它们,一旦逻辑卷被激活,则可从/dev/halvm_vg/ha_lv访问共享卷
# Lvchange –an之后将无法使用lv,必须依赖CLVM和rgmanager进程
# LV Status变成NOT available,并且/dev/目录下也将看不到此设备,

# 若要重新手动激活lv,请使用以下指令:
Lvchange –ay vg_halvm/lv_halvm

LVM扩容基本流程

  1. 准备物理磁盘(可以使用新的分区,也可以使用新的硬盘,推荐使用新建分区),例如/dev/sdx

    1
    2
    3
    4
    5
    6
    7
    8
    9
    parted & gdisk & fdisk  # 新建一个gpt或mbr分区
    # 注:新建分区时需要将分区类型指定为LVM

    # GPT分区
    parted /dev/sdx mklabel gpt # 如果是使用现有磁盘中的剩余空间,则无需该步骤
    parted /dev/sdx mkpart parmary 2048s 100% # 创建一个主分区,然后使用所有空间
    parted /dev/sdx set 1 lvm on # 将/dev/sdx的第一个分区设置为LVM类型或在交互中使用toggle 1 lvm #LVM磁盘ID为31)
    quit
    # mbr分区类型方法类似
  2. 创建PV

    1
    2
    pvcreate /dev/sdx1
    pvdisplay
  3. 扩展VG,即将新的PV添加到现有VG

    1
    2
    vgextend vgname1 /dev/sdx1
    vgdisplay
  4. 扩展LV

    1
    2
    3
    4
    5
    6
    7
    8
    # 向该lv中添加指定大小的容量,如果不使用“+”则表示将该LV设置为指定大小。
    lvextent -L +x{mb|gb|tb} /dev/vg01/lv01(lvname)
    # 向该lv中添加全部可用的LE数量
    lvextent -l +100%free /dev/vg01/lv01(lvname)

    -L|--size [+]Size[m|UNIT] LV
    [ -l|--extents [+]Number[PERCENT] ]
    [ -r|--resizefs ] //此后无再次针对文件系统执行resize
  5. 扩展文件系统

    1
    2
    3
    4
    5
    # xfs:
    xfs_growfs /date //注意,指定的是挂载点

    # ext4:
    resize2fs /dev/vg01/lv01 //指定的是lv的设备文件名

关于文件系统扩容

xfs

使用xfs_growfs mountpoint扩展文件系统以占用已扩展的LV。使用xfs_growfs时,==必须挂载目标文件系统==,在调整文件系统大小时,可以继续使用该文件系统。

我们知道,文件系统是在最初格式化的时候建立的inode/block/superblock等信息,要更改这部分信息很难。但因为文件系统格式化的时候是创建的多个block group,因此我们可以通过在文件系统元数据中增加block group的方式来增减文件系统的大小,对于xfs文件系统则是使用xfs_growfs

因此,严格来说,扩展文件系统并非没有进行【格式化】,而是格式化的位置是新增的部分,设备前面已经存在的文件系统则没有变化。

1
2
xfs_info /mount_point # 对比前后agcount和blocks的变化
xfs_groufs /mount_point

对比两次xfs_info的结果:

  1. 整个block group (agcount)的数量增加1个,增加的这个block group就是记录新的设备容量之文件系统所在
  2. block数量增加

警告:对于XFS文件系统,没有缩小文件系统容量的设计。即只能扩展不能缩小。

说明:在lvextend后可能会经常忘记执行xfs_growfs,为此可在lvextent中包含-r选项fsadm(8)在扩展lv后自动调整文件系统大小,这种方式可以用于多种不同的文件系统。

ext4

原理和xfs文件系统相同,但使用的工具是resize2fs

1
2
3
4
5
6
7
dumpe2fs /dev/vg/lv  # 查看文件系统元数据

resize2fs [-f] [磁盘设备名称] [size]
# -f:强制resize
# [device]:设备名称,比如/dev/vg/lv
# [size]:可选,单位M,G。如果没有指定,则默认使用整个分区的容量
resize2fs /dev/vg/lv

注意:xfs_growfsresize2fs之间的主要区别是为识别文件系统而传递的参数,xfs_growfs采用挂载点,resize2fs采用逻辑卷名称

swap

格式化为swaplv也可以进行扩展,但其过程和ext4xfs都有所不同。

格式化为swaplv必须脱机才能进行扩展。

  1. 验证vg具有可用空间

  2. 停用swap

    1
    swapoff –v /dev/vgname/lvname

    注意:在停用swap之前必须有足够的可用RAM或其他交换空间,否则停用将会失败。

  3. 增加大小

    1
    lvextent –l +10M /dev/vgname/lvname
  4. 重新格式化

    1
    mkswap /dev/vgname/lvname # 重新格式化为swap
  5. 重新激活swap

    1
    swapon –va /dev/vgname/lvname (激活swap)

删除PV,VG,LV

场景1:更换物理磁盘,保持LV

比如,你可能想给LVM更换更大,更快的磁盘,但LV配置不动。仅从LVM中删除需要更换的磁盘。

  1. 确认需要更换的PV(磁盘)没有正在被使用:

    1
    2
    pvdisplay PVName  # 查看该磁盘已分配出去的PE数量是否为0
    pvdisplay -m PVName # 还可以查看一些PE和LE之间的映射关系
  2. 防止再从该磁盘中继续分配PE

    1
    pvchange -x n PVName
  3. 如果该磁盘已经正在使用,则需要将其上面的数据移动到其他PV中。

    1
    2
    pvmove PVName
    # 注意:这里指定的是你需要移除的PVName,你不能指定将数据具体移动到哪个PV中。
  4. 从VG中移除PV

    1
    vgreduce VGName PVName
  5. 删除PV

    1
    pvremove PVName

场景2:删除无用的LV

1
lvremove lv_name

场景3:删除无用的VG

1
vgremove vg_name

查看LV实际空间占用

1
2
3
4
5
[root@docker1 ~]# lvs --segments -o +pe_ranges vg_docker
LV VG Attr #Str Type SSize PE Ranges
lv_docker vg_docker -wi-ao---- 1 linear <200.00g /dev/sdb1:0-51198
lv_docker vg_docker -wi-ao---- 1 linear <100.00g /dev/sdc1:0-25598
[root@docker1 ~]#

PE Ranges:就是LV实际从磁盘中拿走的空间,跟创建LV时为其指定的大小一致。而对于精简卷来说,其大小跟PE Ranges并不一致。

LVM状态管理

关于pvs,lvs和vgs中Attr各个字节对应的含义,最准确快速查找的方法是:

man 对应的命令,然后搜索pv_attrlv _attr 或者vg _attr ,就有当前版本最准确的解释了

PV状态

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
[root@docker1 ~]# pvs
PV VG Fmt Attr PSize PFree
/dev/sda2 centos lvm2 a-- <49.00g 4.00m
/dev/sdb1 vg_docker lvm2 a-- <200.00g 0
/dev/sdc1 vg_docker lvm2 a-- <100.00g 0
[root@docker1 ~]# pvdisplay
--- Physical volume ---
PV Name /dev/sdb1
VG Name vg_docker
PV Size <200.00 GiB / not usable 2.00 MiB
Allocatable yes (but full)
PE Size 4.00 MiB
Total PE 51199
Free PE 0
Allocated PE 51199
PV UUID RWBRu3-6cPj-3RUm-huWv-JaLH-YMSf-i02wkN

--- Physical volume ---
PV Name /dev/sdc1
VG Name vg_docker
PV Size <100.00 GiB / not usable 3.00 MiB
Allocatable yes (but full)
PE Size 4.00 MiB
Total PE 25599
Free PE 0
Allocated PE 25599
PV UUID mPK1Ys-dkiw-k2Y4-Ihyq-dNBO-PDE5-LCBLov

--- Physical volume ---
PV Name /dev/sda2
VG Name centos
PV Size <49.00 GiB / not usable 3.00 MiB
Allocatable yes
PE Size 4.00 MiB
Total PE 12543
Free PE 1
Allocated PE 12542
PV UUID WaTTyv-tPCL-5n52-MSVz-UPZ7-UCaJ-1c1tPs

[root@docker1 ~]#

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
[root@docker1 ~]# vgs
VG #PV #LV #SN Attr VSize VFree
centos 1 2 0 wz--n- <49.00g 4.00m
vg_docker 2 1 0 wz--n- 299.99g 0
[root@docker1 ~]# vgdisplay
--- Volume group ---
VG Name vg_docker
System ID
Format lvm2
Metadata Areas 2
Metadata Sequence No 4
VG Access read/write
VG Status resizable
MAX LV 0
Cur LV 1
Open LV 1
Max PV 0
Cur PV 2
Act PV 2
VG Size 299.99 GiB
PE Size 4.00 MiB
Total PE 76798
Alloc PE / Size 76798 / 299.99 GiB
Free PE / Size 0 / 0
VG UUID mrirZR-Emhw-6FTn-Qv2F-D4VS-nVKh-YkARz2

--- Volume group ---
VG Name centos
System ID
Format lvm2
Metadata Areas 1
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 1
Act PV 1
VG Size <49.00 GiB
PE Size 4.00 MiB
Total PE 12543
Alloc PE / Size 12542 / 48.99 GiB
Free PE / Size 1 / 4.00 MiB
VG UUID 09YOZW-EQwI-8enY-Bwp8-776I-q6VL-t5KhSG

[root@docker1 ~]#

VG Size:是VG可用于LV的总大小

Total PE:PE总数量

LV状态

有些工具可能将设备名报告为/dev/mapper/vgname-lvname;这两个名称都代表同一个lv。

Current LE:此LV使用的逻辑区块数量,LE通常1对1映射到PE。

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
[root@docker1 ~]# lvs
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
root centos -wi-ao---- <45.12g
swap centos -wi-ao---- <3.88g
lv_docker vg_docker -wi-ao---- 299.99g
[root@docker1 ~]# lvdisplay
--- Logical volume ---
LV Path /dev/vg_docker/lv_docker
LV Name lv_docker
VG Name vg_docker
LV UUID 0i9VLY-9Qfs-ZB0D-EKyO-otOc-IC38-wBliUp
LV Write Access read/write
LV Creation host, time docker1, 2022-09-04 20:55:08 +0800
LV Status available
# open 1
LV Size 299.99 GiB
Current LE 76798
Segments 2
Allocation inherit
Read ahead sectors auto
- currently set to 8192
Block device 253:2

--- Logical volume ---
LV Path /dev/centos/swap
LV Name swap
VG Name centos
LV UUID G3ieJX-u0fo-Gx2L-WfmK-I5A2-EVT7-eiiCWA
LV Write Access read/write
LV Creation host, time localhost, 2022-09-04 20:09:46 +0800
LV Status available
# open 2
LV Size <3.88 GiB
Current LE 992
Segments 1
Allocation inherit
Read ahead sectors auto
- currently set to 8192
Block device 253:1

--- Logical volume ---
LV Path /dev/centos/root
LV Name root
VG Name centos
LV UUID 1LrMfa-pAbu-YACD-ecHv-5dEv-0EB2-vZeIIr
LV Write Access read/write
LV Creation host, time localhost, 2022-09-04 20:09:46 +0800
LV Status available
# open 1
LV Size <45.12 GiB
Current LE 11550
Segments 1
Allocation inherit
Read ahead sectors auto
- currently set to 8192
Block device 253:0

[root@docker1 ~]#