DB-유

LVM Basics: Extending a Logical Volume

· linux, lvm, storage

"The database volume is at 95 percent, can you make it bigger?" is the storage request I get most. On LVM (the CentOS 7 default, optional on Ubuntu) it's a ten-minute job, no reboot, no unmount. On a bare partition it's miserable, which is most of the case for LVM.

Two situations come up: the volume group still has free space, or you have to add a disk first. Commands are the same on CentOS 7 and Ubuntu 16.04. Take a recent backup before you start. Growing is safe in practice, but storage is where mistakes are expensive, and I don't skip that.

Look at the layout first

LVM has three layers: physical volumes (disks or partitions), volume groups (pools made of physical volumes) and logical volumes (what you format and mount). Look at all three:

sudo pvs
sudo vgs
sudo lvs -o +devices
df -hT /var/lib/mysql

Typical output on a CentOS 7 VM:

  VG     #PV #LV #SN Attr   VSize   VFree
  centos   1   3   0 wz--n- <49.51g 4.00g

  LV   VG     Attr       LSize  Devices
  data centos -wi-ao---- 20.00g /dev/sda2(2560)
  root centos -wi-ao---- 20.00g /dev/sda2(0)
  swap centos -wi-ao----  2.00g /dev/sda2(7680)

The VFree column tells you whether you can skip the next section. Here there are 4 GB free in the group.

If VFree is zero, add a disk

If VFree is zero, attach a new disk through your hypervisor or cloud console, then find it. It appears without a reboot; if not, ask the kernel to rescan:

lsblk
echo "- - -" | sudo tee /sys/class/scsi_host/host0/scan

Suppose the new disk is /dev/sdb. Turn it into a physical volume and add it to the group. I use the whole disk rather than partitioning it; there is no advantage to a partition table here.

sudo pvcreate /dev/sdb
sudo vgextend centos /dev/sdb
sudo vgs

VFree now reflects the new disk. For a virtual disk that was grown in place rather than added, use pvresize /dev/sda2 after fixing the partition table with growpart from the cloud-utils-growpart package.

Extend the LV and the filesystem

lvextend can resize the filesystem in the same step with -r, which calls xfs_growfs or resize2fs for you. Grow by a fixed amount:

sudo lvextend -r -L +10G /dev/centos/data

Or take everything that is free in the group:

sudo lvextend -r -l +100%FREE /dev/centos/data

Note the difference between -L (size in bytes with a unit) and -l (size in extents or a percentage). Both XFS and ext4 grow while mounted.

If you prefer to do the filesystem step separately, or you are on a tool version without -r:

sudo lvextend -L +10G /dev/centos/data
sudo xfs_growfs /var/lib/mysql          # XFS takes the mount point
sudo resize2fs /dev/centos/data         # ext4 takes the device

Did it grow?

sudo lvs
df -hT /var/lib/mysql

The LSize in lvs and the Size column in df should both show the new size. On XFS, xfs_info /var/lib/mysql reports the block count in data = ... blocks=; multiply by the block size to cross-check. Nothing on the volume needs restarting; MySQL or whatever lives there just sees more free space.

Errors I've hit

  • Insufficient free space: 2560 extents needed, but only 1024 available. You asked for more than the group has. Check vgs, use +100%FREE, or add a disk first.
  • Filesystem /dev/mapper/centos-data has unsupported feature(s) or resize2fs: Bad magic number in super-block. You ran resize2fs on an XFS volume. Use xfs_growfs with the mount point instead. blkid /dev/centos/data shows the actual filesystem type.
  • Device /dev/sdb excluded by a filter. The disk carries an old partition table or filesystem signature. Confirm it really is the right, empty disk with lsblk -f, then sudo wipefs -a /dev/sdb and retry pvcreate.
  • xfs_growfs: /dev/centos/data is not a mounted XFS filesystem. xfs_growfs wants the mount point, not the device node, on the version in CentOS 7.

Shrinking is a different story: XFS cannot shrink at all, and ext4 must be unmounted to do so. So I size logical volumes small and leave headroom in the volume group. Growing is cheap and online; shrinking is neither.