LVM硬盘移除与缩容方法

2026-04-01 21:31:00
丁国栋
原创 6
摘要:本文记录和介绍如何将Linux的LVM缩容。

LVM硬盘移除与缩容方法

现在有一台云服务器,上面有多个硬盘组成的lvm,现在文件系统的空间使用率非常低。文件系统空间大小4.4T实际使用636G。现在需要将一些不再使用的硬盘从lvm中移除。应该如何做?

这是一个典型的 LVM 缩容与物理卷(PV)移除需求。由于你提到“文件系统空间使用率非常低”,这通常意味着数据已经集中迁移或删除,重点在于安全地释放物理设备

重要警告:LVM 缩容(特别是涉及物理盘移除)是高风险操作。请务必在操作前对重要数据进行完整备份,并在测试环境验证流程。


一、 操作前:关键信息确认

在执行任何命令前,请先通过以下命令摸清家底,记录下关键信息(如 VG 名、PV 路径、LV 名):

  1. 查看物理卷(PV)状态:确认哪些 PV 属于该 VG,以及它们的使用情况。

    pvs
  2. 查看卷组(VG)详情:确认 VG 名称、总大小、空闲空间。

    vgs
    vgdisplay <你的VG名称>
  3. 查看逻辑卷(LV)详情:确认 LV 名称、路径(如 /dev/mapper/vg0-lv_data)及挂载点。

    lvs
    lvdisplay <你的VG名称>
    df -hT  # 确认文件系统类型和挂载点
  4. 确认文件系统:你提到“文件系统空间大小 4.4T”,这通常是 xfsext4这一步至关重要,因为 xfs 不支持在线缩容,而 ext4 支持

    df -hT | grep /dev/mapper

二、 场景一:ext4 文件系统(相对简单,支持在线缩容)

如果你的文件系统是 ext4,操作流程相对直接,可以在线操作。

操作流程

  1. 卸载文件系统(可选,但更安全) 如果业务允许,建议卸载。如果必须在线操作,跳过此步,但风险增加。

    umount /你的/挂载点
  2. 检查文件系统(强制步骤)

    e2fsck -f /dev/你的VG/你的LV
  3. 缩小文件系统(必须先于LV缩容) 将文件系统缩小到略小于你最终目标的大小(例如你目标留 1T,这里缩到 900G,留点缓冲)。

    resize2fs /dev/你的VG/你的LV 900G
  4. 缩小逻辑卷(LV)

    lvreduce -L 1T /dev/你的VG/你的LV

    注意:resize2fslvreduce 的顺序不能反,且 lvreduce 的大小不能小于当前文件系统占用。

  5. 再次调整文件系统以填满LV

    resize2fs /dev/你的VG/你的LV
  6. 重新挂载(如果卸载了)

    mount /dev/你的VG/你的LV /你的/挂载点
  7. 从卷组中移除空闲的PV 现在 VG 中应该有大量空闲空间,你可以将不再使用的物理卷移出。

    vgreduce <你的VG名称> /dev/sdX  # /dev/sdX 是你要移除的硬盘
  8. 移除物理卷头(可选) 如果确定该硬盘不再用于 LVM,可以抹掉 PV 标签。

    pvremove /dev/sdX

实际操作

[z@backup:~$] df -h | grep -vP '(tmpfs|overlay|shm|kubelet|efivarfs|loop|snap|udev)'
Filesystem            Size  Used Avail Use% Mounted on
/dev/vda1              40G   29G  8.3G  78% /
/dev/mapper/vg01-pm1  4.4T  636G  3.6T  15% /home/data
cgmfs                 100K     0  100K   0% /run/cgmanager/fs
[z@backup:~$]
[z@backup:~$] sudo lsof|grep /home/data
[z@backup:~$] cat /etc/fstab
# # /etc/fstab: static file system information.
# #
# # Use 'blkid' to print the universally unique identifier for a
# # device; this may be used with UUID= as a more robust way to name devices
# # that works even if disks are added and removed. See fstab(5).
# #
# # <file system> <mount point>   <type>  <options>       <dump>  <pass>
# # / was on /dev/sda1 during installation
# UUID=fe5d9ef3-0382-4b4d-9057-f09962f7d00d /                          ext4    errors=remount-ro 0       1
# UUID=175bf173-8178-4488-b85c-13b44e2068ad /home/data                 ext4    errors=remount-ro 0       1
# UUID=ee937963-6266-4d99-95cf-3831fd297c33 /home/data1                ext4    errors=remount-ro 0       1
#
# # swap was on /dev/sdb1 during installation
# LABEL=YUNIFYSWAP none            swap    sw              0       0
# Above content backup at 2024-09-02 16:49:52
# /etc/fstab: static file system information.
#
# Use 'blkid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
# <file system> <mount point>   <type>  <options>       <dump>  <pass>
# / was on /dev/sda1 during installation
UUID=fe5d9ef3-0382-4b4d-9057-f09962f7d00d /               ext4    errors=remount-ro 0       1
# swap was on /dev/sdb1 during installation
LABEL=YUNIFYSWAP none            swap    sw              0       0
#UUID=175bf173-8178-4488-b85c-13b44e2068ad /home/data                 ext4    errors=remount-ro 0       1
UUID=ee937963-6266-4d99-95cf-3831fd297c33 /home/data                ext4    errors=remount-ro 0       1
[z@backup:~$] sudo umount /home/data
[z@backup:~$] e2fsck -f /dev/mapper/
control   vg01-pm1
[z@backup:~$] sudo e2fsck -f /dev/mapper/vg01-pm1
e2fsck 1.44.1 (24-Mar-2018)
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/vg01-pm1: 4073384/294912000 files (0.2% non-contiguous), 185015801/1179640832 blocks
[z@backup:~$] sudo resize2fs /dev/mapper/vg01-pm1 900G
resize2fs 1.44.1 (24-Mar-2018)
Resizing the filesystem on /dev/mapper/vg01-pm1 to 235929600 (4k) blocks.
The filesystem on /dev/mapper/vg01-pm1 is now 235929600 (4k) blocks long.
[z@backup:~$]
z@backup:~$] sudo vgs
  VG   #PV #LV #SN Attr   VSize VFree
  vg01   7   1   0 wz--n- 4.39t 3.39t
[z@backup:~$] sudo vgreduce vg01 /dev/vdi
  Removed "/dev/vdi" from volume group "vg01"
[z@backup:~$] udevadm info --query=all --name=/dev/vdi
P: /devices/pci0000:00/0000:00:0d.0/virtio9/block/vdi
N: vdi
S: disk/by-id/lvm-pv-uuid-970nAu-hSeE-HKbb-Ei62-3dvu-7S1E-QAAn8K
S: disk/by-id/virtio-vos-10dohijl
S: disk/by-path/pci-0000:00:0d.0
S: disk/by-path/virtio-pci-0000:00:0d.0
E: DEVLINKS=/dev/disk/by-path/virtio-pci-0000:00:0d.0 /dev/disk/by-id/lvm-pv-uuid-970nAu-hSeE-HKbb-Ei62-3dvu-7S1E-QAAn8K /dev/disk/by-id/virtio-vos-10dohijl /dev/disk/by-path/pci-0000:00:0d.0
E: DEVNAME=/dev/vdi
E: DEVPATH=/devices/pci0000:00/0000:00:0d.0/virtio9/block/vdi
E: DEVTYPE=disk
E: ID_FS_TYPE=LVM2_member
E: ID_FS_USAGE=raid
E: ID_FS_UUID=970nAu-hSeE-HKbb-Ei62-3dvu-7S1E-QAAn8K
E: ID_FS_UUID_ENC=970nAu-hSeE-HKbb-Ei62-3dvu-7S1E-QAAn8K
E: ID_FS_VERSION=LVM2 001
E: ID_MODEL=LVM PV 970nAu-hSeE-HKbb-Ei62-3dvu-7S1E-QAAn8K on /dev/vdi
E: ID_PATH=pci-0000:00:0d.0
E: ID_PATH_TAG=pci-0000_00_0d_0
E: ID_SERIAL=vos-10dohijl
E: MAJOR=252
E: MINOR=128
E: SUBSYSTEM=block
E: SYSTEMD_ALIAS=/dev/block/252:128
E: SYSTEMD_READY=1
E: SYSTEMD_WANTS=lvm2-pvscan@252:128.service
E: TAGS=:systemd:
E: USEC_INITIALIZED=7238811
[z@backup:~$] sudo pvremove /dev/vdi
  Labels on physical volume "/dev/vdi" successfully wiped.
[z@backup:~$]
[z@backup:~$] sudo vgreduce vg01 /dev/vdg
  Physical volume "/dev/vdg" still in use
[z@backup:~$] sudo pvmove /dev/vdg
  /dev/vdg: Moved: 0.00%
  /dev/vdg: Moved: 0.08%
  /dev/vdg: Moved: 0.17%
  /dev/vdg: Moved: 0.26%
  /dev/vdg: Moved: 0.34%
  /dev/vdg: Moved: 0.43%
  /dev/vdg: Moved: 0.51%
  /dev/vdg: Moved: 0.58%
  /dev/vdg: Moved: 0.65%
  /dev/vdg: Moved: 0.74%
  ...
  /dev/vdg: Moved: 100.00%
[z@backup:~$]

执行 vgreduce vg01 /dev/vdg 时提示 Physical volume "/dev/vdg" still in use 这个报错意味着 /dev/vdg 这个物理卷(PV)上仍有数据(即逻辑卷的物理盘区),LVM 出于保护机制拒绝直接移除。你需要先通过数据迁移(pvmove)把这块硬盘上的数据清空,才能安全移除。


一、 为什么报错?

LVM 的底层逻辑是:数据是分散在多个 PV 上的。即使文件系统使用率低,数据也可能恰好分布在你想要移除的这块盘上。

当前状态

  • 卷组(VG)vg01 中,PV /dev/vdg仍包含活跃的逻辑卷(LV)数据
  • 直接 vgreduce 相当于“抽掉地基”,会导致数据丢失,因此被 LVM 阻止。

二、 解决方案:使用 pvmove 迁移数据

核心思路:将 /dev/vdg 上的数据块全部搬移到 VG 内的其他空闲硬盘上,使其变为“空闲 PV”,再移除。

1. 检查 PV 使用情况

先确认 /dev/vdg 是否真的被占用,以及是否有其他空闲 PV 可以接收数据。

sudo pvs -o+pv_used

输出示例:

 PV         VG   Fmt  Attr PSize  PFree  Used
  /dev/vdb  vg01 lvm2 a--  1.00t  1.00t    0
  /dev/vdc  vg01 lvm2 a--  1.00t  500g   500g
  /dev/vdg  vg01 lvm2 a--  1.00t  200g   800g  <-- 这个 Used 不为 0

2. 执行数据迁移(关键步骤)

使用 pvmove 命令将数据从 /dev/vdg 搬走。确保 VG 内有其他 PV 且有足够空闲空间

# 将 /dev/vdg 上的所有数据迁移到 VG 内的其他 PV
sudo pvmove /dev/vdg

命令会显示进度,大硬盘耗时较长。如果只想迁到特定 PV(如 /dev/vdb),可用 sudo pvmove /dev/vdg /dev/vdb

3. 确认迁移完成

迁移完成后,再次检查状态,确认 /dev/vdgUsed 变为 0。

sudo pvs -o+pv_used

4. 移除 PV

此时数据已清空,可以安全移除。

sudo vgreduce vg01 /dev/vdg

5. 彻底清理(可选)

如果该硬盘不再用于 LVM,移除 PV 标签。

sudo pvremove /dev/vdg

三、 如果迁移失败(无空闲空间)

如果你执行 pvmove 时提示 Insufficient free space,说明 VG 内其他 PV 没有足够空间接收 /dev/vdg 上的数据。此时你有两个选择:

方案 A:先缩容文件系统(释放空间)

如果你文件系统确实只用了 636G,但 LV 分配了 4.4T,可以先缩小 LV 和文件系统(参考之前的 ext4/xfs 流程),腾出 VG 空闲空间,再进行 pvmove

方案 B:添加临时硬盘

在云平台挂载一块临时云盘,将其加入 VG 作为“中转站”。

# 假设新挂载的盘为 /dev/vdh
sudo pvcreate /dev/vdh
sudo vgextend vg01 /dev/vdh
sudo pvmove /dev/vdg /dev/vdh  # 迁移数据到临时盘
sudo vgreduce vg01 /dev/vdg    # 移除旧盘
# 之后若需回收临时盘,再反向操作 pvmove 回来并移除

四、 风险提示

  1. 数据安全pvmove 是底层数据搬运,操作前务必对重要数据做备份或云盘快照
  2. 业务影响:迁移过程中 I/O 压力较大,建议在业务低峰期操作。
  3. 云环境:如果是云服务器,移除 PV 后记得去云控制台卸载云盘,否则可能继续计费。
[z@backup:~$] sudo pvs -o+pv_used
  PV         VG   Fmt  Attr PSize    PFree    Used
  /dev/vdc   vg01 lvm2 a--  <500.00g       0  <500.00g
  /dev/vdd   vg01 lvm2 a--  <200.00g   75.99g  124.00g
  /dev/vde   vg01 lvm2 a--  <500.00g <500.00g       0
  /dev/vdf   vg01 lvm2 a--  <500.00g <500.00g       0
  /dev/vdg   vg01 lvm2 a--  <900.00g       0  <900.00g
  /dev/vdh   vg01 lvm2 a--  <500.00g <100.00g  400.00g
[z@backup:~$]
[z@backup:~$] sudo pvs -o+pv_used
  PV         VG   Fmt  Attr PSize    PFree    Used
  /dev/vdc   vg01 lvm2 a--  <500.00g       0  <500.00g
  /dev/vdd   vg01 lvm2 a--  <200.00g   75.99g  124.00g
  /dev/vde   vg01 lvm2 a--  <500.00g <500.00g       0
  /dev/vdf   vg01 lvm2 a--  <500.00g <500.00g       0
  /dev/vdg   vg01 lvm2 a--  <900.00g       0  <900.00g
  /dev/vdh   vg01 lvm2 a--  <500.00g <100.00g  400.00g
[z@backup:~$]  sudo vgreduce vg01 /dev/vde
  Removed "/dev/vde" from volume group "vg01"
[z@backup:~$]  sudo vgreduce vg01 /dev/vdf
  Removed "/dev/vdf" from volume group "vg01"
[z@backup:~$] sudo pvremove /dev/vde
  Labels on physical volume "/dev/vde" successfully wiped.
[z@backup:~$] sudo pvremove /dev/vdf
  Labels on physical volume "/dev/vdf" successfully wiped.
[z@backup:~$]
[z@backup:~$] udevadm info --query=all --name=/dev/vde |grep ID_SERIAL
E: ID_SERIAL=vos-x2qv6vg9
[z@backup:~$] udevadm info --query=all --name=/dev/vdf |grep ID_SERIAL
E: ID_SERIAL=vos-iwi6o9zu
[z@backup:~$]

三、 场景二:xfs 文件系统(不支持在线缩容,需迁移数据)

XFS 不支持缩小! 这是很多人的误区。你不能直接对已挂载的 XFS 执行 xfs_growfs 缩容。唯一安全的方法是:创建新LV -> 迁移数据 -> 替换。

操作流程

  1. 创建新的、小容量的 LV 利用你 VG 中空闲的 PV(或者确保有足够空间)创建一个新的 LV,大小为你需要的目标大小(如 1T)。

    lvcreate -L 1T -n lv_new <你的VG名称>
  2. 在新 LV 上创建文件系统

    mkfs.xfs /dev/你的VG/lv_new
  3. 挂载新 LV 并迁移数据

    mkdir /mnt/new
    mount /dev/你的VG/lv_new /mnt/new
    rsync -avP /原挂载点/ /mnt/new/  # 使用 rsync 同步数据
  4. 切换挂载点 确认数据同步无误后(diff 检查),停服(如果是在线业务),然后切换挂载点。

    umount /原挂载点
    umount /mnt/new
    mount /dev/你的VG/lv_new /原挂载点
  5. 删除旧 LV 并释放 PV 确认业务运行正常后,删除旧的大 LV,此时 VG 空间释放,可以移除旧的 PV。

    lvremove /dev/你的VG/lv_old
    vgreduce <你的VG名称> /dev/sdX  # 移除不再使用的硬盘

四、 关键风险点与建议

  1. 备份!备份!备份!:误操作可能导致数据丢失,云服务器建议先打快照。
  2. 确认文件系统类型xfsext4 的缩容策略完全不同,切勿混淆。
  3. 顺序不能错:ext4 必须是 fsck -> resize2fs -> lvreduce
  4. 预留缓冲空间:缩容时不要卡着 636G 用,建议预留 20%-30% 的缓冲空间。
  5. 云盘注意事项:如果是云硬盘(如阿里云、腾讯云),移除 PV 后,记得在云控制台卸载云盘,否则可能继续计费。
发表评论
博客分类