线上磁盘满了是生产环境最常见的问题之一。新建目录不行、写入失败、MySQL 启动报错 No space left on device,第一反应是 df -h 看哪个分区满了。但如果这个分区是 LVM 管理的逻辑卷,那么扩容的路径并不是"加一块盘、mkfs、mount"这么简单,而是要把新盘做成 PV,加入 VG,再扩展 LV,最后扩展文件系统。
很多初中级运维卡在 LVM 这一步:
lvextend 和 resize2fs/xfs_growfs 的关系这一篇把 LVM 从入门到熟练,把扩容、缩容、迁移、快照、备份全部讲透,配合命令实战和回滚脚本。
LVM(Logical Volume Manager)逻辑卷管理,在物理磁盘和文件系统之间引入三层抽象:
类比:
LV 的大小 = LE 数量 × PE 大小。
每个 VG、LV、PV 都有自己的元数据,记录在 /etc/lvm/backup/ 和 /etc/lvm/archive/。
/etc/lvm/backup/
:最近的元数据备份/etc/lvm/archive/
:历史元数据备份pvcreate
、pvs、pvdisplay、pvscan、pvremove、pvmovevgcreate
、vgs、vgdisplay、vgscan、vgremove、vgextend、vgreduce、vgcfgbackup、vgcfgrestorelvcreate
、lvs、lvdisplay、lvscan、lvremove、lvextend、lvreduce、lvrename、lvresize、lvconvertlvchange
、vgchange、pvchangeLVM 可以和软 RAID 组合:
lvcreate -s -L 10G -n snap_lv /dev/vg0/lv0
快照是基于 COW(Copy-On-Write)实现的,适合备份场景。
LVM cache 用 SSD 给 HDD 做缓存:
lvcreate --type cache
/ lvconvert --type cacheLVM thin provision 按需分配空间:
lvcreate --type thin不同文件系统对 LV 的支持:
扩容的完整路径:
1. 检查现状:df -h、lsblk、pvs、vgs、lvs 2. 加盘或加分区:fdisk/parted 准备新 PV 3. 创建 PV:pvcreate /dev/sdX 4. 扩展 VG:vgextend vg0 /dev/sdX 5. 扩展 LV:lvextend -L +100G /dev/vg0/lv0 6. 扩展 FS:xfs_growfs /mount/point 或 resize2fs /dev/vg0/lv0 7. 验证:df -h 8. 备份元数据:vgcfgbackup 每一步都有回滚预案,不能盲跑。
df -h Filesystem Size Used Avail Use% Mounted on /dev/mapper/centos-root 50G 48G 2.0G 96% / /dev/mapper/vg0-data 100G 95G 5.0G 95% /data 判断:/data 用了 95%,需要扩容。
bash
pvs vgs lvs 预期输出:
pvs: PV VG Fmt Attr PSize PFree /dev/sda2 centos lvm2 a-- 99.51g 9.51g /dev/sdb1 vg0 lvm2 a-- 200.00g 100.00g vgs: VG #PV #LV #SN Attr VSize VFree centos 1 2 0 wz--n- 99.51g 9.51g vg0 1 1 0 wz--n- 200.00g 100.00g lvs: LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert data vg0 -wi-ao---- 100.00g 判断:/data 对应 vg0/data,VG 还有 100G 空闲。
直接扩展 LV:
bash
lvextend -L +50G /dev/vg0/data 或:
bash
lvextend -l +100%FREE /dev/vg0/data
判断:+100%FREE 利用所有 VG 空闲。
扩展后文件系统同步:
bash
# XFS xfs_growfs /data # ext4 resize2fs /dev/vg0/data bash
df -h /data 预期:
Filesystem Size Used Avail Use% Mounted on /dev/mapper/vg0-data 150G 95G 55G 63% /data 判断:扩容生效。
bash
vgcfgbackup vg0 bash
echo 1 > /sys/class/scsi_host/host0/scan lsblk 判断:/dev/sdc 出现。
用 parted 或 fdisk:
bash
parted /dev/sdc mklabel gpt parted /dev/sdc mkpart primary 0% 100% 或:
bash
fdisk /dev/sdc # n, p, 1, Enter, Enter, t, 8e, w 判断:分区类型是 8e(Linux LVM)。
bash
pvcreate /dev/sdc1 pvs 预期:/dev/sdc1 加入。
bash
vgextend vg0 /dev/sdc1 vgs 预期:vg0 的 VFree 增加。
bash
lvextend -L +200G /dev/vg0/data xfs_growfs /data df -h /data bash
vgcfgbackup vg0 只有同 VG 内 LV 可以调整。多 VG 之间需要 pvmove:
bash
pvmove -n /dev/vg0/data /dev/sdc1 或把整个 PV 数据迁到另一个 PV:
bash
pvmove /dev/sdc1 /dev/sdd1 判断:pvmove 是耗时的 IO 操作,要在低峰跑。
根分区扩容比较复杂,因为根分区不能直接 umount。需要:
vgchange -ay或:
lvextend --resizefs 自动扩展bash
lvextend --resizefs -L +10G /dev/centos/root 判断:–resizefs 是 RHEL/CentOS 7+ 才支持。
缩容只在 ext4 文件系统下支持,xfs 不支持。
缩容前必须备份:
bash
cp -a /data /backup/data.$(date +%F) 或:
bash
rsync -a /data/ /backup/data/ bash
umount /data bash
e2fsck -f /dev/vg0/data bash
resize2fs /dev/vg0/data 80G bash
lvreduce -L 80G /dev/vg0/data 判断:lvreduce 必须大于等于 FS 大小。
bash
mount /data df -h /data 如果 LV 是 xfs 文件系统,缩容前必须:
lvremove /dev/vg0/datalvcreate -L 80G -n data vg0mkfs.xfs /dev/vg0/datamount /dev/vg0/data /datarsync -a /backup/data/ /data/判断:xfs 缩容只能"重做",不像 ext4 可以 in-place 缩。
bash
pvcreate /dev/sdd1 vgextend vg0 /dev/sdd1 bash
pvmove /dev/sdc1 /dev/sdd1 判断:pvmove 是 in-place 迁移,不影响业务。
bash
vgreduce vg0 /dev/sdc1 pvremove /dev/sdc1 bash
pvs df -h /data bash
lvcreate -s -L 10G -n data_snap /dev/vg0/data 判断:快照大小根据数据变化率定,建议 10-20%。
bash
mkdir /mnt/snap mount /dev/vg0/data_snap /mnt/snap bash
rsync -a /mnt/snap/ /backup/data/$(date +%F)/ 或:
bash
tar czf /backup/data.$(date +%F).tgz -C /mnt/snap . bash
umount /mnt/snap lvremove /dev/vg0/data_snap 判断:快照占用空间随数据变化增长,超出会自动失效。
bash
#!/bin/bash # lv-snapshot.sh set -euo pipefail DATE=$(date +%F_%H%M%S) LV_PATH=/dev/vg0/data SNAP_SIZE=10G SNAP_NAME=data_snap_$DATE BACKUP_DIR=/backup/data/$DATE lvcreate -s -L $SNAP_SIZE -n $SNAP_NAME $LV_PATH mkdir -p /mnt/snap mount /dev/vg0/$SNAP_NAME /mnt/snap mkdir -p $BACKUP_DIR rsync -a /mnt/snap/ $BACKUP_DIR/ umount /mnt/snap lvremove -f /dev/vg0/$SNAP_NAME echo "snapshot $SNAP_NAME backed up to $BACKUP_DIR" bash
lvcreate -L 100G -n cache_meta vg0 /dev/sdc1 lvcreate -L 1T -n cache_data vg0 /dev/sdc1 bash
lvconvert --type cache --cachepool vg0/cache_data vg0/data bash
lvs -o +cache_total_blocks bash
lvconvert --splitcache vg0/data bash
lvcreate -L 100G --thinpool thin_pool vg0 bash
lvcreate -V 1T --thin -n thin_lv vg0/thin_pool 判断:thin LV 实际占用随数据增长,最大 1T。
bash
pvdisplay /dev/sdc1 判断:故障 PV 通常显示 missing。
bash
vgreduce --removemissing vg0 --force bash
pvcreate /dev/sdd1 vgextend vg0 /dev/sdd1 bash
cp /etc/lvm/backup/vg0 /etc/lvm/backup/vg0.bak bash
vgcfgrestore vg0 判断:从最近的备份恢复元数据。
bash
vgchange -ay vg0 在多路径环境下,LVM 可能识别到多个相同的 PV:
bash
multipath -ll pvscan 判断:每个 multipath 设备应该被 filter 掉。
修改 /etc/lvm/lvm.conf:
bash
filter = [ "a|/dev/mapper/mpath.*|", "r/.*/" ] 判断:白名单 multipath 设备,其他都过滤。
云服务器一般不直接用 LVM,但可以在 OS 内层做:
操作与本地一致。
bash
pvcreate /dev/sdc1 # 创建 PV pvs # 简略列出所有 PV pvdisplay # 详细列出 PV pvscan # 扫描 PV pvremove /dev/sdc1 # 删除 PV pvmove /dev/sdc1 # 移动 PV 数据 bash
vgcreate vg0 /dev/sdc1 # 创建 VG vgs # 简略列出 VG vgdisplay vg0 # 详细 vgscan # 扫描 vgextend vg0 /dev/sdd1 # 扩展 VG vgreduce vg0 /dev/sdc1 # 缩减 VG vgremove vg0 # 删除 VG vgcfgbackup vg0 # 备份元数据 vgcfgrestore vg0 # 恢复元数据 vgchange -ay vg0 # 激活 vgchange -an vg0 # 取消激活 bash
lvcreate -L 10G -n data vg0 # 创建 LV lvs # 简略列出 lvdisplay /dev/vg0/data # 详细 lvscan # 扫描 lvextend -L +10G /dev/vg0/data # 扩展 lvextend -l +100%FREE /dev/vg0/data # 用尽 VG 空闲 lvreduce -L 10G /dev/vg0/data # 缩减 lvremove /dev/vg0/data # 删除 lvrename vg0 data data_new # 改名 lvresize -L 20G /dev/vg0/data # 调整大小 bash
# ext4 resize2fs /dev/vg0/data e2fsck -f /dev/vg0/data mkfs.ext4 /dev/vg0/data # xfs xfs_growfs /data xfs_info /data mkfs.xfs /dev/vg0/data # 通用 blkid /dev/vg0/data fsck /dev/vg0/data bash
pvs -o +pv_used,pv_free vgs -o +vg_mda_count,vg_mda_size,vg_mda_free lvs -o +devices 判断:devices 列能看到 LV 由哪些 PV 组成。
bash
df -h /data df -i /data mount | grep /data findmnt /data bash
lsblk fdisk -l /dev/sdc parted /dev/sdc print bash
ls /etc/lvm/archive/ cat /etc/lvm/archive/vg0_00001.vg bash
vgchange -ay lvchange -ay /dev/vg0/data
LVM 通过文件锁避免并发操作,默认在 /run/lock/lvm/。
bash
# 默认配置 locking_dir = "/run/lock/lvm" backup_dir = "/etc/lvm/backup" archive_dir = "/etc/lvm/archive" use_lvmetad = 1 obtain_device_list_from_udev = 1 # 多路径 filter filter = [ "a|/dev/mapper/mpath.*|", "r/.*/" ] # 缓存设置 max_lv = 256 max_pv = 1024 # 锁类型 locking_type = 1 bash
activation { thin_pools = { vg0/thin_pool { activation_mode = "deferred" monitor = "y" } } } bash
auto_activation_volume_list = [ "vg0/data", "centos/root", "centos/swap" ] bash
#!/bin/bash # lvm-monitor.sh echo "=== PV ===" pvs --noheadings | awk '{print $1, $2, $6}' echo "=== VG ===" vgs --noheadings | awk '{print $1, $6, $7}' echo "=== LV ===" lvs --noheadings | awk '{print $1, $2, $4, $5}' echo "=== FS ===" df -h | grep -E '/dev/mapper' bash
# /etc/fstab /dev/mapper/vg0-data /data xfs defaults,noatime 0 2 判断:用 UUID 更可靠:
bash
blkid /dev/vg0/data bash
# /etc/systemd/system/data.mount [Unit] Description=Data mount Before=local-fs.target [Mount] What=/dev/vg0/data Where=/data Type=xfs Options=defaults,noatime [Install] WantedBy=multi-fs.target bash
# /etc/multipath.conf blacklist { devnode "^sda" } multipaths { multipath { wwid "3600508..." alias "mpath0" } } bash
# 元数据备份 backup { retain_min = 50 retain_days = 30 } # 全局过滤器 devices { filter = [ "a|/dev/sd.*|", "r|/dev/cdrom|" ] cache_dir = "/etc/lvm/cache" } # 日志 log { level = 1 file = "/var/log/lvm2.log" } bash
# /etc/udev/rules.d/99-lvm.rules KERNEL=="dm-*", SUBSYSTEM=="block", RUN+="/usr/sbin/lvm vgchange -ay --monitor y vg0" bash
#!/bin/bash # lvm-autoextend.sh set -euo pipefail VG=$1 LV=$2 FS_PATH=$3 INCREMENT=10G if [ "$(vgs --noheadings -o vg_free $VG | tr -d ' ')" != "0" ]; then lvextend -L +$INCREMENT /dev/$VG/$LV if mount | grep $FS_PATH | grep -q xfs; then xfs_growfs $FS_PATH else resize2fs /dev/$VG/$LV fi fi bash
tail -f /var/log/lvm2.log 判断:所有 LVM 操作都会留下日志。
bash
dmesg | grep -i lvm dmesg | grep -i dm- bash
journalctl -u lvm2-monitor bash
#!/bin/bash VG=vg0 LV=data vgfree=$(vgs --noheadings -o vg_free --units g $VG | tr -d ' g') lvsize=$(lvs --noheadings -o lv_size --units g $VG/$LV | tr -d ' g') if (( $(echo "$vgfree < 10" | bc -l) )); then echo "WARN: VG $VG free space < 10G" fi if (( $(echo "$lvsize > 900" | bc -l) )); then echo "WARN: LV $LV > 900G" fi bash
lvs -o +snap_percent 判断:snap_percent 100% 时快照失效。
bash
lvs -o +data_percent bash
pvs -o +pv_attr 判断:attr 第二位 = z 表示正常,m 表示 missing。
bash
dmsetup info /dev/vg0/data dmsetup ls dmsetup table /dev/vg0/data bash
vgscan pvscan lvscan 判断:扫描所有 LVM 元数据。
bash
pvdisplay vgreduce --removemissing vg0 --force bash
lvdisplay /dev/vg0/data fsck /dev/vg0/data bash
vgs # 看 VFree pvs # 看 PV 判断:VG 没有空闲。
bash
df -h /data mount | grep /data 判断:xfs_growfs 必须挂载在线,ext4 用 resize2fs。
bash
e2fsck -f /dev/vg0/data 判断:先 e2fsck 再 resize2fs。
bash
ps aux | grep lvm fuser /run/lock/lvm 判断:找出持锁进程。
bash
vgcfgrestore vg0 bash
vgchange -an vg0 判断:cluster 模式才有多机问题。
bash
iostat -xz 1 5 判断:可能需要 pvmove 整理数据分布。
lvremove /dev/vg0/data
:直接删除 LV,数据全丢vgremove vg0
:删除整个 VG,所有 LV 全丢lvreduce
:缩容 LV,数据丢失风险pvmove
:在生产环境跑,可能影响 IOresize2fs
:缩容时如果空间不够会失败xfs_growfs
:必须在挂载状态xfs
缩容:文件本身不支持vgcfgbackup
不备份:灾难恢复困难vgextend
加错盘:可能造成数据分布异常multipath filter
没配:可能识别到错误设备pvs
显示 missing:可能真盘有问题pvmove
中断:能恢复,但要小心lvcreate
不指定 VG:默认选 VG,可能选错lvextend -l +100%FREE
:可能扩展超过预期lvreduce
大于 FS:文件系统会损坏vgmerge
/ vgsplit:合并/拆分 VG,复杂操作pvmove:需要 clusterpvs
列出预期 PVvgs
列出预期 VG 和空闲lvs
列出预期 LVdf -h /data
大小符合预期mount
挂载点正确lvextend 后没有撤销命令,只能 lvreduce:
bash
umount /data e2fsck -f /dev/vg0/data resize2fs /dev/vg0/data 100G lvreduce -L 100G /dev/vg0/data mount /data bash
lvextend -L 200G /dev/vg0/data resize2fs /dev/vg0/data 判断:lvreduce 之前必须备份和 fsck。
bash
vgreduce vg0 /dev/sdc1 pvremove /dev/sdc1 bash
vgextend vg0 /dev/sdc1 bash
pvcreate /dev/sdc1 vgextend vg0 /dev/sdc1 pvmove 判断:先恢复元数据,再恢复数据。
快照删除后无法恢复,必须重新创建。
bash
lvremove /dev/vg0/data 如果 LV 还没真正删除:
bash
lvcreate -L 100G -n data vg0 xfs_growfs /data # 不需要重新 mkfs 判断:lvremove 之后除非有快照或备份,否则无法恢复。
bash
vgcfgrestore vg0 vgchange -ay vg0 bash
cp /etc/lvm/backup/vg0.bak /etc/lvm/backup/vg0 vgcfgrestore vg0 LVM 不是玄学,三层结构 + 几组命令就能搞定:
扩容场景:90% 是 vgextend + lvextend + xfs_growfs。
缩容场景:除非必要,不缩。XFS 缩容只能"重做"。
数据迁移:pvmove 是 in-place 迁移,不影响业务。
快照:基于 COW,是备份利器。
元数据:定期 vgcfgbackup,故障时 vgcfgrestore。
把这一篇收藏好,遇到 LVM 故障按章节走,比查 Google 高效得多。
bash
lvcreate --type raid1 -L 10G -n lv_raid1 vg0 判断:LVM 自带的软件 RAID,可与硬件 RAID 组合。
bash
lvs -o +data_percent 判断:data_percent 接近 100% 时需要扩容 thin pool。
bash
vgchange --monitor y vg0 判断:开启 D-Bus 监控,自动激活。
不建议同时用 LVM 和 ZFS,层叠复杂。
bash
cryptsetup luksFormat /dev/sdc1 cryptsetup open /dev/sdc1 sdc1_crypt pvcreate /dev/mapper/sdc1_crypt 判断:LUKS + LVM。
bash
dmsetup threshold /dev/vg0/data 0 100 判断:throttle IO。
bash
systemctl status lvm2-monitor yaml
- alert: VGAlmostFull expr: (node_lvm_vg_free_bytes / node_lvm_vg_size_bytes) < 0.1 LVM 快照是 XFS、ext4 文件系统备份的标准做法。
云盘通过多路径挂载后,可以加入 LVM。
某数据库服务器 /data 目录从 500G 涨到 480G(96%),报警。
bash
df -h /data pvs vgs lvs 判断:vg0 VFree=200G,可以直接扩展 LV。
bash
vgcfgbackup vg0 cp /etc/lvm/backup/vg0 /backup/lvm-backup-vg0-$(date +%F) bash
mysqldump --all-databases > /backup/db-$(date +%F).sql 判断:重要数据先备份。
bash
lvextend -l +100%FREE /dev/vg0/data bash
xfs_growfs /data bash
df -h /data bash
mysql -e "CREATE DATABASE test_lvm_expand;" mysql -e "USE test_lvm_expand; CREATE TABLE t (id INT);" mysql -e "DROP DATABASE test_lvm_expand;" 确认监控正常,告警恢复。
每周跑一遍:
bash
#!/bin/bash # lvm-audit.sh echo "=== PV ===" pvs --noheadings -o pv_name,vg_name,pv_size,pv_free,pv_attr echo "=== VG ===" vgs --noheadings -o vg_name,vg_size,vg_free,vg_attr echo "=== LV ===" lvs --noheadings -o lv_name,vg_name,lv_size,lv_attr echo "=== FS ===" df -h | grep -E '/dev/mapper' echo "=== LVM metadata backup ===" ls -lt /etc/lvm/backup/ | head echo "=== Multipath ===" multipath -ll echo "=== Filter ===" grep -E "^[[]]*filter" /etc/lvm/lvm.conf 判断:把脚本接入监控。
LVM 是运维基本功。三层结构、命令链、回滚预案、元数据备份,每个细节都要熟。把这一篇里的命令多跑几遍,遇到 LVM 故障按章节走,比临时查资料高效得多。
记住一句话:扩容有风险,操作前必须备份元数据。生产环境永远不要盲跑 lvreduce、lvremove 这种危险命令。
LVM 的元数据写在每个 PV 的开头,UUID 标识。VG 元数据会复制到所有 PV 上,保证冗余。
LVM 基于 Linux device-mapper,每个 LV 是一个 dm 设备:
bash
ls -la /dev/mapper/ ls -la /dev/vg0/ ls -la /dev/dm-* 判断:dm-0、dm-1 等是 device-mapper 设备。
bash
locking_type = 1 locking_type = 2 判断:集群 LVM 用 dlm,否则本地锁。
bash
lvchange -ay /dev/vg0/data lvchange -an /dev/vg0/data lvchange --refresh /dev/vg0/data bash
vgchange -s 8M vg0 判断:PE 大小影响最大 LV 数(65536 个 PE 是上限)。
PE=4M 时最大 LV = 256G PE=8M 时最大 LV = 512G PE=16M 时最大 LV = 1T PE=64M 时最大 LV = 4T
不同调度器对 LV 影响:
bash
echo none > /sys/block/dm-0/queue/scheduler bash
vgck vg0 lvck /dev/vg0/data 判断:校验元数据完整性。
LVM2 兼容 LVM1 格式,但部分高级特性需要新版本。RHEL/CentOS 7+ 默认 LVM2。
bash
lvcreate -L 500G -n mysql_data vg0 mkfs.xfs /dev/vg0/mysql_data mount /dev/vg0/mysql_data /var/lib/mysql 判断:把数据库放在独立 LV 上便于管理。
bash
lvcreate -s -L 50G -n mysql_snap /dev/vg0/mysql_data mount /dev/vg0/mysql_snap /mnt/snap rsync -a /mnt/snap/ /backup/mysql/ umount /mnt/snap lvremove -f /dev/vg0/mysql_snap 判断:快照备份比 mysqldump 完整。
bash
lvcreate -L 100G -n redis_data vg0 mkfs.xfs /dev/vg0/redis_data mount /dev/vg0/redis_data /var/lib/redis bash
lvcreate -L 200G -n pg_index vg0 mkdir /var/lib/pgsql/index mount /dev/vg0/pg_index /var/lib/pgsql/index sql
CREATE TABLESPACE ts_index LOCATION '/var/lib/pgsql/index'; CREATE INDEX idx_user ON users(id) TABLESPACE ts_index; bash
lvcreate -L 1T -n mongo_data vg0 mkfs.xfs /dev/vg0/mongo_data mount /dev/vg0/mongo_data /var/lib/mongo bash
lvcreate -L 5T -n es_data vg0 lvcreate -L 1T -n es_logs vg0 判断:数据和日志分开 LV。
bash
lvcreate -L 10T -n kafka_data vg0 mkfs.xfs /dev/vg0/kafka_data bash
lvconvert --merge /dev/vg0/mysql_snap 判断:merge 会自动恢复。
bash
lvcreate -L 1T -n docker_data vg0 mkfs.xfs /dev/vg0/docker_data mount /dev/vg0/docker_data /var/lib/docker bash
lvcreate -L 500G -n docker_imagedata vg0 mount /dev/vg0/docker_imagedata /var/lib/docker/image bash
lvcreate -L 5T -n k8s_data vg0 mount /dev/vg0/k8s_data /var/lib/kubelet bash
lvcreate -s -L 100G -n docker_snap /dev/vg0/docker_data bash
lvcreate -L 100G --thinpool docker_thin vg0 lvcreate -V 1T --thin -n container1 docker_thin 判断:thin LV 适合容器,每个容器独立 LV。
bash
lvs -o +data_percent docker_thin bash
lvextend -L +100G vg0/docker_thin bash
mkfs.xfs /dev/vg0/container_overlay mount /dev/vg0/container_overlay /var/lib/docker/overlay2 容器内 IO 抖动时,把 LV 放 SSD。
bash
mount -t nfs server:/data /var/lib/docker 判断:NFS 与 LVM 二选一。
LVM 在 Linux 2.4+ 内核支持,所有现代发行版都可用。
bash
udevadm trigger bash
systemctl status lvm2-monitor bash
auto_activation_volume_list = [ "vg0/data", "centos/root" ] 判断:白名单自动激活的 LV,避免误激活加密盘。
LVM 元数据在不同发行版间兼容。直接 vgexport/vgimport:
bash
vgexport vg0 vgimport vg0 yaml
- alert: VGLowSpace expr: (node_lvm_vg_free_bytes / node_lvm_vg_size_bytes) < 0.1 for: 30m annotations: summary: "VG free space < 10 percent" - alert: ThinPoolHighUsage expr: node_lvm_lv_data_percent > 80 for: 30m python
import subprocess import json def parse_vgs(): result = subprocess.run(['vgs', '--reportformat', 'json', '-o', 'vg_name,vg_free,vg_size'], capture_output=True, text=True) return json.loads(result.stdout) vgs = parse_vgs() for vg in vgs['report'][0]['vg']: free = int(vg['vg_free'].replace('B', '')) size = int(vg['vg_size'].replace('B', '')) percent = (1 - free / size) * 100 print(f"VG {vg['vg_name']}: {percent:.1f} percent used") 把 LVM 巡检接入:
多个 LVM 告警关联到一个根因。
每月做一次告警演练。
bash
lvcreate -s -L 10G -n data_snap /dev/vg0/data mount /dev/vg0/data_snap /mnt/snap rsync -a /mnt/snap/ /backup/ umount /mnt/snap lvremove /dev/vg0/data_snap bash
lvcreate -s -L 10G -n data_snap /dev/vg0/data mount /dev/vg0/data_snap /mnt/snap borg create /backup/repo::snapshot /mnt/snap umount /mnt/snap lvremove /dev/vg0/data_snap bash
lvcreate -s -L 10G -n data_snap /dev/vg0/data mount /dev/vg0/data_snap /mnt/snap tar czf /backup/data.tgz -C /mnt/snap . umount /mnt/snap lvremove /dev/vg0/data_snap bash
lvcreate -s -L 10G -n data_snap /dev/vg0/data mount /dev/vg0/data_snap /mnt/snap rsync -a /mnt/snap/ /backup/data/ umount /mnt/snap lvremove /dev/vg0/data_snap 不建议同时使用,层叠复杂。
mysqldump 是逻辑备份,LVM 快照是物理备份,两者结合:
btrfs 自带快照,不建议叠用。
xfs 自带 xfsdump:
bash
lvcreate -s -L 10G -n data_snap /dev/vg0/data mount /dev/vg0/data_snap /mnt/snap xfsdump -f /backup/data.dump /mnt/snap umount /mnt/snap lvremove /dev/vg0/data_snap bash
lvcreate -s -L 10G -n data_snap /dev/vg0/data mount /dev/vg0/data_snap /mnt/snap restic backup /mnt/snap umount /mnt/snap lvremove /dev/vg0/data_snap bash
pcs resource create lv_data ocfLVM volgrpname=vg0 exclusive=true pcs resource create fs_data ocfFilesystem device=/dev/vg0/data directory=/data fstype=xfs DRBD + LVM 是经典组合:
bash
lvcreate -L 100G -n drbd_data vg0 drbdmanage add-volume drbd_data 100G iSCSI target 用 LV 做后端:
bash
lvcreate -L 500G -n iscsi_lun vg0 targetcli /backstores/block/ create name=lun1 dev=/dev/vg0/iscsi_lun 集群 LVM 用 dlm:
bash
lvmconf --enable-cluster bash
lvcreate --type mirror -L 100G -m 1 -n data vg0 判断:LVM 自带镜像,无需硬件 RAID。
GlusterFS brick 可以放 LV:
bash
lvcreate -L 10T -n gluster_brick vg0 mkfs.xfs /dev/vg0/gluster_brick mount /dev/vg0/gluster_brick /var/lib/glusterfs/brick Ceph OSD 用 LV:
bash
lvcreate -L 10T -n ceph_osd vg0 DataNode 用 LV:
bash
lvcreate -L 100T -n hdfs_data vg0 MinIO 用 LV:
bash
lvcreate -L 50T -n minio_data vg0 mount /dev/vg0/minio_data /var/lib/minio CSI 驱动支持 LVM provisioner:
yaml
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: lvm-sc provisioner: lvmplugin.example.com parameters: vgName: vg0 65536 个 PE 是单个 LV 上限:
理论上 LV 总数有限(实际由 LV 数量决定)。
应用 fsync、VFS、文件系统、LVM (device-mapper)、MD 或硬件 RAID、设备驱动、硬件。
判断:层叠增加延迟。LVM 单层通常 < 5%。
判断:高性能场景可以绕过 LVM。
LVM 支持 io_uring,性能优于传统 IO。
远程 NVMe 通过 LVM:
bash
nvme connect -t rdma -n subsystem -a ip -s 4420 pvcreate /dev/nvme0n1 bash
cat /sys/block/dm-0/queue/nr_requests 判断:dm 多队列默认开启。
bash
cat /sys/fs/cgroup/blkio/system.slice/lvcheck.service/blkio.throttle.read_bps_device 判断:cgroup 可以限制 LV 的 IO。
bash
numactl --cpunodebind=0 --membind=0 dd if=/dev/zero of=/dev/vg0/test bs=1M count=1000 判断:NUMA 跨 socket 访问 LV 会慢。
bash
cat /sys/kernel/mm/transparent_hugepage/enabled 判断:数据库建议 never。
bash
mount -t hugetlbfs hugetlbfs /mnt/huge 判断:大页适合大内存应用。
bash
df -h /data vgs lvextend -l +100%FREE /dev/vg0/data xfs_growfs /data df -h /data bash
pvcreate /dev/sdc1 vgextend vg0 /dev/sdc1 lvextend -l +100%FREE /dev/vg0/data xfs_growfs /data bash
umount /data e2fsck -f /dev/vg0/data resize2fs /dev/vg0/data 80G lvreduce -L 80G /dev/vg0/data mount /data bash
lvcreate -s -L 10G -n data_snap /dev/vg0/data mount /dev/vg0/data_snap /mnt/snap rsync -a /mnt/snap/ /backup/ umount /mnt/snap lvremove /dev/vg0/data_snap bash
pvcreate /dev/sdd1 vgextend vg0 /dev/sdd1 pvmove /dev/sdc1 /dev/sdd1 vgreduce vg0 /dev/sdc1 pvremove /dev/sdc1 bash
umount /data lvremove /dev/vg0/data bash
vgremove vg0 bash
vgreduce vg0 /dev/sdc1 pvremove /dev/sdc1 bash
cp /etc/lvm/backup/vg0.bak /etc/lvm/backup/vg0 vgcfgrestore vg0 bash
pvs vgs lvs -o +devices LVM 是运维的基本功。三层结构 + 几组命令 + 元数据备份,把这一篇里的命令多跑几遍,遇到 LVM 故障按章节走,比临时查资料高效得多。
关键动作:
记住一句话:LVM 不是玄学,三层结构 + 命令链 + 备份习惯。
全部0条评论
快来发表一下你的评论吧 !