Thursday, August 12, 2021

How to resize an LVM partition

My Linux VM is Ubuntu20 with a primary partition of 32GB root volume in an LVM configuration. I need to increase the partition size. We can do this without a service interruption using standard Linux tools.

TL;DR: 

The overall procedure is as follows:

1. Increase the virtual disk size from the hypervisor
2. Check the partitions to identify which partition you need to expand - sfdisk -l /dev/sda
3. If a partition size mismatch occurs correct it automatically using parted -l /dev/sda
4. Increase the partition size to match the new disk layout - use growpart or parted ex. growpart /dev/sda 3
5. Increase the physical volume size to match the new partition size - pvresize
6. Increase the logical volume size to the new physical volume size - lvextend
7. Finally update the filesystem to match the logical volume layout - resize2fs


ELI5: How LVM works?

Physical disks (HDD) can have partitions (PART). Traditionally these partitions contain filesystems inside (ext4, xfs etc..). LVM extends this functionality by adding logical RAID capabilities on top of the traditional discs and partitions. One major benefit is that with LVM the partitions can be increased on the fly without system interruption.

With LVM the physical disks still have partitions. Inside the partition is what we define a LVM PV (Physical Volume) object. The PV is a member of a VG (Volume Group). A VG must have at least one PV in it. The VG can have one or more LVs (Logical Volumes) inside. The filesystem (ext4 or xfs) is defined within the VG.

This can be seen on the images bellow:






The steps in detail


Step 1 - Check disks and partitions

My VM has about 32GB.

I have increased the virtual disk size to 64GB but I will still need to increase the partition size and also the logical volume.

# df -h
Filesystem                         Size  Used Avail Use% Mounted on
udev                               1.9G     0  1.9G   0% /dev
tmpfs                              389M  932K  388M   1% /run
/dev/mapper/ubuntu--vg-ubuntu--lv   30G  4.5G   25G  16% /

The sfdisk command will also show an error for the primary disk /dev/sda informing of a size mismatch:

# sfdisk -l /dev/sda
GPT PMBR size mismatch (67108863 != 134217727) will be corrected by write.
The backup GPT table is not on the end of the device. This problem will be corrected by write.
Disk /dev/sda: 64 GiB, 68719476736 bytes, 134217728 sectors
Disk model: Virtual Disk
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: gpt
Disk identifier: 1F833CBF-C25F-47D4-81D1-ADD4BAEC2B80

Device       Start      End  Sectors  Size Type
/dev/sda1     2048  1050623  1048576  512M EFI System
/dev/sda2  1050624  3147775  2097152    1G Linux filesystem
/dev/sda3  3147776 67108830 63961055 30.5G Linux filesystem


Step 2 - Fix the size mismatch 

The mismatch can be fixed automatically by just listing the partitions with parted:

# parted -l
Warning: Not all of the space available to /dev/sda appears to be used, you can
fix the GPT to use all of the space (an extra 67108864 blocks) or continue with
the current setting?
Fix/Ignore? Fix
Model: Msft Virtual Disk (scsi)
Disk /dev/sda: 68.7GB
Sector size (logical/physical): 512B/4096B
Partition Table: gpt
Disk Flags:

Number  Start   End     Size    File system  Name  Flags
 1      1049kB  538MB   537MB   fat32              boot, esp
 2      538MB   1612MB  1074MB  ext4
 3      1612MB  34.4GB  32.7GB


Model: Linux device-mapper (linear) (dm)
Disk /dev/mapper/ubuntu--vg-ubuntu--lv: 32.7GB
Sector size (logical/physical): 512B/4096B
Partition Table: loop
Disk Flags:

Number  Start  End     Size    File system  Flags
 1      0.00B  32.7GB  32.7GB  ext4

... after which we can see that out disk size is ~68GB but the partition is still ~32GB.

Check the LVM configuration in more detail

# pvdisplay
  --- Physical volume ---
  PV Name               /dev/sda3
  VG Name               ubuntu-vg
  PV Size               <30.50 GiB / not usable 1.98 MiB
  Allocatable           yes (but full)
  PE Size               4.00 MiB
  Total PE              7807
  Free PE               0
  Allocated PE          7807
  PV UUID               MZPaja-j7E6-jFtX-U3Wr-DwO3-3vXa-udDg4s

# vgdisplay
  --- Volume group ---
  VG Name               ubuntu-vg
  System ID
  Format                lvm2
  Metadata Areas        1
  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                1
  Act PV                1
  VG Size               <30.50 GiB
  PE Size               4.00 MiB
  Total PE              7807
  Alloc PE / Size       7807 / <30.50 GiB
  Free  PE / Size       0 / 0
  VG UUID               fkfgen-hO2W-4Q0K-eRb7-0qs7-vTCq-BOGZjS

# lvdisplay
  --- Logical volume ---
  LV Path                /dev/ubuntu-vg/ubuntu-lv
  LV Name                ubuntu-lv
  VG Name                ubuntu-vg
  LV UUID                1DS7Aq-qpL4-vQ8X-ITTA-EvCf-ottt-wsk8di
  LV Write Access        read/write
  LV Creation host, time ubuntu-server, 2021-06-28 13:03:17 +0200
  LV Status              available
  # open                 1
  LV Size                <30.50 GiB
  Current LE             7807
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           253:0

# pvs
  PV         VG        Fmt  Attr PSize   PFree
  /dev/sda3  ubuntu-vg lvm2 a--  <30.50g    0
# vgs
  VG        #PV #LV #SN Attr   VSize   VFree
  ubuntu-vg   1   1   0 wz--n- <30.50g    0
# lvs
  LV        VG        Attr       LSize   Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  ubuntu-lv ubuntu-vg -wi-ao---- <30.50g


... The LVM physical volume is using the /dev/sda3 partition. The LVM volume group name is named ubuntu-vg. The LVM logical volume path is  /dev/ubuntu-vg/ubuntu-lv and its name is ubuntu-lv. The size of the logical volume is ~30GB.

First lets increase the partition itself to match the new disk layout. The partition can be increased using parted or growpart. I will use growpart since its easier and the command will persist in the Linux history.
The command bellow is: growpart <PHISICAL/DISK> <PART-NUMBER>


Step 3 - Increase the partition size

# growpart /dev/sda 3
CHANGED: partition=3 start=3147776 old: size=63961055 end=67108831 new: size=131069919 end=134217695

Let's check the disk itself again with the partitions. The partition has been resized however the partition is just the frame boundary of the LVM physical volume which needs to be increased next to match the partition size.

# sfdisk -l /dev/sda
Disk /dev/sda: 64 GiB, 68719476736 bytes, 134217728 sectors
Disk model: Virtual Disk
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: gpt
Disk identifier: 1F833CBF-C25F-47D4-81D1-ADD4BAEC2B80

Device       Start       End   Sectors  Size Type
/dev/sda1     2048   1050623   1048576  512M EFI System
/dev/sda2  1050624   3147775   2097152    1G Linux filesystem
/dev/sda3  3147776 134217694 131069919 62.5G Linux filesystem

... Notice how /dev/sda3 now shows ~62GB of size. This is just the partition as seen by sfdisk or parted command. Both are not aware of the LVM configuration bellow.

Step 4 - Increase PV size to inside the partition

Next the LVM physical volume needs to be updated:

# pvresize /dev/sda3
  Physical volume "/dev/sda3" changed
  1 physical volume(s) resized or updated / 0 physical volume(s) not resized

After which the LVM logical volume can be updated to the new size:

Step 5 - Increase LV size to match the PV

# lvextend -l +100%FREE /dev/ubuntu-vg/ubuntu-lv
  New size (7807 extents) matches existing size (7807 extents). 

If you check with df -h now, you will still see the old value for the partition space. See it for yourself. That is because the filesystem inside the partition needs to match the new disk geometry. The filesystem can be updated using resize2fs.

Step 6 - Update the filesystem to match the LV size

# resize2fs /dev/mapper/ubuntu--vg-ubuntu--lv
resize2fs 1.45.5 (07-Jan-2020)
Filesystem at /dev/mapper/ubuntu--vg-ubuntu--lv is mounted on /; on-line resizing required
old_desc_blocks = 4, new_desc_blocks = 8
The filesystem on /dev/mapper/ubuntu--vg-ubuntu--lv is now 16382976 (4k) blocks long.

Finally check that the new partition size matches the new disk layout:

~# df -h
Filesystem                         Size  Used Avail Use% Mounted on
udev                               1.9G     0  1.9G   0% /dev
tmpfs                              389M  936K  388M   1% /run
/dev/mapper/ubuntu--vg-ubuntu--lv   62G  4.5G   55G   8% /

No comments:

Post a Comment