Red Hat Certified System Administrator (RHCSA) #6: Local Storage 2 — LVM Expansion and LUKS Encryption
In #5 Local Storage 1 we built partitions, swap, and the basic LVM structure (PV/VG/LV). This post builds on top of that, covering growing and shrinking an LVM you already created and encrypting a block device with LUKS for a permanent mount. Both tasks show up often in the RHCSA practical, and LV expansion in particular is a staple that appears on nearly every exam.
The value of LVM lies in being able to adjust capacity online, without downtime. When a disk runs low, you add a new disk as a PV, fold it into the VG, then grow the LV. The key point here is that growing the LV alone isn’t the end — you also have to extend the file system on top of it before the space actually shows up.
Recalling the LVM layers #
To understand expansion, you need to keep in mind how LVM’s three layers stack up. The higher you go, the more abstract each layer becomes.
| Layer | Abbr. | What it is |
|---|---|---|
| Physical Volume | PV | A physical block device (disk/partition) that LVM uses |
| Volume Group | VG | A capacity pool built by bundling several PVs |
| Logical Volume | LV | A virtual partition carved out of a VG. You put a file system on it |
Growing capacity always follows these layers. You enlarge the VG’s pool by adding a new PV, carve more capacity out of that pool into an LV, and finally extend the file system on top of the LV. To find out which step you’re blocked at, check the current state of each layer with these commands.
pvs # PV summary: capacity per disk and its owning VG
vgs # VG summary: total capacity and remaining free space (VFree)
lvs # LV summary: capacity per logical volume and its owning VGFor more detail, use the display family.
pvdisplay /dev/vdb1 # PV detail: PE size, total/allocated/free PE
vgdisplay vg_data # VG detail: total PE, Free PE / Size
lvdisplay /dev/vg_data/lv_app # LV detail: LV path, size, segmentsThe VFree column of vgs and the Free PE / Size row of vgdisplay are the key indicators that tell you how much further you can grow an LV right now. If that value is 0, you have to enlarge the VG first.
Expanding a VG: folding a new disk into the pool #
When the VG has no free space, you make a new block device into a PV and add it to the VG. The exam usually gives you a new disk (/dev/vdc, etc.) or a freshly created partition.
First, initialize the device you’ll add as a PV.
# When using the whole disk as a PV
pvcreate /dev/vdc
# Or when using a single partition as a PV (set the type code to LVM)
pvcreate /dev/vdc1When using a partition as a PV, create the partition with
fdiskorparted, set its type to LVM (8eorlvm), and tell the kernel about the partition-table change withpartprobe. The partition-creation procedure was covered in #5.
Now fold the PV you made into the existing VG.
vgextend vg_data /dev/vdcCheck with vgs that the expansion took effect. If VSize grew and VFree now has free space equal to the new disk’s capacity, it worked.
vgs vg_data
# VG #PV #LV #SN Attr VSize VFree
# vg_data 2 1 0 wz--n- <19.99g 10.00gExpanding an LV: growing the logical volume and file system together #
Once the VG has free space, grow the LV. This is where RHCSA’s most common point loss happens. If you grow only the LV and not the file system, lvs shows the increased capacity, but the actual usable space seen by df stays the same.
Method 1: all at once with the -r option (recommended) #
Giving lvextend the -r (--resizefs) option handles LV expansion and file-system expansion in a single command. It automatically calls the right tool for both XFS and ext4, so it’s the safest choice on the exam.
# Grow the LV by an additional 5 GB and extend the file system too
lvextend -r -L +5G /dev/vg_data/lv_app
# Pour all of the VG's remaining space into this LV and extend the file system
lvextend -r -l +100%FREE /dev/vg_data/lv_appMethod 2: extend the LV, then extend the file system separately #
If you don’t use -r, or you want to understand it as separate steps, grow the LV first and then grow the file system separately. Here the tool differs depending on the file-system type.
# 1) Extend the LV first
lvextend -L +5G /dev/vg_data/lv_app
# 2-a) For an XFS file system, use xfs_growfs (the mount point as the argument)
xfs_growfs /mnt/app
# 2-b) For an ext4 file system, use resize2fs (the LV path as the argument)
resize2fs /dev/vg_data/lv_appXFS can only be grown with xfs_growfs while mounted, and it takes the mount point as its argument. ext4’s resize2fs takes the LV device path as its argument and works regardless of whether it’s mounted. If you’re unsure which file system it is, check the type first with df -T /mnt/app or lsblk -f.
The difference between -L and -l #
lvextend has two ways to specify size, and confusing the two gives you a size you didn’t intend.
| Option | Unit | Meaning |
|---|---|---|
-L 8G | Absolute size (in bytes) | Make the LV exactly 8 GB |
-L +5G | Absolute-size increment | Add 5 GB to the current size |
-l 200 | Number of PEs | Make the LV 200 PEs |
-l +50 | PE-count increment | Add 50 PEs to the current count |
-l +100%FREE | Ratio of VG free space | Add all the space remaining in the VG |
Uppercase -L takes human-readable capacity (G/M), while lowercase -l takes a PE count or ratio (%FREE/%VG). When the request is “use all of the remaining space,” -l +100%FREE is the answer, and in that case it’s hard to hit it exactly with -L.
Shrinking an LV: ext4 only, XFS is impossible #
Shrinking — the reverse of expansion — is decided by the file-system type. This difference is an RHCSA staple trap.
- ext4: Can be shrunk. But you must always shrink the file system first and then the LV (the reverse order of expansion).
- XFS: Cannot be shrunk. XFS cannot be reduced by design. If you need to make it smaller, your only option is to back up and recreate.
For ext4 shrinking, the order is critical. To prevent data corruption, shrink the file system first and then reduce the LV to match that size.
# ext4 shrink procedure (does not apply to XFS)
umount /mnt/app # Unmount first
e2fsck -f /dev/vg_data/lv_app # Force a file-system check
resize2fs /dev/vg_data/lv_app 6G # Shrink the file system to 6 GB
lvreduce -L 6G /dev/vg_data/lv_app # Shrink the LV to 6 GB
mount /mnt/app # Mount again
lvreducealso has a-roption that can handle file-system shrinking and LV shrinking at once. But even bundled with-r, if the target is XFS, the shrink still fails. Remember that XFS won’t shrink whether the tool is chosen automatically or manually.
LUKS-encrypted volumes #
LUKS (Linux Unified Key Setup) is the standard way to encrypt a block device. An encrypted device must be unlocked with the correct passphrase (or key) before a plaintext mapping appears under /dev/mapper/, and you create a file system on that mapping to mount it. RHCSA presents a scenario where you encrypt a given disk or LV with LUKS and configure it to be unlocked and mounted automatically at boot.
The tool is cryptsetup, provided by the cryptsetup package.
1) LUKS format #
Initialize the target device as LUKS. This erases all existing data on the device, so always confirm the target. As a confirmation step you must type uppercase YES yourself.
cryptsetup luksFormat /dev/vdb1
# WARNING! ... will overwrite data ... irrevocably.
# Are you sure? (Type 'yes' in capital letters): YES
# Enter passphrase: ...
# Verify passphrase: ...2) LUKS open #
Open the encrypted device to create a plaintext mapping. The last argument is the mapping name, exposed as /dev/mapper/<name>.
cryptsetup luksOpen /dev/vdb1 cryptdata
# Enter passphrase for /dev/vdb1: ...
ls -l /dev/mapper/cryptdata # Verify the plaintext mapping3) Creating and mounting a file system #
Now treat the mapping device like an ordinary block device. Create a file system and mount it.
mkfs.xfs /dev/mapper/cryptdata
mkdir /secure
mount /dev/mapper/cryptdata /secureWhen you’re done, you can also close it. Closing removes the mapping under /dev/mapper/, and reopening it requires the passphrase.
umount /secure
cryptsetup luksClose cryptdataChecking LUKS device information #
Check an encrypted device’s status and header information with the following.
cryptsetup luksDump /dev/vdb1 # LUKS header: version, key slots
cryptsetup status cryptdata # Status of the open mapping
blkid /dev/vdb1 # Confirm TYPE="crypto_LUKS" and the UUID
lsblk -f # Device hierarchy and mapping relationshipThe UUID of the LUKS device that blkid reports is used as-is in the next step’s permanent crypttab configuration.
Permanent LUKS mount: crypttab + fstab #
A setup that relies on manual luksOpen and mount disappears on reboot. You have to configure two files together so the device is automatically unlocked and mounted at boot. This permanent configuration is the crux of RHCSA grading.
/etc/crypttab: which device to open under which name #
/etc/crypttab defines the LUKS devices to unlock at boot. The format is name backing-device key-file options, in that order.
# /etc/crypttab
# mapping-name backing device key-file options
cryptdata UUID=11112222-3333-4444-5555-666677778888 noneThe none in the third field means there is no key file, in which case you enter the passphrase by hand during boot. It’s safer to write the backing device as UUID=... rather than a path like /dev/vdb1, so it holds up even if the disk order changes. Use the blkid /dev/vdb1 result from the earlier step for the UUID.
/etc/fstab: where to mount the mapping device #
In fstab you write the mapping device that crypttab will create (/dev/mapper/cryptdata), not the encrypted original device.
# /etc/fstab
/dev/mapper/cryptdata /secure xfs defaults 0 0Order matters. crypttab creates /dev/mapper/cryptdata first, and then fstab mounts that mapping. If you write the original /dev/vdb1 in fstab, it tries to mount the raw encrypted data and fails.
Skipping the passphrase with a key file #
To avoid entering a passphrase on every boot, register a key file. Create a key file, add it as a key slot to LUKS, and write its path in crypttab.
# Create the key file (restrict permissions so only root can read)
dd if=/dev/urandom of=/root/luks-key bs=512 count=4
chmod 600 /root/luks-key
# Add the key file to this LUKS device's key slot (authenticate with the existing passphrase)
cryptsetup luksAddKey /dev/vdb1 /root/luks-keyThen change the key-file field in crypttab from none to the key-file path.
# /etc/crypttab (using a key file)
cryptdata UUID=11112222-3333-4444-5555-666677778888 /root/luks-keyVerifying the configuration #
Once the permanent configuration is done, verify it without rebooting. Close the mapping, make systemd process crypttab, and check fstab.
umount /secure
cryptsetup luksClose cryptdata
# Reapply crypttab (if there's no key file, you enter the passphrase here)
systemctl daemon-reload
cryptdisks_start cryptdata 2>/dev/null || cryptsetup luksOpen /dev/vdb1 cryptdata
mount -a # Verify fstab syntax and mounting. It must finish without errors
df -h /secure # Confirm the mountThe most reliable verification is an actual reboot. On the exam, if time allows, check directly after a reboot that /secure is mounted automatically.
Exam points #
Here are the points people get wrong most often in this area.
- XFS cannot be shrunk. Only expansion (
xfs_growfs) works. If “shrink it” comes up, that LV must be ext4; if it’s XFS, backup-and-recreate is the only path. - Forgetting to extend the file system after extending the LV is zero points. Bundle it with
lvextend -r, or if doing it separately, don’t forgetxfs_growfs <mount point>for XFS andresize2fs <LV path>for ext4. - ext4 shrinking is the reverse order. Shrink the file system first (
resize2fs) and the LV next (lvreduce). Reversing the order truncates data. - Distinguish
-Lfrom-l. “All of the remaining space” is-l +100%FREE. - For LUKS, write the mapping device in fstab. It’s
/dev/mapper/cryptdata, not/dev/vdb1. You must configure both crypttab and fstab for the permanent mount to work. - All work must survive a reboot to count. Get into the habit of verifying fstab with
mount -a.
Wrap-up #
What this post locked in:
- VG expansion: create a new PV with
pvcreateand fold it into the VG withvgextendto secure free space. - LV expansion: grow the LV and file system at once with
lvextend -r, or afterlvextend, grow them separately withxfs_growfsfor XFS andresize2fsfor ext4. - LV shrinking: only ext4 can do it, and you shrink the file system first. XFS cannot be shrunk.
- LVM info: use
pvs/vgs/lvsfor summaries andpvdisplay/vgdisplay/lvdisplayfor detail. - LUKS encryption: encrypt and unlock with
cryptsetup luksFormat/luksOpen, and configure/etc/crypttaband/etc/fstabtogether so it auto-unlocks and mounts at boot.
Next — File Systems #
We’ve covered storage’s block layer, up through expansion and encryption. Now we shift our eyes to the file system itself that rides on top of it.
In #7 File Systems: XFS, ext4, mount/fstab, NFS, AutoFS, we’ll type our way through the difference between XFS and ext4, how to permanently mount a local file system with fstab, and how to mount an NFS share and set up AutoFS to auto-mount only when needed.