磁盘扩容这事,做过机房运维的人应该都有体会:一开始图省事,直接在某块盘上建文件系统,/data1、/data2、/data3越堆越多,等到某天某个目录突然爆满,才发现空间被切得七零八落,想从别的盘挪一点过来比登天还难。后来大家开始用 LVM,把物理盘先"上缴"给卷组统一管理,再按需切逻辑卷,扩容缩容都在线完成。而这道流程的第一颗螺丝,就是pvcreate。
pvcreate是 LVM2 工具集里最基础、也最容易被轻视的一条命令。它做的事情听起来简单——把一个块设备初始化为物理卷(Physical Volume,简称 PV)——但这一步做错了,后面vgcreate、lvcreate会连环报错,严重的时候还会把盘上原有的数据签名覆盖掉。这篇内容面向刚接手存储运维的新手,也面向那些"会用但没细想过为什么"的老手:我会把pvcreate到底在盘上写了什么、几个关键参数怎么选、整盘和分区的取舍、完整的实操流程,以及我这些年踩过的坑,一次讲透。看完之后,你至少应该能做到:拿到一块新盘,判断该不该分区、该不该清签名、该加哪些参数,然后一条命令下去心里有数。
1. pvcreate 到底是什么:先把 LVM 的三层结构捋顺
1.1 物理卷、卷组、逻辑卷的从属关系
LVM 的抽象是三层:底层是物理卷 PV,中间是卷组 VG,上层是逻辑卷 LV。这个结构可以用一个很生活化的类比来理解——PV 是砖块,VG 是砌好的整面墙,LV 是从墙上划出来的一个个房间。砖块本身不带功能,只有砌进墙里、再划分出房间,才谈得上使用。
pvcreate作用在最底层。它不创建任何文件系统,不格式化,也不分配挂载点,它只做一件事:在块设备的开头写入 LVM 的标签(label)和元数据区(metadata area),声明"这块设备从今天起归 LVM 管"。这个动作是破坏性的,因为它会覆盖设备开头若干个扇区,如果盘上原本有分区表、文件系统超级块或者引导记录,都会被冲掉。
这里有个新手经常混淆的点:PV 不等于"一整块磁盘"。一块物理磁盘可以先分区,再把某个分区做成 PV;也可以不分盘,整块设备直接做成 PV。两种做法在 LVM 眼里没有本质区别,pvcreate接收的参数永远是"一个块设备节点",至于这个节点是/dev/sdb还是/dev/sdb1,它不关心。选择权在你手上,后面第 3 章会详细讲怎么选。
再往上,一个 VG 可以由一个或多个 PV 组成,一个 LV 可以跨多个 PV 分布。所以 PV 是可以横向叠加的:今天一块 2T,明天再加一块 4T,卷组容量就变成 6T,逻辑卷按需扩容,业务无感知。这也是 LVM 相比裸分区的核心价值所在。
1.2 为什么要有 pvcreate 这一层抽象
有人会问:既然最后都是往盘上写数据,为什么不让vgcreate直接吃裸盘,非要中间插一个pvcreate?
关键在于元数据的归属。PV 上保存的是"这块设备属于哪个卷组、它的 PE 怎么排列"这类信息,而 VG 上保存的是"卷组里有哪些 PV、有哪些 LV、每个 LV 分布在哪些 PE 上"。这两层元数据的生命周期不一样:PV 可能被pvremove摘掉,VG 可能被vgremove销毁,LV 又可以被单独lvremove。分层的意义就是让每一层的操作互不干扰。
另一个原因是性能与容错。PV 上会预留一块元数据区,默认情况下 VG 的元数据会在每个 PV 上存一份副本。也就是说,如果卷组由三块盘组成,VG 配置就有三份,任何一块盘挂了,只要剩下的盘还在,vgcfgrestore就能把配置救回来。这个副本机制的前提,就是每块盘上都得有那块被pvcreate划出来的元数据空间。
我在一个项目里见过反例:某位同事图快,直接用dd手写 LVM 标签想跳过pvcreate,结果元数据区大小算错,vgcreate当场报Cannot use /dev/sdX: device is too small,排查了半天才发现是标签里的边界值不对。这种"省一步"的操作,最后往往要花十倍时间补回来。
1.3 pvcreate 在设备上到底写了哪几样东西
搞清楚它写了什么,排查问题时才有方向。一条成功的pvcreate会在设备上落下这些内容:
第一是LABEL,位于设备的第二个扇区(偏移 512 字节处,labelsector默认为 1),里面包含 PV 的 UUID、设备大小、元数据区的位置和大小等。这个位置是固定的,所以pvcreate一定会覆盖掉 MBR 分区表所在区域之后的一小段内容。
第二是元数据区(metadata area),默认从 1MiB 偏移处开始,大小通常为 1MiB 左右。VG 的配置文本就存在这里。你可以用--metadatasize调整它,也可以把--pvmetadatacopies设为 0 让它不存元数据副本(大型磁盘阵列场景下有人这么做,减少写入开销)。
第三是PE 起始位置pe_start,默认对齐到 1MiB。这个值的意义在于:数据区从哪个扇区开始。对齐做得好不好,直接影响 SSD 和 RAID 卡的性能表现。
第四是设备末尾的标签备份,用于防止头部扇区损坏后无法识别。所以严格来说,pvcreate是"头部 + 尾部"两处写入,中间的数据区域它不碰——但别因此以为原数据安全,因为分区表和文件系统超级块通常就在头部。
2. 命令语法与关键参数逐个拆解
2.1 最朴素的语法骨架与两三个常用变体
pvcreate的语法骨架非常短:
pvcreate [选项] 设备名 [设备名...]一条命令可以同时初始化多个设备,这是很多人不知道的便利之处。常规用法大概就这三种:
# 单块整盘 pvcreate /dev/sdb # 多个分区一起初始化 pvcreate /dev/sdb1 /dev/sdc1 /dev/sdd1 # 带元数据区大小,适合大容量磁盘 pvcreate --metadatasize 128m /dev/sde真正需要动脑子的不是命令怎么写,而是加什么参数。默认参数在大多数场景下够用,但如果你面对的是 SSD、NVMe、磁盘阵列 LUN,或者要给几十上百块盘批量初始化,那就得知道哪些开关值得改。
2.2 常用参数对照表与选用逻辑
我把实际工作中会碰到的参数整理成一张表,重点不是背下来,而是知道什么时候该翻它:
| 参数 | 作用 | 什么时候用 |
|---|---|---|
-f/--force | 强制创建,跳过"设备上已有签名"的确认 | 明确要覆盖旧 PV 或旧文件系统时 |
-y/--yes | 所有交互式提问自动回答 yes | 脚本批量执行,配合-f使用 |
-t/--test | 演练模式,只走流程不落盘 | 生产环境先验证参数是否正确 |
-v/--verbose | 输出详细过程 | 排查"为什么这条命令没生效" |
-u/--uuid | 手工指定 PV 的 UUID | 从备份恢复、盘符漂移后重建 |
-Z/--zero | 是否清零前 4 个扇区(y/n) | 需要彻底抹掉旧标签时 |
--metadatasize | 指定元数据区大小 | 卷组规模大、LV 数量多时 |
--pvmetadatacopies | 元数据副本数量(0/1/2) | 大规模阵列减少元数据写开销 |
--dataalignment | 数据区对齐到指定字节 | SSD、RAID 条带对齐优化 |
--labelsector | 标签所在扇区位置 | 极少数需要避开特殊扇区的场景 |
--bootloaderareasize | 预留引导区 | 需要从该盘引导的老式场景 |
-t这个参数我要专门夸一句。它的存在让"破坏性操作"变得可预演,命令会完整走一遍检查逻辑并打印出将要执行的动作,但不会真的写盘。在给客户环境做变更前跑一遍pvcreate -t -v /dev/sdX,可以提前发现设备忙、容量异常、已有签名等问题,比事后回滚便宜太多。
2.3 容易被忽略但很致命的几个细节
-f和-y不是一回事。-f是"强制",针对的是"设备上检测到了不属于 LVM 的签名"这种安全拦截;-y是"自动确认",针对的是交互提问。很多脚本里写了-y却没写-f,跑起来照样卡住等输入。
元数据区不是越大越好。有人觉得--metadatasize 1g更稳妥,实际上 LVM 元数据是纯文本,一个 LV 大约占几百字节,一千个 LV 也就几百 KB。元数据区开太大纯属浪费,开太小(比如小于 128KiB)在 LV 数量极多时又可能写满并告警。常规建议:普通场景保持默认,单卷组 LV 数量预计超过 500 个时给到 64MiB 或 128MiB。
pe_start的对齐问题必须重视。LVM2 默认把pe_start对齐到 1MiB,这对绝大多数 SSD 和 RAID 都是安全的。但如果你用的阵列卡最佳 I/O 大小是 256KiB 或 1MiB 条带,可以配合--dataalignment显式指定,让数据区正好落在条带边界上。经验上,一块被错误对齐的盘,随机写性能掉 20% 到 30% 都有可能,而且是那种"跑分看不出、业务能感觉出来"的隐性损耗。
提示:
--dataalignment的单位是字节,不是字符后缀。写--dataalignment 1m是无效的,得写--dataalignment 1M或者直接1048576。
UUID 不要随手指定。-u参数看着方便,但没有极强理由不要动。LVM 靠 UUID 识别 PV,盘符变化无所谓,UUID 才是身份。手工指定 UUID 出错,会导致同一 UUID 出现两份,后续pvs输出会冒出重复项,处理起来非常难受。
3. 上盘之前的准备:整盘还是分区
3.1 整盘做 PV 与分区做 PV 的取舍
这是新手第一个岔路口,也是最容易吵架的话题。两种做法都对,取决于你的管理习惯和后续扩展计划。
整盘直做 PV的好处是简单直接,少一层分区表,容量利用率最高,也不存在"分区表损坏导致 PV 不可见"的中间故障点。用pvcreate /dev/sdb一条命令搞定,pvs里显示的就是/dev/sdb。缺点有两个:一是某些老式的系统管理工具或监控脚本靠分区表识别磁盘用途,看不到分区会觉得异常;二是如果这块盘以后想改用途,需要整体清掉。
先分区再做 PV的好处是留有余地。比如一块 4T 盘,你划了 3.9T 的sdb1做 PV,剩下几十兆留作他用;或者出于规范,所有数据盘统一是"一个分区占满整盘,类型码 8e"。缺点是多了分区表这一层,容量会因对齐损失掉极小一部分,而且分区表本身也需要维护。
我的实际选择是:云主机和虚拟化环境用整盘,物理裸机遵循团队既有的分区规范。原因很实在——云盘扩容是在块设备层面做的,pvresize直接作用于/dev/vdb最顺;物理机如果已经有了一套分区标准,擅自打破只会让后来接手的人困惑。
无论选哪种,有一个动作是一致的:先用lsblk确认设备的真实层级关系。
lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINT这条命令能把磁盘、分区、LVM 逻辑卷、挂载点全部串起来显示,哪种设备上有文件系统、哪个正被挂载,一目了然。上机第一件事就是跑它,比fdisk -l更直观。
3.2 分区类型码到底要不要改成 8e
老资料里几乎都会强调"分区类型必须改成 8e(Linux LVM)"。这个说法在 20 年前是对的,现在其实已经不强制了——LVM2 识别 PV 靠的是标签里的 UUID 和魔数,不依赖分区类型码。你哪怕把分区标成 FAT32,只要里面写的是 LVM 标签,LVM 照样认。
但我依然建议改,理由是给人和工具看。运维交接时,fdisk -l里出现8e Linux LVM,任何人一眼就知道这块分区是干什么的,不用再跑pvs去猜。监控系统、资产管理系统通常也按分区类型做归类。这是零成本的规范,没有理由不做。
具体操作按工具分:
# fdisk(MBR) fdisk /dev/sdb # 交互中输入 t 改类型,再输入 8e,最后 w 保存 # gdisk(GPT) gdisk /dev/sdb # 交互中输入 t 改类型,再输入 8e00,最后 w 保存 # parted(一步到位) parted /dev/sdb -- set 1 lvm onGPT 下的类型 GUID 是E6D6D379-F507-44C2-A23C-238F2A3DF928,对应短代码8e00。这个细节知道就行,日常用8e00足够。
注意:改分区类型码本身不影响分区内的数据,但如果分区表正在被内核使用,需要用
partprobe或partx -u让内核重新读取,否则后续pvcreate可能报设备找不到。
3.3 清签名:动盘之前最该做的一步
拿到一块"以为是空盘"的设备,直接pvcreate是很危险的。这块盘可能刚从别的系统上拆下来,头上还躺着旧的分区表、旧的 LVM 标签、或者一个 ext4 超级块。pvcreate会检测到这些签名并拒绝执行——这是好事,说明保护机制在工作。
正确的做法是先看清有什么,再决定清不清:
# 扫描设备上残留的签名 wipefs -a --no-act /dev/sdb # 确认无误后真正清除 wipefs -a /dev/sdbwipefs的优点是它只清除签名所在的少数扇区,不像dd那样整盘抹零,速度快且对 SSD 友好。加上--no-act可以先干跑一遍,看清楚会清掉哪些位置,这个习惯值得养成。
如果wipefs之后pvcreate还是拒绝,通常有两种情况:一是设备上有正在使用的分区被挂载了,二是 LVM 认为这块设备属于某个已存在的卷组。前者用umount解决,后者需要先vgreduce --removemissing或者pvremove处理残留的元数据。
还有一种隐蔽情况:设备上残留的是另一个系统的 LVM 元数据(比如从别的机器整盘搬过来的)。这时候pvs可能会报出重复的 PV UUID,pvcreate -f能强制覆盖,但覆盖前请务必确认那块盘的数据确实不要了。
4. 完整实操案例:从裸盘到可用逻辑卷
4.1 案例一:单盘整盘初始化到底
假设我们有一台服务器,新插入一块 1TB 的 SSD,设备节点是/dev/sdb,准备整盘交给 LVM,创建一个 800G 的逻辑卷挂到/data。
第一步,确认设备状态:
lsblk /dev/sdb # NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT # sdb 8:16 0 1.0T 0 diskTYPE是disk,没有子分区,MOUNTPOINT为空,说明是裸盘且未被挂载。
第二步,干跑一遍验证参数:
pvcreate -t -v /dev/sdb输出会打印TEST MODE: Metadata will NOT be updated and volumes will not be (de)activated.并列出将要执行的动作。确认没报错再进下一步。
第三步,正式创建:
pvcreate /dev/sdb # Physical volume "/dev/sdb" successfully created.第四步,验证结果:
pvs # PV VG Fmt Attr PSize PFree # /dev/sdb lvm2 --- 1.00t 1.00t pvdisplay /dev/sdbpvs里VG一栏是空的,说明这块 PV 还没加入任何卷组,Attr显示---是正常的未分配状态。PSize显示 1.00t 而不是精确的 1.00TiB,是因为pvs默认做了单位取整,想看精确值用pvs --units b或者pvdisplay。
第五步,建卷组和逻辑卷:
vgcreate -s 4M data_vg /dev/sdb lvcreate -n data_lv -L 800G data_vg mkfs.xfs /dev/data_vg/data_lv mkdir -p /data mount /dev/data_vg/data_lv /data-s 4M指定 PE 大小,这是 VG 级别的参数,不是 PV 的。默认就是 4MiB,写出来是为了显式声明,避免以后有人改动默认值导致行为不一致。
把这个流程捋一遍你会发现,pvcreate在整个链条里只占一行,但它决定了后面所有步骤能否成立。曾经有一次,同事在分区上误用了整盘路径,pvcreate /dev/sdb而不是/dev/sdb1,结果分区表被覆盖,本来划好的sdb2上的旧数据一并没有了。事后复盘,问题就出在没跑lsblk那一步。
4.2 案例二:多块盘组成卷组与容量换算
接下来处理一个更真实的场景:一台存储节点,同时插入四块 2TB 的 HDD,设备是/dev/sdc到/dev/sdf,要求合成一个大的卷组,做一个 6T 的逻辑卷。
四块盘一起初始化,一条命令即可:
pvcreate /dev/sdc /dev/sdd /dev/sde /dev/sdf如果四块盘都是全新的,命令会一次性创建四个 PV。假如其中某块有残留签名,整条命令会中断并提示是哪一块出了问题,其他盘不受影响——这一点设计得挺好,不会出现"一半成功一半失败还搞不清是哪块"的局面。
批量操作时我更倾向加参数:
pvcreate -ff -y /dev/sdc /dev/sdd /dev/sde /dev/sdf-ff(两个 f)会跳过所有签名检测。这个操作危险系数很高,只建议在确认这批盘是刚从仓库拆封的全新盘时使用。生产环境的旧盘一律老老实实wipefs后再来。
四个 PV 建好后,创建卷组:
vgcreate -s 4M storage_vg /dev/sdc /dev/sdd /dev/sde /dev/sdf vgdisplay storage_vgvgdisplay里会看到几个关键数字,这里我把计算过程摊开讲:
PE Size是 4.00 MiBTotal PE是四块盘可用 PE 的总和- 单块 2TB 盘实际可用约 1.82 TiB(1862.6 GiB),减去
pe_start的 1MiB 和元数据区的 1MiB,可用数据区约 1862.6 GiB - 1862.6 GiB ÷ 4 MiB ≈ 476,825 个 PE(取整到 4MiB 边界内)
- 四块盘合计约 1,907,300 个 PE
所以vgdisplay里Total PE应该在 190 万左右,Free PE在创建 LV 之前等于它。如果你算出来的数字和显示差得离谱,八成是某块盘的容量不及预期,或者 PE 大小被改过。
创建一个 6T 的 LV:
lvcreate -n big_lv -L 6T storage_vg # Rounding up size to full physical extent 6.00 TiB注意那行Rounding up。LVM 的 LV 大小必须是 PE 的整数倍,6TiB ÷ 4MiB = 1,572,864,正好整除,所以这次没有实际取整。如果你写-L 500G,500GiB ÷ 4MiB = 128,000,也整除。但写-L 5000M就不一定了,LVM 会自动向上取整到 PE 边界,并打印提示。这个提示不是错误,但值得留意——它意味着你实际拿到的空间比申请的多一点点。
4.3 案例三:分区做 PV 与 PE 大小选择的实际影响
第三种情况更贴近传统机房:盘上已经按规范划好了分区,分区类型都是8e,要把sdc1、sdd1、sde1做成 PV。
流程和整盘几乎一样,只是设备名带上了分区号:
# 先确认三个分区确实存在且类型正确 fdisk -l /dev/sdc /dev/sdd /dev/sde # 初始化 pvcreate /dev/sdc1 /dev/sdd1 /dev/sde1这里有个细节值得说:用分区做 PV 时,pe_start的对齐基准是分区起点,不是整盘起点。如果分区起点本身没对齐到 1MiB(老的分区工具可能只对齐到 63 扇区),那么pe_start虽然对齐了分区起点,但整体相对物理盘是错位的。遇到这种盘,我一般直接--dataalignmentoffset或者干脆重建分区,别在小数点上抠。
PE 大小怎么选,这是个经典问题。默认 4MiB 适合绝大多数场景,但有两种情况需要调整:
- 单卷组内有大量小 LV(比如每个虚拟机一个 10G 盘,几百个),4MiB 的 PE 会导致每个 LV 浪费最多 4MiB。这种情况下用
-s 1M或-s 2M能减少碎片浪费。 - 卷组规模极大(几十 TB 以上),PE 太小会让元数据里的映射表膨胀,影响激活速度和内存占用。这时候用
-s 16M甚至-s 32M更合适。
代价是 PE 大小一旦在vgcreate时定下就不能改。要改只能备份数据、重建 VG。所以建 VG 之前想清楚,别等跑了半年才后悔。
5. 常见报错与排查实录
5.1 "Device /dev/sdX excluded by a filter"
这是pvcreate最高频的报错之一,尤其在多路径环境、虚拟化环境里。原因是 LVM 配置文件/etc/lvm/lvm.conf里的filter规则把这块设备排除了。
典型场景:一块盘同时被/dev/sdb、/dev/mapper/mpatha、/dev/disk/by-id/xxx三条路径可见,LVM 为了防止把同一块盘识别成多个 PV,通过 filter 只保留其中一条。如果你的设备名不在白名单里,就会被拒。
排查步骤:
# 看出 LVM 眼里到底有哪些设备 lvmdevices # 或者老一点的版本 pvs -a # 查看当前 filter 配置 grep -A 10 'devices {' /etc/lvm/lvm.confpvs -a会列出所有被扫描到的设备,包括被排除的(Attr里会标记)。如果目标设备压根没出现,说明扫描阶段就被过滤了,需要改filter或global_filter。
改完之后不需要重启,但要让 LVM 重新加载配置:
vgscan --cache注意:直接编辑
lvm.conf之前务必备份。filter 写错会导致系统启动时找不到根卷组,直接进不了系统。这是真正能让人半夜被叫起来的那种事故。
5.2 "Can't open /dev/sdX exclusively. Mounted filesystem?"
报错字面意思很明确:设备被独占占用了。但"被占用"的原因五花八门,按概率从高到低排:
第一,设备或它上面的分区被挂载了。用mount | grep sdb或者findmnt /dev/sdb确认,卸载后再试。
第二,设备被某个进程持有句柄。lsof /dev/sdb能查出来,但要注意lsof对块设备不一定敏感,更可靠的是fuser -vm /dev/sdb。
第三,设备是某个 MD RAID 阵列或 dm 设备的成员。这种情况lsblk会显示TYPE是raid1之类,需要先mdadm --stop停掉阵列。
第四,设备被 swap 占用。swapon --show看一眼,有的话swapoff掉。
第五,设备是某个正在运行的虚拟机的磁盘直通目标。这个最隐蔽,fuser也查不出来,得从虚拟化层确认。
处理顺序建议:先lsblk看拓扑,再findmnt看挂载,再fuser看进程,三层筛下来基本都能定位。
5.3 重复 PV 与多路径的坑
pvs输出里出现两条记录,UUID 一模一样,PSize也一样——这是典型的同一块盘被识别成了两个 PV。
原因几乎都是多路径。一块盘通过两条 HBA 路径可见,如果 multipath 没配好或者 LVM filter 没排掉,LVM 会把两条路径当成两块独立的盘。这种情况下如果误执行了pvcreate,两条路径上都会写入标签,但实际是同一块物理盘,元数据就乱了。
正确做法:
# 确认多路径是否生效 multipath -ll # 在 lvm.conf 里把非 mpath 路径全部排除 # 只保留 /dev/mapper/mpath* 参与扫描如果已经产生了重复 PV,处理起来要格外小心。用pvs --uuid找出重复的,先vgreduce把多余的踢出卷组(如果已经建了 VG),再pvremove清掉。整个过程绝对不能在有数据的情况下贸然操作,先做vgcfgbackup。
5.4 建完 PV 之后的几个高频疑问
为什么pvs显示的容量比标称少?因为磁盘厂商按 10 进制标容量,1TB = 1000^4 字节,而操作系统按 2 进制显示,1TiB = 1024^4 字节。一块"1TB"盘实际约 931GiB,再减去 LVM 元数据区,显示 930 多 GiB 完全正常。这不是 LVM 吃掉了空间。
PV 建好了为什么df -h看不到?因为df看的是文件系统,PV 上还没有文件系统。PV 只是"已标记归属",没有任何可挂载的东西。这个误解在刚接触 LVM 的人里非常普遍。
能不能把 PV 从卷组里摘出来?可以,前提是这块 PV 上没有活跃的 LV 数据。流程是pvmove先把数据迁走,再vgreduce摘除,最后pvremove清除标签。pvmove的耗时和数据量成正比,几 TB 的数据可能要跑几个小时,建议放在维护窗口做。
pvresize和pvcreate什么关系?pvresize是把"已经变大的块设备"的新容量同步给 PV。云盘在线扩容后,块设备从小变大,但 PV 还记着旧尺寸,这时候跑pvresize /dev/sdb就能把新增容量纳进来,不用重建。注意顺序:先让内核感知新容量(云平台通常自动做,物理机可能需要echo 1 > /sys/class/block/sdb/device/rescan),再pvresize,最后lvextend。
6. 运维视角的经验与红线
6.1 元数据备份是被低估的救命手段
LVM 会自动把 VG 配置备份到/etc/lvm/backup/和/etc/lvm/archive/,前者是最新版本,后者是历史版本。很多人不知道这个目录的存在,直到卷组出问题才翻出来。
我的习惯是:每次pvcreate、vgcreate、lvcreate这类结构性变更之后,手动跑一次vgcfgbackup,把配置固定下来。
vgcfgbackup -f /root/lvm-backup-$(date +%F).vg storage_vg备份文件里记录着每个 PV 的 UUID、PE 布局、LV 的段映射,配合vgcfgrestore可以把卷组恢复到任意历史状态。这在误删 LV、误摘 PV 时是唯一能救命的稻草。
但要记住一点:备份的是元数据,不是数据。vgcfgrestore能恢复"卷组长什么样",恢复不了 LV 里的文件。数据本身还是得靠常规备份。
6.2 一步步确认的肌肉记忆
我给自己定的规矩是,任何一次pvcreate之前必须走完这几步:
lsblk确认设备层级和目标节点findmnt确认没有挂载wipefs --no-act确认签名情况pvcreate -t -v干跑一遍- 才执行真正的
pvcreate
五步走下来大概多花一分钟,但这一分钟能挡掉 90% 以上的误操作。我见过最惨烈的一次,是有人把服务器的系统盘/dev/sda当成了数据盘,pvcreate -ff -y /dev/sda一条命令下去,分区表和引导记录全没了,机器当场失联。虽然最后靠重装恢复了,但那天晚上整个团队都没睡好。
提示:可以在 shell 里给危险命令加一层保护,比如写一个 wrapper 脚本,执行
pvcreate前强制要求输入设备名确认。这种"笨办法"在多人协作的环境里效果极好。
6.3 和 pvremove、pvresize、pvck 的配合
pvcreate不是孤立存在的,它有一套配套工具,实际运维中经常连着用:
pvremove是它的逆操作,清除 PV 标签,让设备回到"未标记"状态。执行前必须先vgreduce把 PV 从卷组摘除,否则会报PV is still in use。清完之后用wipefs -a再扫一遍,确保没残留。
pvck是检查工具,专门用来检查 PV 上的元数据区是否一致。如果怀疑某个 PV 的元数据损坏(比如pvdisplay报Couldn't read volume group metadata),用pvck /dev/sdb看一眼。它能报告哪个元数据区坏了,但不一定能修,修不了就靠vgcfgrestore。
pvresize前面讲过了,扩容必备。有个细节:pvresize之后pvs里PFree会增加,但 VG 的Free PE不会自动更新,需要vgscan刷新一下。
pvmove严格说不算 PV 工具,但和 PV 操作强相关。摘盘之前先pvmove /dev/sdb,把数据搬到同卷组的其他 PV 上,这是安全摘盘的标准动作。如果目标 PV 空间不够,pvmove会报错并中止,原数据不受影响。
6.4 几条不能碰的红线
最后把我认为最该写进团队规范里的几条列出来:
永远不要在没跑lsblk的情况下执行pvcreate。哪怕你百分百确信设备名是对的,也跑一下。盘符漂移是真实存在的,/dev/sdb在重启后未必还是同一块盘。
生产环境禁用-ff。双 f 跳过所有检查,等于把安全带解了开车。真要覆盖旧盘,先wipefs再正常pvcreate,多一步但心里踏实。
不要在根卷组相关的 PV 上做任何实验。根卷组一旦出问题,系统直接起不来。要在根卷组上扩 PV,先做好救援介质和配置备份。
分批操作,不要一把梭。给一百块盘做初始化,先挑一块跑通全流程,确认pvs、vgdisplay、挂载都正常,再批量执行。批量脚本里加-t干跑和日志输出,出问题能快速定位是哪一块。
记录每一次变更。哪块盘什么时候做的 PV、加进了哪个 VG、当时用的什么参数,这些都值得记一笔。半年后接手的人(可能就是你自己)会感谢当时的记录。
这套流程用熟了,pvcreate其实就是一条命令的事。但正是这条最基础的命令,把"一块裸盘"变成"可被统一调度存储资源"的第一步。把这步做扎实,后面的vgcreate、lvcreate、在线扩容、跨盘迁移,才有一切顺利的前提。我在实际项目里越来越体会到,存储这事没什么高深技巧,无非是把每一个不起眼的动作做到位,然后在别人踩坑的时候,你已经因为那五分钟的确认而躲过去了。