22.2 pvcreate, vgcreate, lvcreate: Building an LVM Stack
Right, let’s get our hands dirty. You’ve got some raw storage—a disk, a partition, maybe a fancy RAID array. It’s just sitting there, dumb and inert. Our job is to infuse it with LVM’s particular brand of magic, and it all starts with a three-step ritual: pvcreate, vgcreate, lvcreate. Think of it as building a storage skyscraper: Physical Volumes (PVs) are your bricks, the Volume Group (VG) is the building itself, and Logical Volumes (LVs) are the swanky, configurable apartments inside.
Turning Raw Space into an LVM Brick (pvcreate)
First, you need a block device. This could be a whole disk (/dev/sdb) or, more sensibly, a partition (/dev/sdb1). Using a whole disk is faster but hands over the entire thing to LVM, which will slap its own metadata on there. I usually just use partitions; it keeps the BIOS and other tools from getting confused.
The pvcreate command does one simple thing: it initializes the device for use by LVM. It writes a small metadata header onto the device, effectively branding it as an LVM Physical Volume. It’s now a brick, ready to be used in construction.
# Let's assume we're using a partition. First, create it if needed.
sudo parted /dev/sdb mkpart primary 1MiB 100%
# Now, brand it for LVM.
sudo pvcreate /dev/sdb1
Why it works this way: This initialization separates LVM’s domain from the raw hardware. The system now knows /dev/sdb1 isn’t just some random partition; it’s a member of the LVM club. The most common pitfall here is trying to pvcreate a device that’s already in use (mounted, part of another VG, etc.). LVM will usually yell at you, which is good. Always double-check with lsblk or fdisk -l.
The Storage Pool: Creating a Volume Group (vgcreate)
A Physical Volume by itself is useless. This is where LVM’s real genius kicks in. You toss one or more PVs into a pool called a Volume Group (VG). This pool is your available storage budget. The VG abstracts away the underlying physical devices; it doesn’t care if your storage budget comes from one big SSD or ten rusty old hard drives. They all just become “available extents” (the basic units of storage in LVM, typically 4MiB chunks).
Creating one is straightforward. You give it a name (make it descriptive!) and point it at your prepared PV(s).
# Create a VG named 'my_volume_group' using the PV we just created
sudo vgcreate my_volume_group /dev/sdb1
# Want to use multiple PVs? Easy.
sudo vgcreate my_big_vg /dev/sdb1 /dev/sdc1 /dev/nvme0n1p2
The brilliant part: Once these PVs are in the VG, their individual identities cease to matter. You’re just drawing from a pooled resource. The best practice here is to give your VGs a meaningful name. vg00 tells you nothing; data_ssd_vg tells you everything. Also, note that you can add more PVs to a VG later with vgextend, which is like adding more bricks to your building’s foundation. It’s one of the killer features.
Carving Out Usable Space: Logical Volumes (lvcreate)
Now for the fun part. Your VG is just a pool of potential. You need to carve out Logical Volumes from it. These LVs are the block devices you’ll actually format with mkfs and mount to a directory. They are fantastically flexible.
The basic command requires a name (-n), a size (-L), and the VG to pull from.
# Create a 50GiB LV named 'my_data' from our VG
sudo lvcreate -L 50G -n my_data my_volume_group
This creates the device /dev/my_volume_group/my_data (the path is /dev/<vg name>/<lv name>). Now you can treat it like any other disk:
sudo mkfs.ext4 /dev/my_volume_group/my_data
sudo mkdir /data
sudo mount /dev/my_volume_group/my_data /data
Why this is better than partitions: Notice we specified the size as 50G. We didn’t have to care where on the physical disks that space came from. We’re not wedging it between other partitions. We’re just allocating it from the free pool. Need a bigger LV later? lvextend. Need a smaller one? Well, that’s trickier, but often possible. You can even create thin-provisioned LVs that are like promising you’ll buy more furniture only after you actually need it, letting you overallocate space. It’s a bit absurd, but incredibly useful.
The designers’ questionable choice: The default naming scheme for the device node. /dev/mapper/my_volume_group-my_data is also created as a symlink to /dev/my_volume_group/my_data. It’s redundant and confusing when you’re looking at lsblk output. Just be aware both paths exist and point to the same thing. It’s a historical quirk we’re stuck with.
And there you have it. You’ve turned dumb hardware into intelligent, flexible storage. pvcreate -> vgcreate -> lvcreate. The fundamental trilogy. Master this, and you’re already dangerous.