LVM逻辑卷管理

admin 2022年09月03日 621次浏览

LVM(Logical Volume Manager,逻辑卷管理器) 的重点在于可以弹性的调整文件系统的容量,而并非在于性能与数据安全上面。LVM 可以整合多个物理分区,让这些分区看起来就像是一个磁盘一样,而且,未来还可以在这个 LVM 管理的磁盘中新增或删除其他物理分区,如此一来,整个磁盘空间的使用上,就可以弹性分配

1、LVM简介

LVM 的作法是将几个物理分区或硬盘通过软件组合成为一块看起来是独立的大磁盘 (VG) ,然后将这块大磁盘再经过分区成为可使用分区 (LV),最终就能够挂载使用了

1.1、物理卷(Physical Volume,PV )

我们实际的分区或硬盘需要调整系统标识符 (system ID)成为 8e(LVM 的标识符),然后再经过 pvcreate 的命令将其转成 LVM 最底层的物理卷 (PV) ,之后才能够将这些 PV 加以利用。调整 system ID 的方是就是通过 gdisk 实现

1.2、卷组(Volume Group, VG)

所谓的 LVM 大磁盘就是将许多 PV 整合成这个 VG,所以 VG 就是 LVM 组合起来的大磁盘,VG 支持的最大容量和PE 以及 LVM 的格式版本有关,默认情况下,使用 32 位的 Linux 系统时,基本上 LV 最大仅能支持到 65534 个 PE,若使用默认的 PE 为 4MB 的情况下, 则最大容量仅能达到约 256GB,不过,这个问题在 64 位的 Linux 系统上面已经不存在了,LV 几乎没有啥容量限制了

1.3、物理扩展快(Physical Extent, PE)

LVM 默认使用 4MB 的 PE 数据块,而 LVM 的 LV 在 32 位系统上最多仅能含有 65534 个 PE(LVM1 的格式),因此默认的 LVM 的 LV 会有 4M * 65534 /(1024M / G)= 256G

PE 是整个 LVM 最小的储存数据单位,也就是说,其实我们的文件数据都是借由写入 PE 来完成的。PE 就有点像文件系统里面的 block 大小,因此调整 PE 会影响到 LVM 的最大容量,不过,在 CentOS 6.x 以后,由于直接使用 LVM2 的各项格式功能,以及系统转为 64 位,因此这个限制已经不存在了

1.4、逻辑卷(Logical Volume, LV)

最终的 VG 还会被切成 LV,这个 LV 就是最后可以被格式化使用的类似分区的东西,PE 是整个 LVM 的最小储存单位,LV 的大小与在此 LV 内的 PE 总数有关,为了方便用户利用 LVM 来管理其系统,LV 的设备文件名通常为 /dev/vgname/lvname 的样式

前面说使用 LVM 可以弹性的管理文件系统空间,其实就是通过调整 LV 中的 PE 数量实现的,要扩大容量,就加入 PE,要缩小文件系统空间就减少 PE 数量

1.5、LVM操作流程简介

通过 PV,VG,LV 的规划之后,再利用 mkfs 就可以将 LV 格式化成为可以利用的文件系统了,这个文件系统的容量在未来还能够进行扩充或减少,而且里面的数据还不会被影响,整个操作流程如下:

1.6、数据写入LV的方式

  • 线性模式 (linear):假如将 /dev/sda1, /dev/sdb1 这两块硬盘加入到 VG 当中,并且整个 VG 只有一个 LV 时,那么所谓的线性模式就是:当 /dev/sda1 的容量用完之后,/dev/sdb1 的硬盘才会被使用,建议使用该模式

  • 交错模式 (triped):就是将数据拆成两部分,分别写入 /dev/sda1 与 /dev/sdb1(与RAID0相似,如此,一份数据用两块硬盘来写入,理论上,读写的性能相对较好,但是如果有任何一块硬盘损坏,那么整个数据也就不保了

LVM 最主要的用处是在实现一个可以弹性调整容量的文件系统上,而不是在建立一个性能为主的磁盘上,所以,我们应该利用的是 LVM 可以弹性管理整个分区大小的用途上,而不是着眼在性能上的,因此,LVM 默认的读写模式就是线性模式

2、LVM实践操作

2.1、物理硬盘操作

  • 物理硬盘分区

    此处以操作一块硬盘为例,其他硬盘操作相同

    [root@localhost ~]# gdisk /dev/sdb
    GPT fdisk (gdisk) version 0.8.10
    Command (? for help): n
    Partition number (1-128, default 1): 
    First sector (34-20971486, default = 2048) or {+-}size{KMGTP}: 
    Last sector (2048-20971486, default = 20971486) or {+-}size{KMGTP}: 
    Current type is 'Linux filesystem'
    # 此处code填8e00
    Hex code or GUID (L to show codes, Enter = 8300): 8e00
    Changed type of partition to 'Linux LVM'
    Command (? for help): w
    Do you want to proceed? (Y/N): y
    OK; writing new GUID partition table (GPT) to /dev/sdb.
    The operation has completed successfully.
    
  • 查看硬盘分区格式

    [root@localhost ~]#  gdisk -l /dev/sdb
    Number  Start (sector)    End (sector)  Size       Code  Name
       1            2048        20971486   10.0 GiB    8E00  Linux LVM
    [root@localhost ~]#  gdisk -l /dev/sdc
    Number  Start (sector)    End (sector)  Size       Code  Name
       1            2048        20971486   10.0 GiB    8E00  Linux LVM
    [root@localhost ~]#  gdisk -l /dev/sdd
    Number  Start (sector)    End (sector)  Size       Code  Name
       1            2048        20971486   10.0 GiB    8E00  Linux LVM
    

2.2、PV操作

2.2.1、相关命令

  • pvcreate :将物理分区建立成为 PV
  • pvscan :查看目前系统里面所有具有 PV 的磁盘
  • pvdisplay :查看目前系统上 PV 的状态
  • pvremove :将 PV 属性删除

2.2.2、操作示例

  • 查看系统上有没有PV

    [root@localhost ~]# pvscan
      PV /dev/sda2   VG centos          lvm2 [<39.00 GiB / 4.00 MiB free]
      Total: 1 [<39.00 GiB] / in use: 1 [<39.00 GiB] / in no VG: 0 [0   ]
    
  • 创建PV

    [root@localhost ~]# pvcreate /dev/sd{b,c,d}1
      Physical volume "/dev/sdb1" successfully created.
      Physical volume "/dev/sdc1" successfully created.
      Physical volume "/dev/sdd1" successfully created.
      
    # 再次查看PV
    [root@localhost ~]# pvscan
      PV /dev/sda2   VG centos          lvm2 [<39.00 GiB / 4.00 MiB free]
      PV /dev/sdb1                      lvm2 [<10.00 GiB]
      PV /dev/sdc1                      lvm2 [<10.00 GiB]
      PV /dev/sdd1                      lvm2 [<10.00 GiB]
      ## 此处显示:整体PV的量 / 已使用VG的PV量 / 剩余的PV量
      Total: 4 [68.99 GiB] / in use: 1 [<39.00 GiB] / in no VG: 3 [<30.00 GiB]
    
  • 显示详细PV信息

    [root@localhost ~]# pvdisplay /dev/sdb1
      "/dev/sdb1" is a new physical volume of "<10.00 GiB"
      --- NEW Physical volume ---
      PV Name               /dev/sdb1	# 实际的分区设备名称
      VG Name               			# 没有分配,所以空白
      PV Size               <10.00 GiB	# 该PV容量
      Allocatable           NO			# 是否被分配
      PE Size               0   		# 此PV内PE的大小
      Total PE              0			# 一共有多少个PE
      Free PE               0			# 未被LV使用的PE数量
      Allocated PE          0			# 可以被分配的PE数量
      PV UUID               bHfJ2R-fVr6-c8WH-WLBz-Mxhl-2KBg-nRSetM
    ## 说明:由于PE是在建立VG时才分配的参数,因此在这里看到的PV里PE都是0,而且也没有分配的PE
    

2.3、VG操作

2.3.1、相关命令

  • vgcreate :创建VG

  • vgscan :查看系统上是否存在 VG

  • vgdisplay :显示目前系统上的 VG 状态

  • vgextend :在 VG 内增加 PV

  • vgreduce :在 VG 内删除 PV

  • vgchange :设置 VG 是否启动 (active)

  • vgremove :删除一个 VG

2.3.2、操作示例

  • 创建VG

    # 语法
    vgcreate [-s N[mgt]] VG 名称 PV 名称
    ## -s参数指定PE的大小,单位可以是:m、g、t(不区分大小写)
    
    # 将 /dev/sdb1、/dev/scd1 建立成为一个VG,且指定PE为16MB
    [root@localhost ~]# vgcreate -s 16m VG_1 /dev/sd{b,c}1
      Volume group "VG_1" successfully created
    
  • 查看系统现有VG

    # 查看现有VG信息
    [root@localhost ~]# vgscan
      Reading volume groups from cache.
      ## 刚才创建的
      Found volume group "VG_1" using metadata type lvm2
      ## 系统原有的
      Found volume group "centos" using metadata type lvm2
      
    # 查看PV信息
    ## 两个PV已经加入VG_1,/dev/sdd1未加入
    [root@localhost ~]# pvscan
      PV /dev/sda2   VG centos          lvm2 [<39.00 GiB / 4.00 MiB free]
      PV /dev/sdb1   VG VG_1            lvm2 [9.98 GiB / 9.98 GiB free]
      PV /dev/sdc1   VG VG_1            lvm2 [9.98 GiB / 9.98 GiB free]
      PV /dev/sdd1                      lvm2 [<10.00 GiB]
      Total: 4 [68.96 GiB] / in use: 3 [58.96 GiB] / in no VG: 1 [<10.00 GiB]
    
    # 查看VG详细信息
    [root@localhost ~]# vgdisplay VG_1 
      --- Volume group ---
      VG Name               VG_1
      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的总大小
      VG Size               <19.97 GiB
      ## 当前VG内每个PE的大小
      PE Size               16.00 MiB
      ## 当前VG内PE的总数量
      Total PE              1278
      Alloc PE / Size       0 / 0  
      ## 可分配给LV的PE数量/总空间大小
      Free  PE / Size       1278 / <19.97 GiB
      VG UUID               R5k1VZ-sw2K-DSbR-nOfO-9F8F-eXq2-ROTLeN
    
  • 扩展VG

    # 扩容VG
    [root@localhost ~]# vgextend VG_1 /dev/sdd1 
      Volume group "VG_1" successfully extended
      
    # 查看VG详细信息
    [root@localhost ~]# vgdisplay VG_1 
      --- Volume group ---
      VG Name               VG_1
      VG Size               29.95 GiB
      PE Size               16.00 MiB
      Total PE              1917
      Alloc PE / Size       0 / 0   
      Free  PE / Size       1917 / 29.95 GiB
      VG UUID               R5k1VZ-sw2K-DSbR-nOfO-9F8F-eXq2-ROTLeN
      ## VG的总空间大小与PE数量都增加了
    

2.4、LV操作

2.4.1、相关命令

  • lvcreate:创建 LV

  • lvscan :查看当前系统上的 LV

  • lvdisplay :显示当前系统上 LV 的状态

  • lvextend :LV 增加容量

  • lvreduce :LV 缩小容量

  • lvremove :删除 LV

  • lvresize :对 LV 进行容量大小的调整

2.4.2、操作示例

  • 创建LV

    # 语法
    lvcreate [-L N[mgt]] [-n LV名称] VG名称
    选项与参数:
    -L :后面接容量,单位可以是:M、G、T等(容量必须是PE大小的倍数,若不相符,系统会自动计算最相近的容量) 
    -n :LV名称
    
    # 创建一个2GB的LV
    [root@localhost ~]# lvcreate -L 2G -n LV_1 VG_1 
      Logical volume "LV_1" created.
    
  • 查看现有LV

    # 查看现有LV
    [root@localhost ~]# lvscan 
      # 刚创建的GB的LV
      ACTIVE            '/dev/VG_1/LV_1' [2.00 GiB] inherit
      ACTIVE            '/dev/centos/swap' [2.00 GiB] inherit
      ACTIVE            '/dev/centos/root' [36.99 GiB] inherit
      
    # 查看LV状态
    [root@localhost ~]# lvdisplay /dev/VG_1/LV_1 
      --- Logical volume ---
      LV Path                /dev/VG_1/LV_1
      LV Name                LV_1
      VG Name                VG_1
      LV UUID                09LkZb-H0H4-z13N-k8ee-G8hS-Ucmj-oBa51d
      LV Write Access        read/write
      LV Creation host, time localhost.localdomain, 2022-09-02 21:08:36 +0800
      LV Status              available
      # open                 0
      ## 当前LV大小
      LV Size                2.00 GiB
      Current LE             128
      Segments               1
      Allocation             inherit
      Read ahead sectors     auto
      - currently set to     8192
      Block device           253:2
    

2.5、LV的使用

[root@localhost ~]# mkfs.xfs /dev/VG_1/LV_1
[root@localhost ~]# mount /dev/VG_1/LV_1 /mnt/
[root@localhost ~]# df -lh
文件系统                 容量  已用  可用 已用% 挂载点
/dev/mapper/VG_1-LV_1    2.0G   33M  2.0G    2% /mnt

3、LV扩容

3.1、LV扩容的流程

  • VG 阶段需要有剩余的容量:因为需要扩容文件系统,所以需要对 LV 扩容,但是如果没有多的 VG 容量, 那么 LV 与文件系统就无法扩容

  • LV 阶段产生更多的可用容量:如果 VG 的剩余容量足够,此时就可以利用 lvresize 命令将剩余容量加入到所需扩容的 LV 中

  • 文件系统阶段的扩容:我们最终目的是对 LV 这个设备内的文件系统进行扩容

由于整个文件系统在格式化的时候就建立了inode、block、superblock 等信息,这些信息是无法改变的,不过因为文件系统格式化的时候创建的是多个区块组,因此我们可以通过在文件系统当中增加区块组的方式来扩容文件系统的容量

3.2、LV 扩容示例

  • 查看VG剩余容量

    [root@localhost ~]# vgdisplay VG_1 
      --- Volume group ---
      VG Size               29.95 GiB
      PE Size               16.00 MiB
      Total PE              1917
      Alloc PE / Size       128 / 2.00 GiB
      Free  PE / Size       1789 / 27.95 GiB
      VG UUID               R5k1VZ-sw2K-DSbR-nOfO-9F8F-eXq2-ROTLeN
    
  • 扩容LV

    从上面的信息中可以看出,还有充足的空间可以使用

    [root@localhost ~]# lvresize -L +500M /dev/VG_1/LV_1
      Rounding size to boundary between physical extents: 512.00 MiB.
      Size of logical volume VG_1/LV_1 changed from 2.00 GiB (128 extents) to 2.50 GiB (160 extents).
      Logical volume VG_1/LV_1 successfully resized.
      
    # 确认扩容效果
    [root@localhost ~]# lvscan 
      ACTIVE            '/dev/VG_1/LV_1' [2.50 GiB] inherit
    
  • 扩容文件系统

    # 查看原本的文件系统内的superblock记录
    [root@localhost ~]# xfs_info /mnt
    meta-data=/dev/mapper/VG_1-LV_1  isize=512    agcount=4, agsize=131072 blks
    data     =                       bsize=4096   blocks=524288, imaxpct=25
             =                       sunit=0      swidth=0 blks
    
    # 扩容文件系统
    [root@localhost ~]# xfs_growfs /mnt
    
    # 再次查看文件系统内的superblock记录
    [root@localhost ~]# xfs_info /mnt
    meta-data=/dev/mapper/VG_1-LV_1  isize=512    agcount=5, agsize=131072 blks
    data     =                       bsize=4096   blocks=655360, imaxpct=25
             =                       sunit=0      swidth=0 blks
    
    # 查看文件系统大小
    [root@localhost ~]# df -lh /mnt
    文件系统               容量  已用  可用 已用% 挂载点
    /dev/mapper/VG_1-LV_1  2.5G   33M  2.5G    2% /mnt
    

从两次 xfs_info 的结果来看,整个区块组 (agcount) 的数量增加 1 个,新增的 block group 就是纪录新的设备容量文件系统所在;整体的 block 数量增加了,这样整个文件系统就扩容成功了

4、LVM动态分配空间

在传统的空间分配上,我们是一次性将所有的空间一次性分配完毕,比如我们创建一个 5GB 的分区,那么系统就一次性从硬盘上划 5GB 空间出来,但实际我们可能最多只使用了 500M,那么剩下的 4.5GB 也就浪费了

LVM thin Volume 提供了一种动态分配空间的技术,即用多少,分配多少。还是以分配 5GB 空间为例,LVM thin Volume 会预分配一个最大空间限制为 5GB 的存储池,然后再由 thin pool 去产生一个指定大小的 LV 设备,此时 thin pool 并不会把 5GB 空间全部分配给 LV,而是按需分配,假如此时 LV 只是用了 500M 的空间,那么 thin pool 就只给 LV 分配 500M 的空间,但是 LV 的最大使用空间不能超过 5GB

  • 使用lvcreate创建一个thin pool设备

    [root@localhost ~]# lvcreate -L 1G -T VG_1/test_pool
      Thin pool volume with chunk size 64.00 KiB can address at most 15.81 TiB of data.
      Logical volume "test_pool" created.
    
  • 查看创建的设备

    [root@localhost ~]# lvdisplay /dev/VG_1/test_pool 
      --- Logical volume ---
      LV Name                test_pool
      VG Name                VG_1
      LV UUID                olQfSe-FT11-aZEz-OMff-F3FI-6xmG-bvT3aB
      LV Write Access        read/write
      LV Creation host, time localhost.localdomain, 2022-09-02 22:15:39 +0800
      LV Pool metadata       test_pool_tmeta
      LV Pool data           test_pool_tdata
      LV Status              available
      # open                 0
      ## 总共可分配大小
      LV Size                1.00 GiB
      ##  已分配的容量百分比
      Allocated pool data    0.00%
      ## 已分配的元数据百分比
      Allocated metadata     10.23%
      Current LE             64
      Segments               1
      Allocation             inherit
      Read ahead sectors     auto
      - currently set to     8192
      Block device           253:5
      
    # 也可以使用lvs VGname的方式查看简要信息
    [root@localhost ~]# lvs VG_1
      LV        VG   Attr       LSize Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
      LV_1      VG_1 -wi-ao---- 2.50g                                                 
      test_pool VG_1 twi-a-tz-- 1.00g             0.00   10.23
    
  • 创建thin Volume

    # 语法
    lvcreate -V [容量] -T thin_pool_NAME -n  thin_Volume_NAME
    # 创建一个5GB的 thin Volume
    ## 这里只是做一个示例,实际情况下,为了安全起见,不建议创建超过最大允许空间的分区
    [root@localhost ~]# lvcreate -V 5G -T VG_1/test_pool -n tplv1
      Logical volume "tplv1" created.
      ## 1GB的test_pool可以创建出5GB的tplv1
      ## 这其实是假象,因为空间实际没有全部分配,实际最大使用空间不能超出1GB
    
  • 查看创建的tplv1

    [root@localhost ~]# lvs VG_1
      LV        VG   Attr       LSize Pool      Origin Data%  Meta%  Move Log Cpy%Sync Convert
      LV_1      VG_1 -wi-ao---- 2.50g                                                   
      test_pool VG_1 twi-aotz-- 1.00g                  0.00   10.25                  
      tplv1     VG_1 Vwi-a-tz-- 5.00g test_pool        0.00
    
  • 使用tplv1

    [root@localhost ~]# mkfs.xfs /dev/VG_1/tplv
    [root@localhost ~]# mount /dev/VG_1/tplv1 /mnt
    [root@localhost ~]# df -Th /mnt
    文件系统               类型  容量  已用  可用 已用% 挂载点
    /dev/mapper/VG_1-tplv1 xfs   5.0G   33M  5.0G    1% /mnt
    

5、LVM拆除流程

  • 卸载系统上的 LVM 文件系统(包括快照与所有 LV)

  • 使用 lvremove 移除 LV

  • 使用 vgchange -a n VG名称 移除 VG 的 Active 的标志

  • 使用 vgremove 移除 VG

  • 使用 pvremove 移除 PV

  • 使用 fdisk 修改 ID

6、重要说明

在 LVM 中,虽然可以缩减 PV、VG、LV,但是在缩减后可能会导致数据丢失,所以一般不建议对 LVM 进行缩减操作

  • 删除 PV 将删除当前受操作 PV 中的所有数据,如果确实需要减少 PV,在确保数据安全的情况下,建议从最后一个 PV 开始删除 (前提是 LV 采用线性模式写入)

  • 删除 VG 将会删除该 VG 中的所有数据,且不可恢复

  • LV 建议只是用扩容, 不建议做缩减操作