Linux LVM

Understand Linux Logical Volume Manager and learn how to create Physical Volumes, Volume Groups, Logical Volumes, filesystems, and mount points.

Introduction

LVM, or Logical Volume Manager, provides a flexible way to manage storage on Linux systems.

Traditional disk management often connects a filesystem directly to a partition:

Disk
  │
  ▼
Partition
  │
  ▼
Filesystem
  │
  ▼
Mount Point

LVM introduces additional abstraction layers:

Disk
  │
  ▼
Partition
  │
  ▼
Physical Volume (PV)
  │
  ▼
Volume Group (VG)
  │
  ▼
Logical Volume (LV)
  │
  ▼
Filesystem
  │
  ▼
Mount Point

This separation allows storage to be managed more flexibly.

For example, a Volume Group can combine storage from multiple Physical Volumes and provide that storage to multiple Logical Volumes.

Why Use LVM?

LVM is useful when storage needs to be managed independently from the physical disk layout.

Some common use cases include:

  • servers
  • virtualization hosts
  • databases
  • application servers
  • backup systems
  • container hosts
  • infrastructure environments

One important benefit is that logical volumes do not have to map directly to physical disk partitions.

For example:

/dev/sdb1 ──┐
            ├── Volume Group
/dev/sdc1 ──┘
                  │
                  ├── LV: database
                  ├── LV: docker
                  └── LV: backup

The physical storage and logical storage layout are therefore separated.

The LVM Layers

LVM consists of three main concepts:

  • Physical Volume (PV)
  • Volume Group (VG)
  • Logical Volume (LV)

A filesystem is then created on the Logical Volume.

The complete model is:

Physical Storage
      │
      ▼
Physical Volume
      │
      ▼
Volume Group
      │
      ▼
Logical Volume
      │
      ▼
Filesystem
      │
      ▼
Mount Point

Understanding these layers is more important than memorizing the commands.

Physical Volume

A Physical Volume (PV) is storage initialized for use by LVM.

A Physical Volume can be created from a partition:

sudo pvcreate /dev/sdb1

After running the command, verify it:

sudo pvs

Example:

PV         VG  Fmt  Attr PSize   PFree
/dev/sdb1      lvm2 a--  931.00g 931.00g

The partition is now an LVM Physical Volume.

The storage hierarchy is:

/dev/sdb
└── /dev/sdb1
    └── Physical Volume

A Physical Volume can also be created directly on a disk but sometimes this is causing troubles so better create it on partition:

sudo pvcreate /dev/sdb

However, using a dedicated partition makes the intended storage layout explicit and is a common approach.

You can also use command:

sudo pvdisplay
  • to see more details

If from some reason you do not see all Physical Volumes you can try command for scanning them:

sudo pvscan

Example:

[tomik@localhost ~]$ sudo pvscan
  PV /dev/nvme0n1p2   VG almalinux       lvm2 [<19.00 GiB / 0    free]
  PV /dev/sda2                           lvm2 [1023.00 MiB]
  PV /dev/sdb2                           lvm2 [1023.00 MiB]
  PV /dev/sdc2                           lvm2 [1023.00 MiB]
  Total: 4 [21.99 GiB] / in use: 1 [<19.00 GiB] / in no VG: 3 [<3.00 GiB]

Volume Group

A Volume Group (VG) is a pool of storage made from one or more Physical Volumes.

Create a Volume Group:

sudo vgcreate vg_name device

sudo vgcreate vg_data /dev/sdb1

Verify it:

sudo vgs

Example:

VG       #PV #LV #SN Attr   VSize   VFree
vg_data    1   0   0 wz--n- 931.00g 931.00g

The hierarchy is now:

/dev/sdb
└── /dev/sdb1
    └── PV
        └── VG: vg_data

Multiple Physical Volumes in One Volume Group

One of the useful properties of LVM is that a Volume Group can contain multiple Physical Volumes.

For example:

/dev/sdb1 ──┐
            ├── VG: vg_data
/dev/sdc1 ──┘

The Volume Group then provides a larger pool of storage.

The exact allocation and redundancy characteristics depend on how Logical Volumes are created.

LVM itself should not automatically be considered a RAID solution.

RAID is covered separately in the storage documentation.

Example:

[tomik@localhost ~]$ sudo vgcreate testgroup /dev/sda2 /dev/sdb2 /dev/sdc2
[sudo] password for tomik:
  Volume group "testgroup" successfully created
[tomik@localhost ~]$

Now we can see our physical volumes are associtated to Volume Group

[tomik@localhost ~]$ sudo pvs
  PV             VG        Fmt  Attr PSize    PFree
  /dev/nvme0n1p2 almalinux lvm2 a--   <19.00g       0
  /dev/sda2      testgroup lvm2 a--  1020.00m 1020.00m
  /dev/sdb2      testgroup lvm2 a--  1020.00m 1020.00m
  /dev/sdc2      testgroup lvm2 a--  1020.00m 1020.00m
[tomik@localhost ~]$

You can also check it with other commands:

[tomik@localhost ~]$ sudo vgs
  VG        #PV #LV #SN Attr   VSize   VFree
  almalinux   1   2   0 wz--n- <19.00g     0
  testgroup   3   0   0 wz--n-  <2.99g <2.99g
[tomik@localhost ~]$ sudo vgdisplay
  --- Volume group ---
  VG Name               testgroup
  System ID
  Format                lvm2
  Metadata Areas        3
  Metadata Sequence No  1
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                0
  Open LV               0
  Max PV                0
  Cur PV                3
  Act PV                3
  VG Size               <2.99 GiB
  PE Size               4.00 MiB
  Total PE              765
  Alloc PE / Size       0 / 0
  Free  PE / Size       765 / <2.99 GiB
  VG UUID               O89qmS-Cddt-GOug-oVB8-pba0-I8H4-iPbsEr

  --- Volume group ---
  VG Name               almalinux
  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               <19.00 GiB
  PE Size               4.00 MiB
  Total PE              4863
  Alloc PE / Size       4863 / <19.00 GiB
  Free  PE / Size       0 / 0
  VG UUID               NiPtMp-Km2e-W5dS-erOR-gOit-v7GE-iCWSFe

[tomik@localhost ~]$ sudo vgscan
  Found volume group "testgroup" using metadata type lvm2
  Found volume group "almalinux" using metadata type lvm2
[tomik@localhost ~]$

Logical Volume

A Logical Volume (LV) is a virtual block device created inside a Volume Group.

For example:

sudo lvcreate -l 100%FREE -n lv_data vg_data

This creates:

/dev/vg_data/lv_data

Verify it:

sudo lvs

Example:

LV       VG       Attr       LSize
lv_data  vg_data  -wi-a----- 931.00g

The complete LVM structure is now:

/dev/sdb
└── /dev/sdb1
    └── PV
        └── VG: vg_data
            └── LV: lv_data

Logical Volume Size

Instead of using all available space, you can create a Logical Volume with a specific size.

For example:

sudo lvcreate -L 100G -n lv_data vg_data

This creates a 100 GB Logical Volume.

You can then use the remaining space for other Logical Volumes.

For example:

sudo lvcreate -L 100G -n lv_database vg_data
sudo lvcreate -L 200G -n lv_docker vg_data
sudo lvcreate -L 50G -n lv_backup vg_data

The result could look like:

VG: vg_data
│
├── LV: lv_database   100G
├── LV: lv_docker     200G
└── LV: lv_backup      50G

The remaining space stays available in the Volume Group.

Check it with:

sudo vgs

Creating a Filesystem

A Logical Volume is a block device. It does not automatically contain a filesystem.

For example, create an ext4 filesystem:

sudo mkfs.ext4 /dev/vg_data/lv_data

WARNING: Formatting a Logical Volume destroys existing data on that volume. Always verify the target before running mkfs.

You can verify the filesystem with:

lsblk -f

Example:

NAME                  FSTYPE FSVER LABEL UUID                                 MOUNTPOINTS
sdb
└─sdb1                LVM2_member       ...
  └─vg_data-lv_data   ext4   1.0         ...                                 

Mounting the Filesystem

Create a mount point:

sudo mkdir -p /mnt/data

Mount the Logical Volume:

sudo mount /dev/vg_data/lv_data /mnt/data

Verify it:

df -h

Example:

Filesystem                  Size  Used Avail Use% Mounted on
/dev/mapper/vg_data-lv_data  916G   28K  870G   1% /mnt/data

The filesystem is now available at:

/mnt/data

Making the Mount Persistent

A manual mount command normally applies only to the current boot.

To mount the filesystem automatically after reboot, configure /etc/fstab.

First obtain the filesystem UUID:

sudo blkid /dev/vg_data/lv_data

Example:

/dev/vg_data/lv_data: UUID="12345678-abcd-1234-abcd-123456789abc" TYPE="ext4"

Add an entry to /etc/fstab:

UUID=12345678-abcd-1234-abcd-123456789abc /mnt/data ext4 defaults 0 2

Then test the configuration:

sudo mount -a

If there are no errors, the filesystem should be mountable using the /etc/fstab configuration.

LVM Commands

Several commands are particularly useful when working with LVM.

Physical Volumes

List Physical Volumes:

sudo pvs

Display detailed information:

sudo pvdisplay

Volume Groups

List Volume Groups:

sudo vgs

Display detailed information:

sudo vgdisplay

Logical Volumes

List Logical Volumes:

sudo lvs

Display detailed information:

sudo lvdisplay

These commands are useful for both administration and troubleshooting.

Extending a Logical Volume

One of the practical benefits of LVM is the ability to extend Logical Volumes when free space is available.

Check the available space in the Volume Group:

sudo vgs

For example:

VG       VSize   VFree
vg_data  931.00g 331.00g

This means that approximately 331 GB is still available in the Volume Group.

Extend the Logical Volume by 100 GB:

sudo lvextend -L +100G /dev/vg_data/lv_data

Check the new size:

sudo lvs

The Logical Volume has now grown, but the filesystem may still need to be expanded.

For ext4:

sudo resize2fs /dev/vg_data/lv_data

A common workflow is therefore:

Free space in VG
      │
      ▼
Extend LV
      │
      ▼
Extend filesystem

The exact filesystem command depends on the filesystem type.

Extending the Filesystem with lvextend

For supported filesystems, lvextend can also resize the filesystem automatically with the -r option.

For example:

sudo lvextend -r -L +100G /dev/vg_data/lv_data

This performs both operations:

Logical Volume
      +
Filesystem

Always verify that the filesystem supports the intended resize operation.

Reducing a Logical Volume

Reducing an LV is more dangerous than extending one.

For filesystems such as ext4, the filesystem normally needs to be reduced before reducing the Logical Volume.

The order is important:

Filesystem
      ↓
Reduce filesystem
      ↓
Reduce Logical Volume

Never blindly run:

lvreduce

on a filesystem that still contains data beyond the new size.

Doing so can cause data loss.

sudo lvs
df -h /mnt/vgroup_backup
sudo umount /mnt/vgroup_backup
sudo e2fsck -f /dev/mapper/testgroup-backup
sudo resize2fs /dev/mapper/testgroup-backup 1G
sudo lvreduce -L 1G /dev/mapper/testgroup-backup
sudo lvs
sudo vgs


[tomik@localhost mnt]$ sudo lvs
  LV     VG        Attr       LSize   Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  root   almalinux -wi-ao---- <17.00g
  swap   almalinux -wi-ao----   2.00g
  backup testgroup -wi-ao----  <1.99g
  data1  testgroup -wi-ao----   1.00g

[tomik@localhost mnt]$ lsblk -f
NAME                 FSTYPE      LABEL UUID                                   MOUNTPOINT
sda
├─sda1               ext4              711a9e40-37a5-4cff-9576-e97d414b798f   /mnt/disk_a
└─sda2               LVM2_member       TcNh9D-a9oY-C4EH-dwIQ-c3j4-lsBG-OjubBz
  └─testgroup-data1  ext4              1c02d35a-4bf0-4faa-8498-8e7935e4089e   /mnt/vgroup_data1
sdb
├─sdb1               ext4              5b7dceb5-fbc3-4a4a-b283-84581657db00   /mnt/disk_b
└─sdb2               LVM2_member       rubpMX-o7Ir-1TMJ-xtui-kLpZ-Vu2M-MBsdl5
  ├─testgroup-data1  ext4              1c02d35a-4bf0-4faa-8498-8e7935e4089e   /mnt/vgroup_data1
  └─testgroup-backup ext4              5e688803-e77a-4533-85b1-aa2430b379c8   /mnt/vgroup_backup
sdc
├─sdc1               ext4              186df32e-516d-4a31-bb3b-cddf06e1b373   /mnt/disk_c
└─sdc2               LVM2_member       cdIyxE-G6S2-XVlL-JgfX-FVut-BWOd-okgDzD
  └─testgroup-backup ext4              5e688803-e77a-4533-85b1-aa2430b379c8   /mnt/vgroup_backup
sr0
nvme0n1
├─nvme0n1p1          xfs               da318a00-f09f-4011-a953-bc53134e63be   /boot
└─nvme0n1p2          LVM2_member       PDobUG-lBPP-ivlA-klrL-VpKO-yJ2K-K120lO
  ├─almalinux-root   xfs               79e9a10a-d166-4f92-a499-8be8a442b7ef   /
  └─almalinux-swap   swap              80d58ae7-1412-407a-bfef-83e572b2cd38   [SWAP]

[tomik@localhost mnt]$ df -h
Filesystem                    Size  Used Avail Use% Mounted on
devtmpfs                      351M     0  351M   0% /dev
tmpfs                         370M     0  370M   0% /dev/shm
tmpfs                         370M  5.4M  364M   2% /run
tmpfs                         370M     0  370M   0% /sys/fs/cgroup
/dev/mapper/almalinux-root     17G  3.6G   14G  21% /
vmhgfs-fuse                   930G  611G  320G  66% /mnt/hgfs
/dev/nvme0n1p1               1014M  301M  714M  30% /boot
/dev/sdb1                     989M   24K  922M   1% /mnt/disk_b
/dev/sdc1                     989M   24K  922M   1% /mnt/disk_c
/dev/sda1                     989M  101M  823M  11% /mnt/disk_a
tmpfs                          74M     0   74M   0% /run/user/1000
/dev/mapper/testgroup-data1   974M   24K  907M   1% /mnt/vgroup_data1
/dev/mapper/testgroup-backup  2.0G   28K  1.9G   1% /mnt/vgroup_backup

[tomik@localhost mnt]$ sudo lvs
  LV     VG        Attr       LSize   Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  root   almalinux -wi-ao---- <17.00g
  swap   almalinux -wi-ao----   2.00g
  backup testgroup -wi-ao----  <1.99g
  data1  testgroup -wi-ao----   1.00g

[tomik@localhost mnt]$ sudo umount /mnt/vgroup_backup

[tomik@localhost mnt]$ sudo e2fsck -f /dev/mapper/testgroup-backup
e2fsck 1.45.6 (20-Mar-2020)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/mapper/testgroup-backup: 12/130304 files (0.0% non-contiguous), 17911/521216 blocks

[tomik@localhost mnt]$ sudo resize2fs /dev/mapper/testgroup-backup 1G
resize2fs 1.45.6 (20-Mar-2020)
Resizing the filesystem on /dev/mapper/testgroup-backup to 262144 (4k) blocks.
The filesystem on /dev/mapper/testgroup-backup is now 262144 (4k) blocks long.

[tomik@localhost mnt]$ sudo lvreduce -L 1G /dev/mapper/testgroup-backup
  WARNING: Reducing active logical volume to 1.00 GiB.
  THIS MAY DESTROY YOUR DATA (filesystem etc.)
Do you really want to reduce testgroup/backup? [y/n]: y
  Size of logical volume testgroup/backup changed from <1.99 GiB (509 extents) to 1.00 GiB (256 extents).
  Logical volume testgroup/backup successfully resized.

[tomik@localhost mnt]$ sudo lvs
  LV     VG        Attr       LSize   Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  root   almalinux -wi-ao---- <17.00g
  swap   almalinux -wi-ao----   2.00g
  backup testgroup -wi-a-----   1.00g
  data1  testgroup -wi-ao----   1.00g

[tomik@localhost mnt]$ sudo vgs
  VG        #PV #LV #SN Attr   VSize   VFree
  almalinux   1   2   0 wz--n- <19.00g       0
  testgroup   3   2   0 wz--n-  <2.99g 1012.00m


[tomik@localhost mnt]$ sudo pvs -o pv_name,pv_size,pv_free,pv_used
  PV             PSize    PFree    Used
  /dev/nvme0n1p2  <19.00g       0   <19.00g
  /dev/sda2      1020.00m       0  1020.00m
  /dev/sdb2      1020.00m 1012.00m    8.00m
  /dev/sdc2      1020.00m       0  1020.00m

[tomik@localhost mnt]$ sudo lvs -o lv_name,lv_size,vg_name,devices
  LV     LSize   VG        Devices
  root   <17.00g almalinux /dev/nvme0n1p2(512)
  swap     2.00g almalinux /dev/nvme0n1p2(0)
  backup   1.00g testgroup /dev/sdc2(0)
  backup   1.00g testgroup /dev/sdb2(1)
  data1    1.00g testgroup /dev/sda2(0)
  data1    1.00g testgroup /dev/sdb2(0)

[tomik@localhost mnt]$ sudo vgdisplay testgroup
  --- Volume group ---
  VG Name               testgroup
  System ID
  Format                lvm2
  Metadata Areas        3
  Metadata Sequence No  6
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                2
  Open LV               1
  Max PV                0
  Cur PV                3
  Act PV                3
  VG Size               <2.99 GiB
  PE Size               4.00 MiB
  Total PE              765
  Alloc PE / Size       512 / 2.00 GiB
  Free  PE / Size       253 / 1012.00 MiB
  VG UUID               O89qmS-Cddt-GOug-oVB8-pba0-I8H4-iPbsEr

Removing LVM Components

LVM components should normally be removed in the reverse order in which they were created.

Conceptually:

Filesystem
   ↓
Logical Volume
   ↓
Volume Group
   ↓
Physical Volume
   ↓
Partition

For example, after unmounting a filesystem:

sudo umount /mnt/data

the Logical Volume can be removed:

sudo lvremove /dev/vg_data/lv_data

The Volume Group can then be removed:

sudo vgremove vg_data

The Physical Volume can then be removed from LVM:

sudo pvremove /dev/sdb1

Finally, the partition can be removed using fdisk or parted.

WARNING: These operations are destructive. Make sure the storage is no longer needed before removing any LVM layer.

Complete Practical Example

Assume that:

/dev/sdb

is a new 1 TB disk.

The disk has already been partitioned and contains:

/dev/sdb1

marked as Linux LVM.

Step 1: Create the Physical Volume

sudo pvcreate /dev/sdb1

Verify:

sudo pvs

Step 2: Create the Volume Group

sudo vgcreate vg_data /dev/sdb1

Verify:

sudo vgs

Step 3: Create the Logical Volume

Use all available space:

sudo lvcreate -l 100%FREE -n lv_data vg_data

Verify:

sudo lvs

Step 4: Create the Filesystem

sudo mkfs.ext4 /dev/vg_data/lv_data

Step 5: Create the Mount Point

sudo mkdir -p /mnt/data

Step 6: Mount the Filesystem

sudo mount /dev/vg_data/lv_data /mnt/data

Step 7: Verify

Check the block devices:

lsblk -f

Check the mounted filesystem:

df -h

The final layout is:

/dev/sdb
└── /dev/sdb1
    └── PV
        └── VG: vg_data
            └── LV: lv_data
                └── ext4
                    └── /mnt/data

Understanding the Complete Storage Stack

The complete process can be visualized as:

Physical Disk
/dev/sdb
    │
    ▼
Partition
/dev/sdb1
    │
    ▼
Physical Volume
PV
    │
    ▼
Volume Group
vg_data
    │
    ▼
Logical Volume
lv_data
    │
    ▼
Filesystem
ext4
    │
    ▼
Mount Point
/mnt/data

Each layer has a different responsibility.

Layer Purpose
Disk Physical storage device
Partition Divides the disk
PV Makes storage available to LVM
VG Provides a storage pool
LV Provides a logical block device
Filesystem Organizes files and directories
Mount point Makes the filesystem accessible in Linux

LVM vs RAID

LVM and RAID are related to storage, but they solve different problems.

LVM primarily provides:

  • flexible storage management
  • logical volumes
  • storage pooling
  • volume resizing
  • abstraction from physical disk layout

RAID primarily addresses:

  • redundancy
  • availability
  • performance
  • combining physical disks into arrays

They can also be used together.

For example:

Physical Disks
      │
      ▼
     RAID
      │
      ▼
Storage Device
      │
      ▼
     LVM
      │
      ▼
Logical Volumes

The next storage chapter covers RAID separately.

LVM and DevOps

Understanding LVM is useful for DevOps and infrastructure work because storage frequently sits underneath other technologies.

A simplified infrastructure stack might look like:

Physical Disk
      │
      ▼
Partition
      │
      ▼
LVM
      │
      ▼
Filesystem
      │
      ▼
Container Runtime
      │
      ▼
Application Data

On virtualization hosts, database servers, CI/CD infrastructure, and container hosts, understanding the storage layers makes troubleshooting much easier.

For example, if a filesystem reports that it is full, you need to determine which layer is actually out of space:

Filesystem full?
       │
       ├── Filesystem capacity?
       │
       ├── Logical Volume capacity?
       │
       ├── Free space in Volume Group?
       │
       └── Physical storage capacity?

The commands introduced in this chapter help identify these layers.

Key Takeaways

Remember the three main LVM components:

PV → Physical Volume
VG → Volume Group
LV → Logical Volume

The complete storage model is:

Disk
  ↓
Partition
  ↓
PV
  ↓
VG
  ↓
LV
  ↓
Filesystem
  ↓
Mount Point

The most important commands are:

# Physical Volumes
sudo pvcreate /dev/sdb1
sudo pvs
sudo pvdisplay

# Volume Groups
sudo vgcreate vg_data /dev/sdb1
sudo vgs
sudo vgdisplay

# Logical Volumes
sudo lvcreate -L 100G -n lv_data vg_data
sudo lvs
sudo lvdisplay

# Filesystem
sudo mkfs.ext4 /dev/vg_data/lv_data

# Mount
sudo mkdir -p /mnt/data
sudo mount /dev/vg_data/lv_data /mnt/data

The key idea is that LVM separates physical storage from logical storage.

Once this concept is understood, commands such as pvcreate, vgcreate, and lvcreate become parts of one logical process rather than unrelated commands.

Replacing a Physical Disk with pvmove

One of the useful features of LVM is the ability to move data from one Physical Volume to another.

This can be useful when:

  • a disk needs to be replaced
  • a disk is showing signs of failure
  • a larger disk is being introduced
  • a disk needs to be removed from a Volume Group
  • storage needs to be reorganized

The key command for this operation is:

pvmove

pvmove moves allocated Physical Extents from one Physical Volume to another.

Important: pvmove is not a replacement for RAID or backups. If a disk has already completely failed and the data on it is inaccessible, pvmove cannot recover that data.

The Basic Idea

Imagine a Volume Group containing two Physical Volumes:

VG: vg_data
│
├── /dev/sdb1
│
└── /dev/sdc1

If /dev/sdb needs to be replaced, we first add a new Physical Volume:

/dev/sdb1    old disk
/dev/sdc1    existing disk
/dev/sdd1    new disk

The goal is:

Before:

VG: vg_data
│
├── /dev/sdb1  ← old disk
└── /dev/sdc1


After:

VG: vg_data
│
├── /dev/sdc1
└── /dev/sdd1  ← new disk

The data previously stored on /dev/sdb1 is moved to /dev/sdd1.

Important Requirement

The destination Physical Volume must have enough free space to hold the allocated extents from the source Physical Volume.

For example:

Old PV:
Size: 1 TB
Used: 600 GB

New PV:
Size: 700 GB
Free: 700 GB

This can be sufficient because only the allocated 600 GB needs to be moved.

Example Environment

Assume the current system contains:

/dev/sdb1
/dev/sdc1

inside:

vg_data

We want to replace:

/dev/sdb

with:

/dev/sdd

The new disk will eventually become:

/dev/sdd1

Step 1: Check the Current LVM Configuration

List Physical Volumes:

sudo pvs

Example:

PV         VG       Fmt  Attr PSize   PFree
/dev/sdb1  vg_data  lvm2 a--  931.00g  50.00g
/dev/sdc1  vg_data  lvm2 a--  931.00g 400.00g

Check the Volume Group:

sudo vgs

Check the Logical Volumes:

sudo lvs

For more detailed Physical Volume information:

sudo pvdisplay

Step 2: Prepare the New Disk

Identify the new disk:

lsblk

Example:

NAME        SIZE TYPE
sdb         931G disk
└─sdb1      931G part
sdc         931G disk
└─sdc1      931G part
sdd           1T disk

In this example:

/dev/sdd

is the new disk.

WARNING: Always verify the device name before partitioning. Selecting the wrong disk can destroy existing data.

Step 3: Create a Partition on the New Disk

Using parted:

sudo parted /dev/sdd

Inside parted:

mklabel gpt
mkpart primary 0% 100%
set 1 lvm on
print
quit

The new partition should now be:

/dev/sdd1

Verify it:

lsblk

Step 4: Create a Physical Volume

Initialize the new partition:

sudo pvcreate /dev/sdd1

Verify:

sudo pvs

The new PV should appear without a Volume Group initially.

Step 5: Add the New PV to the Volume Group

Add /dev/sdd1 to vg_data:

sudo vgextend vg_data /dev/sdd1

Verify:

sudo vgs
sudo pvs

The Volume Group now contains three Physical Volumes:

VG: vg_data
│
├── /dev/sdb1  ← old PV
├── /dev/sdc1
└── /dev/sdd1  ← new PV

Step 6: Move the Data with pvmove

Move the allocated extents from the old PV to the new PV:

sudo pvmove /dev/sdb1 /dev/sdd1

This tells LVM to move allocated Physical Extents from /dev/sdb1 to /dev/sdd1.

The operation can take significant time depending on:

  • amount of data
  • disk speed
  • storage type
  • system load

The Logical Volumes can generally remain online while the move is performed.

You can also let LVM select suitable free space automatically:

sudo pvmove /dev/sdb1

When replacing a specific disk, explicitly specifying the destination is often clearer:

sudo pvmove /dev/sdb1 /dev/sdd1

Step 7: Verify That the Old PV Is Empty

After pvmove completes:

sudo pvs

The old PV should show no allocated space.

For example:

PV         VG       PSize   PFree
/dev/sdb1  vg_data  931.00g 931.00g
/dev/sdc1  vg_data  931.00g 400.00g
/dev/sdd1  vg_data  931.00g 931.00g

The important part is:

/dev/sdb1
PFree = PSize

You can also check:

sudo pvdisplay /dev/sdb1

Step 8: Remove the Old PV from the Volume Group

Once the old PV is completely empty:

sudo vgreduce vg_data /dev/sdb1

Verify:

sudo pvs

The old /dev/sdb1 should no longer belong to vg_data.

Step 9: Remove LVM Metadata

Remove the LVM metadata from the old PV:

sudo pvremove /dev/sdb1

Verify:

sudo pvs

Remove partition and LVM set bit via parted or fdisk - completely clear the disk

The old disk can now be removed from the system.

Step 10: Physically Replace the Disk

The old disk:

/dev/sdb

can now be physically removed.

The resulting architecture is:

Before:

/dev/sdb1 ──┐
             │
/dev/sdc1 ──┼── VG: vg_data
             │
/dev/sdd1 ──┘


After:

/dev/sdc1 ──┐
             ├── VG: vg_data
/dev/sdd1 ──┘

The Logical Volumes remain part of the same Volume Group.

Complete pvmove Workflow

1. Identify the old PV
        │
        ▼
2. Add the replacement disk - if it is possible. If not start with pvmove and removal procedure of old disk first and replace new 
        │
        ▼
3. Partition the new disk
        │
        ▼
4. pvcreate /dev/sdd1
        │
        ▼
5. vgextend vg_data /dev/sdd1
        │
        ▼
6. pvmove /dev/sdb1 /dev/sdd1
        │
        ▼
7. Verify /dev/sdb1 is empty
        │
        ▼
8. vgreduce vg_data /dev/sdb1
        │
        ▼
9. pvremove /dev/sdb1
        │
        ▼
10. Remove the old disk

The key commands are:

sudo pvcreate /dev/sdd1
sudo vgextend vg_data /dev/sdd1
sudo pvmove /dev/sdb1 /dev/sdd1
sudo pvs
sudo vgreduce vg_data /dev/sdb1
sudo pvremove /dev/sdb1

What If the New Disk Is Larger?

The replacement disk does not need to have exactly the same size.

For example:

Old disk: 1 TB
New disk: 2 TB

After the move, the additional capacity becomes available in the Volume Group.

Check it with:

sudo vgs

The additional free space can then be used to extend existing Logical Volumes or create new ones.

What If the New Disk Is Smaller?

The replacement disk can potentially be smaller than the original disk, but only if it has enough free capacity for the data currently allocated on the old PV.

For example:

Old PV:
1 TB total
300 GB allocated

New PV:
500 GB total
500 GB free

This can work because only approximately 300 GB needs to be moved.

Check the current usage with:

sudo pvs

and:

sudo pvdisplay

What If the Disk Has Already Failed?

pvmove works only while the source PV is accessible.

If /dev/sdb has completely failed:

/dev/sdb
    X

LVM cannot read the extents stored on it.

In that situation, pvmove cannot simply recover the missing data.

Recovery depends on the LVM configuration, redundancy, filesystem, backups, and the nature of the disk failure.

LVM is not a backup solution.

LVM by itself does not provide protection against complete disk failure.

RAID is a separate technology designed to provide storage redundancy.

Important Safety Considerations

Before performing a disk replacement:

Verify the Source

Make sure that:

/dev/sdb1

is the PV you want to evacuate.

Use:

sudo pvs
sudo pvdisplay

Verify the Destination

Make sure the destination PV has enough free space:

sudo pvs

Do Not Remove the PV Before pvmove

The correct order is:

pvmove
   ↓
verify
   ↓
vgreduce
   ↓
pvremove

Do not remove the PV from the Volume Group while it still contains allocated extents.

Have a Backup

Even when using pvmove, maintain backups of important data.

A disk replacement is a storage operation with real risk.

Visual Summary

BEFORE

/dev/sdb1 ───────────┐
                     │
/dev/sdc1 ───────────┼── VG: vg_data
                     │
                     └── Logical Volumes


ADD NEW DISK

/dev/sdb1 ───────────┐
/dev/sdc1 ───────────┼── VG: vg_data
/dev/sdd1 ───────────┘


PVMOVE

/dev/sdb1 ────────────────┐
                          │
                     pvmove
                          │
                          ▼
                    /dev/sdd1


AFTER

/dev/sdc1 ───────────┐
                     ├── VG: vg_data
/dev/sdd1 ───────────┘
                     │
                     └── Logical Volumes

/dev/sdb1 → removed

The important concept is:

pvmove

moves the data allocated on a Physical Volume.

The Volume Group and Logical Volumes can remain in place while the underlying Physical Volume is evacuated.

Key Takeaways

The most important commands for replacing a healthy LVM disk are:

sudo pvcreate /dev/sdd1
sudo vgextend vg_data /dev/sdd1
sudo pvmove /dev/sdb1 /dev/sdd1
sudo pvs
sudo vgreduce vg_data /dev/sdb1
sudo pvremove /dev/sdb1

The conceptual workflow is:

New Disk
   ↓
Partition
   ↓
PV
   ↓
Add PV to VG
   ↓
pvmove
   ↓
Verify old PV is empty
   ↓
Remove old PV from VG
   ↓
Remove LVM metadata
   ↓
Replace old disk

This is one of the practical reasons LVM is useful in Linux infrastructure: a healthy Physical Volume can be evacuated and removed from a Volume Group without rebuilding the Logical Volumes from scratch.

Guide: Creating an Encrypted LVM Volume using LUKS

This guide covers how to isolate a disk partition, encrypt it using LUKS, set up an LVM structure inside the encrypted container, and manage its state (locking and unlocking).


Part 1: Initializing and Encrypting the Drive

Step 1: Remove the partition from the old Volume Group

If the partition (e.g., /dev/sdb2) is currently part of an active unencrypted Volume Group, it must be completely removed first.

sudo vgreduce testgroup /dev/sdb2
sudo pvremove /dev/sdb2

Step 2: Format the partition with LUKS Encryption

This step initializes the encryption layer. You will be prompted to type YES (must be uppercase) and enter a secure passphrase. Warning: If you lose this passphrase, your data cannot be recovered.*

sudo cryptsetup luksFormat /dev/sdb2

Step 3: Open (Unlock) the Encrypted Container

Before you can create layout partitions or file systems, you must unlock the device. This creates a virtual decrypted mapping under /dev/mapper/sdb2_encrypted.

sudo cryptsetup luksOpen /dev/sdb2 sdb2_encrypted

Part 2: Configuring LVM Inside the Encrypted Container

Step 4: Create Physical Volume, Volume Group, and Logical Volume

Now we treat the open decrypted container as a raw device and build the LVM architecture on top of it.

sudo pvcreate /dev/mapper/sdb2_encrypted
sudo vgcreate vg_secure /dev/mapper/sdb2_encrypted
sudo lvcreate -l +100%FREE -n lv_secret vg_secure

Step 5: Create File System and Mount

Format your new secure logical volume with the ext4 file system and mount it to your desired directory.

sudo mkfs.ext4 /dev/vg_secure/lv_secret
sudo mkdir -p /mnt/secure_data
sudo mount /dev/vg_secure/lv_secret /mnt/secure_data

At this stage, you can safely write data into /mnt/secure_data. Everything is automatically encrypted on the fly.


Part 3: Management and Maintenance

How to Safely Lock the Vault (e.g., before shutting down)

To lock the drive and hide your data, unmount the file system, deactivate the inner Volume Group, and close the LUKS mapper device.

sudo umount /mnt/secure_data
sudo vgchange -an vg_secure
sudo cryptsetup luksClose sdb2_encrypted

How to Unlock and Remount the Vault

Whenever you boot the computer and need access to your files again, run the following sequence to supply your passphrase and restore the mounts:

sudo cryptsetup luksOpen /dev/sdb2 sdb2_encrypted
sudo vgchange -ay vg_secure
sudo mount /dev/vg_secure/lv_secret /mnt/secure_data

Verification

To check your active layout and verify that the encryption container is properly recognized by the kernel, run:

lsblk -f

(You will see a tree-like hierarchy showing sdb2 -> type crypt -> vg_secure-lv_secret -> mounted on /mnt/secure_data)