我经常用虚拟机装各种版本的Linux系统来跑程序,一般硬盘分得比较小。比如CentOS 6就只分了16G,跑的是服务端的程序,不用安装界面,整个系统也就占3G不到,一般也够用。直到某一天,我需要把一个20G的sql脚本导入到数据库里。这才发觉自己从来没做过Linux的硬盘扩容,一番鼓捣之后,做个笔记本留档。

现在主流的Linux,基本都使用LVM分区。哪啥是LVM?这得先来了解一下基础概念。Logical Volume Manager中文名叫逻辑卷管理器,简称LVM,它是Linux下对逻辑卷进行管理的一套程序,LVM分区,就是LVM管理下的一个逻辑卷。LVM通常涉及下面几个术语:

  • PP(physical Partition)
    物理分区,通常指硬盘中的主分区,逻辑分区。严格来讲整个硬盘或者其他能存东西的物理介质包括网络存储也能作为一个物理分区,但一定是有实物的
  • PV(Physical Volume)
    物理卷,就是在PP(物理分区)的基础上,使用pvcreate指令写入一些数据,转换为可供LVM识别后的物理介质。
  • VG(Volumes Group)
    卷组,由一个或多个PV组成的一个分组,形成一大块存储空间
  • LV(Logical Volume)
    逻辑卷,也就是LVM分区,在VG上划分一块空间称为逻辑卷,一个VG上只要还有空间就可以建立多个LV。在逻辑卷之上可以建立文件系统(ext3、ext4等),然后即可把数据存到分区里
  • PE(Physical Extent)
    具有唯一编号的PE是可以被LVM寻址的最小单元,其大小是在创建VG时确定的,默认为4MB(可通过vgcreate -s指定)。一个VG包含N个PE,从VG上划分一块空间作为LV时就是把其中一部分数量的PE标记为该LV。

它们之间的关系,可以简单地概括为:一块硬盘,被分成了几个分区(PP),然后把PP转换为PV,多个PV可以组成一个VG。组成VG后,就得到了一块很大的空间,它的大小是以PE的来衡量的。现在从VG上划分一块空间形成一个LV,然后就可以在LV上创建文件系统,进行读写数据。

centos7 lvm扩容分区后 XFS怎么刷新 linux分区扩容 没用lvm_GNU


(图片来源于网络

这么做的目的,就是把物理存储介质和具体使用的空间解耦,例如/home这个文件夹,可能一部分在硬盘A,另一部分在硬盘B。这就是为什么被称为逻辑卷,因为这个卷是通过逻辑虚拟出来的,物理上不存在这个卷。解耦之后整个系统的空间就可以方便的扩容、更换物理介质,这对长期运行,不停服更换硬件的服务器很重要。

我的CentOS 6是在VritualBox中以一个硬盘以默认方式安装的,它的分区如下:

[root@localhost ~]# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/mapper/VolGroup-lv_root
                       14G  2.1G   11G  16% /
tmpfs                 499M     0  499M   0% /dev/shm
/dev/sda1             477M   34M  418M   8% /boot

可以看到,默认情况下只有一个根分区,从参数/dev/mapper/VolGroup-lv_root可以看出来它是一个LVM分区。所有数据都存在这个唯一的分区里,所以这次就是要对这个分区进行扩容。

使用lsblk则可以更清析地看到硬盘的分区结构

[root@localhost ~]# lsblk
NAME                        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sr0                          11:0    1 58.2M  0 rom  
sda                           8:0    0   16G  0 disk 
├─sda1                        8:1    0  500M  0 part /boot
└─sda2                        8:2    0 15.5G  0 part 
  ├─VolGroup-lv_root (dm-0) 253:0    0 13.9G  0 lvm  /
  └─VolGroup-lv_swap (dm-1) 253:1    0  1.6G  0 lvm  [SWAP]

可以看到系统中有一个光驱sr0;一个硬盘sda。硬盘被分为两个区(sda1、sda2),而sda2被划分为两个LVM分区(VolGroup-lv_root、VolGroup-lv_swap)。假如需要看到硬盘的一些更详细的信息,可以使用parted

[root@localhost ~]# parted /dev/sda
GNU Parted 2.1
Using /dev/sda
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) print all                                                        
Model: ATA VBOX HARDDISK (scsi)
Disk /dev/sda: 17.2GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos

Number  Start   End     Size    Type     File system  Flags
 1      1049kB  525MB   524MB   primary  ext4         boot
 2      525MB   17.2GB  16.7GB  primary               lvm

可以看到当前这个硬盘大小为17.2GB,有两个主分区,一个为ext4,另一个被标记为lvm。对于这个lvm管理的分区,它有PV、VG、LV等参数,可通过pvdisplay、vgdisplay、lvdisyplay打印出来:

[root@localhost ~]# pvdisplay
  --- Physical volume ---
  PV Name               /dev/sda2
  VG Name               VolGroup
  PV Size               15.51 GiB / not usable 3.00 MiB
  Allocatable           yes (but full)
  PE Size               4.00 MiB
  Total PE              3970
  Free PE               0
  Allocated PE          3970
  PV UUID               XydIzE-RJIT-Hcfc-5vCw-NnKE-goPE-VFwhn3

[root@localhost ~]# vgdisplay
  --- Volume group ---
  VG Name               VolGroup
  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               15.51 GiB
  PE Size               4.00 MiB
  Total PE              3970
  Alloc PE / Size       3970 / 15.51 GiB
  Free  PE / Size       0 / 0   
  VG UUID               43d3d6-xFIm-s2vF-Z1jY-pKBc-sniG-wT0VTL

[root@localhost ~]# lvdisplay
  --- Logical volume ---
  LV Path                /dev/VolGroup/lv_root
  LV Name                lv_root
  VG Name                VolGroup
  LV UUID                2OJpKu-4KI9-DpUX-ZiVl-wanM-gdlY-yMbCau
  LV Write Access        read/write
  LV Creation host, time localhost.localdomain, 2022-03-14 17:48:16 +0800
  LV Status              available
  # open                 1
  LV Size                13.91 GiB
  Current LE             3561
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           253:0
   
  --- Logical volume ---
  LV Path                /dev/VolGroup/lv_swap
  LV Name                lv_swap
  VG Name                VolGroup
  LV UUID                jWqLXl-yzPu-xzJ9-ao4a-9JB5-KYXu-X2niXP
  LV Write Access        read/write
  LV Creation host, time localhost.localdomain, 2022-03-14 17:48:18 +0800
  LV Status              available
  # open                 1
  LV Size                1.60 GiB
  Current LE             409
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           253:1

通过上面的信息,可以看到整个系统中有一个PV(物理卷,也就是sda2这个分区);有一个VG名字叫VolGroup,一共有3970个PE,每个PE大小为4MB,所以整个VG大小为15.51GB,空闲的PE(Free PE)为0,说明空间都被用光了;有两个LV,都是从VolGroup这个VG上划分出来的,一个13.91GB,一个1.6GB。

了解当前系统的信息后,开始对硬盘进行扩容。由于是虚拟机,就不用去买新硬盘了,可以直接在虚拟机上调整硬盘大小。VirtualBox的操作方式为:

关闭虚拟机,在菜单“管理/虚拟介质管理”中找到对应虚拟机的硬盘,设置新的大小即可。

centos7 lvm扩容分区后 XFS怎么刷新 linux分区扩容 没用lvm_逻辑卷_02

我这里直接把它调整到128GB,现在重新启动虚拟机,df -h可以看到各个分区大小没变,而parted使用print free可以看到硬盘大小变了,后面多出120G空间。这是因为系统是根据分区表来确定分区大小的,新加的空间没法直接使用。

[root@localhost ~]# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/mapper/VolGroup-lv_root
                       14G  2.1G   11G  16% /
tmpfs                 499M     0  499M   0% /dev/shm
/dev/sda1             477M   34M  418M   8% /boot
[root@localhost ~]# parted /dev/sda
GNU Parted 2.1
Using /dev/sda
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) print free                                                       
Model: ATA VBOX HARDDISK (scsi)
Disk /dev/sda: 137GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos

Number  Start   End     Size    Type     File system  Flags
        32.3kB  1049kB  1016kB           Free Space
 1      1049kB  525MB   524MB   primary  ext4         boot
 2      525MB   17.2GB  16.7GB  primary               lvm
        17.2GB  137GB   120GB            Free Space

(parted)

如果是新增一个硬盘,可以直接整个硬盘作为一个PP转换为PV(当然把整个硬盘格式化成一个分区来操作也是可以的)

pvcreate /dev/sdc
Physical volume "/dev/sdc" successfully created

但现在是在原有硬盘上扩展空间,因此只能分区。分区使用fdisk或者parted都可以,这里用更广泛一些的fdisk

[root@localhost ~]# fdisk /dev/sda

WARNING: DOS-compatible mode is deprecated. It's strongly recommended to
         switch off the mode (command 'c') and change display units to
         sectors (command 'u').

Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 3
First cylinder (2089-16709, default 2089):
Using default value 2089
Last cylinder, +cylinders or +size{K,M,G} (2089-16709, default 16709): 
Using default value 16709

Command (m for help): t
Partition number (1-4): 3
Hex code (type L to list codes): 8e
Changed system type of partition 3 to 8e (Linux LVM)

Command (m for help): p

Disk /dev/sda: 137.4 GB, 137438953472 bytes
255 heads, 63 sectors/track, 16709 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x0000a342

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *           1          64      512000   83  Linux
Partition 1 does not end on cylinder boundary.
/dev/sda2              64        2089    16264192   8e  Linux LVM
/dev/sda3            2089       16709   117437826+  8e  Linux LVM

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.

WARNING: Re-reading the partition table failed with error 16: Device or resource busy.
The kernel still uses the old table. The new table will be used at
the next reboot or after you run partprobe(8) or kpartx(8)
Syncing disks.

Command (m for help): n使用n指令创建分区,选p创建主分区(由上面的信息可知,默认情况下系统分了sda1 sda2两个主分区,那我干脆也分一个主分区3)
Partition number (1-4): 3设置主分区id为3,即sda3First cylinder (2089-16709, default 2089):输入分区开始的第一个扇区,默认为空闲空间的第一个扇区2089,所以我这里直接回车
Last cylinder, +cylinders or +size{K,M,G} (2089-16709, default 16709): 输入分区结束的最后一个扇区,默认为空闲空间的最后一个扇区16709,所以我这里直接回车
Command (m for help): t使用t指令修改分区的类型
Partition number (1-4): 3选择要修改的分区id
Hex code (type L to list codes): 8e选择分区的类型(8e就表示lvm),输入l可列出所有支持的类型
Command (m for help): p现在打印一下当前分区表,确认是不是自己想要的
Command (m for help): w确认分区表正确后,用w写入硬盘。我这里出现了一个警告,按提示是要重启一下

现在把新建的分区sda3转换为PV。由于我忽略了上面的警告,结果找不到sda3,这可能和VirtualBox的硬盘模拟有关,其他机子不一定会出现:

[root@localhost ~]# pvcreate sda3
  Device sda3 not found (or ignored by filtering).

重启后再执行即可

[root@localhost ~]# pvcreate /dev/sda3
  Physical volume "/dev/sda3" successfully created

由之前vgdisplay查看的数据可知道,当前系统有一个名字为VolGroup的VG,现在要把刚转换好的PV添加到这个VG里

[root@localhost ~]# vgextend VolGroup /dev/sda3
  Volume group "VolGroup" successfully extended

再次用vgdisplay,可以看到VG已经被扩大,现在有很多空闲的PE了

[root@localhost ~]# vgdisplay
  --- Volume group ---
  VG Name               VolGroup
  System ID             
  Format                lvm2
  Metadata Areas        2
  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                2
  Act PV                2
  VG Size               127.50 GiB
  PE Size               4.00 MiB
  Total PE              32641
  Alloc PE / Size       3970 / 15.51 GiB
  Free  PE / Size       28671 / 112.00 GiB
  VG UUID               43d3d6-xFIm-s2vF-Z1jY-pKBc-sniG-wT0VTL

由之前lvdisplay查看的数据可知道,当前有两个LV,一个lv_swap路径为/dev/VolGroup/lv_swap,一个lv_root路径为/dev/VolGroup/lv_root。记住路径,下面的扩容操作是使用路径来操作。现在需要对lv_root进行扩容

[root@localhost ~]# lvextend -l +100%FREE /dev/VolGroup/lv_root
  Size of logical volume VolGroup/lv_root changed from 13.91 GiB (3561 extents) to 125.91 GiB (32232 extents).
  Logical volume lv_root successfully resized.

上面是使用百分比来扩容,通过lvextend --help可以知道,还有很多种方式指定扩容的单位,比如

# 使用M、G等常用单位扩容,支持的单位为[bBsSkKmMgGtTpPeE]
lvextend -L +10G /dev/VolGroup/lv_root

# 使用PE数量扩容,通用一个PE为4M。空闲PE的数量和单个PE的大小可通过`vgdisplay`查看
lvextend -l +2560 /dev/VolGroup/lv_root

lvm分区的大小扩展了,但是通过df -h来查看,可以看到空间还是不变的。因为在lvm分区之上,linux还有一层文件系统(ext3、ext4等等),需要对文件系统扩展才行。ext3 和 ext4文件系统使用resize2fs,其他系统查下资料才知道

[root@localhost ~]# resize2fs /dev/VolGroup/lv_root
resize2fs 1.41.12 (17-May-2010)
Filesystem at /dev/VolGroup/lv_root is mounted on /; on-line resizing required
old desc_blocks = 1, new_desc_blocks = 8
Performing an on-line resize of /dev/VolGroup/lv_root to 33005568 (4k) blocks.
The filesystem on /dev/VolGroup/lv_root is now 33005568 blocks long.

现在使用df -h可以看到空间已经扩展了。

相比之下,Window的区分则显得更加简单、直观。Windows的分区直接就是采用“物理卷”,即分区怎么分,在物理上就是怎么划分的,使用DiskGenius或者傲梅分区助手等流行的工具可以直观地调整分区的大小

centos7 lvm扩容分区后 XFS怎么刷新 linux分区扩容 没用lvm_逻辑卷_03

centos7 lvm扩容分区后 XFS怎么刷新 linux分区扩容 没用lvm_数据_04

不过这种简单也是有限制的,那就是需要进入PE系统来操作,没办法不停机操作(也许有,但我不会),当然这对于个人电脑来说并不是一个重要的指标。