Linux如何多盘合一

发布时间:2026/7/12 20:18:49
Linux如何多盘合一 Linux 中对磁盘分区的常用方式有两种MBR分区方案寄存器GPT分区方案全局唯一标识磁盘分区表GPT的优势是分区列表中单个分区逻辑上最大支持 18 EB1 EB 1,048,576 TB可以定义128个分区分区的限制是不同系统决定的没有主分区、扩展分区和逻辑分区的概念所有分区都能格式化。通常使用 parted 管理工具创建GPT分区这种方式在日常使用已经足够但是日常工作中大存储设备需求用的不完全是gpt如果你会 K8s 一定知道在 K8s 中有储存卷、储存卷对象(PV)、存储卷声明(PVC)。MBR指的寄存器本质上就是 Linux 系统中 PV 的一种 支持扩容等使用手法使用上来讲是将新的磁盘或者分区声明为 PV (存储卷) 多个 PV 组成 VG (卷组) 对外以 LV (逻辑卷) 提供存储能力。不同发行版多数情况下安装系统界面上分配磁盘空间时指定的 LVM 选项就是在操作定义默认 VG 下的 LV 也就是说除了 /boot 这类特殊用途的路径其他在安装时定义的储存分配本身就是 LV 的分配并且通常默认是 MBR 分区。不过反过来说当通过 PV 这种方式去使用磁盘时PV 并不关心你指定的储存介质是什么分区类型还要注意的是PV 本身并没有 RAID 那种数据灾备的能力而且 PV 和 RAID 本身就也不会相互影响通俗来讲 PV 属于系统可见层RAID属于硬件可见层说白了组成 RAID 后RAID 对于系统或者说要创建 PV 时来讲就只有一个可见逻辑存储设备至于这个设备底层是啥那是硬件层的事情PVPhysical Volume物理卷由磁盘或分区初始化而来是 LV 的底层物理存储单元VGVolume Group卷组 由一个或多个 PV 组成的存储池PEPhysical Extent是 VG 内的最小分配单元LVLogical Volume逻辑卷 从 VG 中划分出来的逻辑存储单元相当于传统意义上的分区正式使用前查看有那些可用盘或者分区本文测试用的虚拟机准备了两块空盘[rootnode1 ~]# parted -lModel: VMware, VMware Virtual S(scsi)Disk /dev/sda:32.2GB Sector size(logical/physical): 512B/512B Partition Table: msdos Disk Flags: Number Start End Size Type File system Flags11049kB 1075MB 1074MB primary xfs boot21075MB32.2GB31.1GB primary lvm Error: /dev/sdb: unrecognised disk label Model: VMware, VMware Virtual S(scsi)Disk /dev/sdb: 1074MB Sector size(logical/physical): 512B/512B Partition Table: unknown Disk Flags: Error: /dev/sdc: unrecognised disk label Model: VMware, VMware Virtual S(scsi)Disk /dev/sdc: 1074MB Sector size(logical/physical): 512B/512B Partition Table: unknown Disk Flags:对于分区来讲你可以用lsblk命令查看哪些磁盘的分区还没有被挂载1、PV物理卷管理# 查看所有 PV 的简要信息pvs# 额外显示 UUIDpvs-opv_uuid# 查看所有 PV 的详细信息含 UUIDpvdisplay# 扫描系统中所有可用的 PVpvscan当你需要将空盘创建为 PV (物理卷)时可如下操作。本文使用的 AImaLinux 可以看到安装时分配的根路径储存空间属于默认的 almalinux VG[rootnode1 ~]# pvcreate /dev/sdb /dev/sdcPhysical volume/dev/sdbsuccessfully created. Physical volume/dev/sdcsuccessfully created.[rootnode1 ~]# pvsPV VG Fmt Attr PSize PFree /dev/sda2 almalinux lvm2 a--29.00g0/dev/sdb lvm2 ---1.00g1.00g /dev/sdc lvm2 ---1.00g1.00gPSize是指该 PV 本身有多大PFree是指该 PV 还有多少空间可以被分配随着后期使用过程中 VG 的使用而变动后期当 pv 不需要时通过pvremove /dev/sdb注销它但注销的前提是 pv 不能处于 vg 中# 禁止/允许该 PV 上的空间被分配常用于维护pvchange-xn /dev/sdb# n禁止分配, y允许分配[reference:5]2、VG卷组管理# 查看所有 VG 的简要信息vgs# 查看 VG 的详细信息vgdisplay# 扫描系统中所有 VGvgscan# 创建 vg 并添加 pv[rootnode1 ~]# vgcreate my_vg /dev/sdb /dev/sdcVolume groupmy_vgsuccessfully created[rootnode1 ~]# vgsVG#PV #LV #SN Attr VSize VFreealmalinux110wz--n-29.00g0my_vg200wz--n-1.99g1.99g# 创建 vg 时指定 PE 大小为 8MBvgcreate-s8M my_vg /dev/sdb如果是 pv 加入已有的 vg 通过vgextend my_vg /dev/sdb ...多个 pv 空格分割命令vg 在创建时可以指定 PE默认是 4MB。PE 是 vg 划分 lv 的底层单位。PE 越小分配颗粒度越细底层的 pv 利用率也就越高但注意随着 vg 自身储存容量的不同PE 的大小会影响 vg 元数据开销与管理性能例如 1TB 容量的 vg 4MB PE 会造成 26 万多的条目1MB PE 则有 100 万多条目依次类推元数据体积的大体量会导致管理命令执行速度线性变慢。同理PE 合理的调大可以让元数据条目变少管理命令执行变得轻快此外理想状态下 lv 的容量应当是 PE 的倍数否则当你在 64MB PE 的条件下创建一个 100MB 的 LV实际会占用 2 个 64MB 的 PE即 128MB这造成 28MB 的内部碎片被占用但无法使用删除 vg 需要先停用# 停用 vg会将所有 lv 变为非活跃且关闭状态 -wi-------vgchange-anmy_vg# 如果此时返回了 可再次激活 vglv回到 -wi-a----- 状态vgchange-aymy_vg# 用上面的命令 删除 pv 再删除 vgvgremove my_vg# 部分激活当有 PV 状态时vgchange-ay--partialmy_vg3、LV逻辑卷管理# 查看所有 LV 的简要信息lvs# 查看 LV 的详细信息lvdisplay# 扫描系统中所有 LVlvscan# 创建 lv[rootnode1 ~]# lvcreate -l 100%FREE -n my_lv my_vgLogical volumemy_lvcreated.# 使用固定大小创建lvcreate-L10G-nmy_lv my_vg[rootnode1 ~]# lvsLV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert root almalinux -wi-ao----29.00g my_lv my_vg -wi-a-----1.99g-l 100%FREE中 FREE 是个关键字指当前逻辑卷占用 VG 百分之多少的空间但要注意一个误区百分比只是在定义时用来便捷的指定大小在定义命令被系统物化的时候大小会被转换成固定值也就是说并不是这里指定百分比后期缩容和扩容 VG 时 LV 也随着变你也可以使用-L直接指定固定的大小现在你就可以格式化 LV并挂载[rootnode1 ~]# mkfs.ext4 /dev/my_vg/my_lvmke2fs1.46.5(30-Dec-2021)Creating filesystem with5222404k blocks and130560inodes Filesystem UUID: 6ea1d03e-669f-4f73-aefa-dcf5df0a5802 Superblock backups stored on blocks:32768,98304,163840,229376,294912Allocating group tables:doneWriting inode tables:doneCreating journal(8192blocks):doneWriting superblocks and filesystem accounting information:done[rootnode1 opt]# mkdir lv_path[rootnode1 opt]# mount /dev/my_vg/my_lv /opt/lv_path[rootnode1 opt]# lltotal12drwxr-xr-x3root root4096Jun2023:44 lv_path[rootnode1 opt]# cd lv_path/[rootnode1 lv_path]# df ./ -hFilesystem Size Used Avail Use% Mounted on /dev/mapper/my_vg-my_lv2.0G 24K1.9G1% /opt/lv_path此外lv 本身还有两个常用能力第一个是条带# 创建条带化 LV提升性能lvcreate-L10G-i2-I128KB-nmy_lv my_vg# -i 指定条带数 -I 指定条带数据块大小写入时所有条带均摊lv 的条带指的是显示指定当前 lv 的数据分担到多少个 pv 上有点是读写并行性能好缺点是很脆弱任何一块盘出现问题数据都会损坏且无法恢复。建议使用条带化的场景a. 磁盘阵列柜SAN提供的大量相同规格 HDD/SSDb. 存放临时性的高吞吐数据如 ETL 中间表、视频转码缓存等坏了就坏了没关系的数据c. 明确知道底层 pv 有 RAID 卡做硬冗余lv 层负责提速绝对不要用的场景a. 只有两块盘且没有其他备份机制如 RAID 1 或定期备份。b. 存放元数据、配置文件和系统根目录。c. 生产环境核心业务数据库除非底层已经是 RAID 且你清楚知道自己在做性能调优。第二个是快照# 创建 LV 的快照lvcreate--snapshot--namesnap_lv--size2G /dev/my_vg/my_lvlv 快照指定的 size 并不是说这个快照要对标被快照的 lv 一比一复制size 是快照自身的空间大小。可以类比 vmware 的虚拟机创建快照快照创建的非常快但快照并不是说把现在虚拟机的磁盘完整的备份一份快照创建的那一刻记录了一个时间戳后续你对磁盘的更改新数据会直接写入原本磁盘而被改变的旧数据副本会进入快照说白了每小时改 500M 的数据快照存在 4 小时你就需要 2-3G 的 size。而没有发生改变的数据快照和原磁盘底层是共享的。但注意如果 size 不够会导致快照数据损坏变为不可用因此快照有两个作用。用途一热备份最常用数据库MySQL/PostgreSQL运行时无法直接拷贝数据文件会损坏。此时就可以使用快照1、执行 lvcreate--snapshot...瞬间完成毫秒级2、挂载快照卷mount /dev/my_vg/snap_lv /mnt/snap——此时快照卷包含了创建那一秒的完整数据(被变动的旧数据 和原 lv 共享的未变动数据)3、将 /mnt/snap 里的文件tar或rsync到远程服务器读快照内核返回的永远是读取时刻快照所持有数据的静态冻结状态视图因此原 lv 可持续读写毫秒不耽误只要tar的过程中 size 没有发生上面提到的不够存放被变更的原始数据就没问题4、备份完成后卸载并删除快照lvremove用途二高危操作回滚救命稻草# 恢复/合并快照将原始卷还原到快照时刻合并后快照会自动删除lvconvert--merge/dev/my_vg/snap_lv4、扩容 LV首先 vgs 确定有可分配的剩余空间 随后就可以操作扩容了。例如要增加 20G 空间并自动刷新文件系统。命令有个容易混淆的点 lvextend 命令下-L参数的值如果无符号指将 lv 扩容到某个大小带 号指的是增量扩容多少。 lvextend-r-L20G /dev/my_vg/my_lv 刷新系统指的是lv 的扩大默认不会自动触发对应数据系统的大小元数据如果不带-r参数就需要手动刷新 ext2/ext3/ext4 文件系统使用 resize2fs /dev/卷组名/逻辑卷名命令它会自动将文件系统扩展到逻辑卷的最大可用大小。 XFS 文件系统使用 xfs_growfs挂载目录命令注意XFS 扩容命令后面跟的是挂载点路径而不是设备路径。5、缩容 LV不同文件系统类型用的命令不一样本文这里以最常用的 extN 类型为例子缩容前必须先卸载否则可能导致数据损坏。umount/dev/my_vg/my_lv 强制检查文件系统确保没有错误。 e2fsck-f/dev/my_vg/my_lv 先让文件系统缩小释放空间比如指定为19.5G resize2fs /dev/my_vg/my_lv19.5G 最后缩小逻辑卷。和扩容类似 不带符号 指缩容到带 - 号值缩容多少 lvreduce-L20G /dev/my_vg/my_lv扩容 LV 时尽量用 lvextend -L 20G增量避免去算当前容量加上 20G 等于多少。缩容 LV 时尽量用 lvreduce -L 20G绝对值但前提是必须提前用 df -h 确认当前已用数据量小于这个目标值否则会导致数据被直接截断丢失6、扩容 VG 比较简单将一个 PV 加入 VG 即可# 创建一个 pvpvcreate /dev/sdb# 加入 vgvgextend myvg /dev/sdb7、缩容 VG同样也是以 PV 为单位但是要求 PV 里的数据迁移到其他地方# 先将一个 PV 中的数据移动到 同 VG 下的其他 PV 中但是通常不直接指定第二个目的 pv 参数而是让系统自动决定分摊到同组的其他 PV 上pvmove /dev/sdb /dev/sdc# 迁移完成后目标 PV 查询一下确定处于空载状态pvs /dev/sdb# 移除 VG 中的这个 PVvgreduce my_vg /dev/sdb# 删除 PV 的定义pvremove /dev/sdbPV 迁移中断有以下几种情况a. 正常中断如按了 CtrlC 或终端意外断开pvmove 命令会自动保存当前的迁移进度。只需要在终端重新执行与之前完全相同的 pvmove 命令系统就会自动从上次中断的检查点继续迁移无需从头开始。b. 非正常中断如系统崩溃、意外断电此时迁移进程被强制终止LVM 同样支持断点续传。只需不带任何物理卷参数直接运行 pvmove 命令系统会自动检测并重新启动上次检查点后正在进行的迁移操作。c. 主动放弃迁移中止操作在迁移过程中发现目标盘选错了或者想主动停止当前的迁移任务可以使用pvmove --abort [目标pv]来安全中止操作。中止后已经移动的数据段会保留在目标 PV 上未移动的数据段会保留在源 PV 上注意pvmove是前端输出日志真正的迁移是内核再做所以取消一个迁移任务前 CtrlC 先断开对于 VG 的扩缩容操作就没有数据丢失的风险分两种情况情况 A该 PV 上还有数据已被分配给 LVLVM 具有自我保护机制它会直接拒绝执行 vgreduce 命令并报错提示该 PV 正在被使用。因此无法强行抽走一块正在存数据的盘也就不会发生数据丢失。所以换盘或者是真的要缩容先使用 pvmove 命令将数据平滑迁移到 VG 中的其他 PV 上然后再执行 vgreduce这个过程是安全的情况 B该 PV 是空闲的未被分配给任何 LV如果这块 PV 只是加入了 VG但从来没有给 LV 分配过空间即处于 Free PE 状态此时执行 vgreduce 移除它不会有任何数据异常因为上面根本没有业务数据。如果担心操作意外可以先用-t参数测试执行8、缩容的恢复操作如果你的缩容本质的目的是为了释放整个 vg 的磁盘或者是一个 lv 用前面管理命名删除即可 。如果是 pv 才需要先迁移要是你不关注数据安全可以执行pvremove -ff /dev/sdb强制释放后果是里面的数据很可能有损失因为大概率会涉及到多 pv 存一个 lv 数据但是缩容用的命令无论是 vgremove、pvremove、lvremove 它们本身只是擦除了元数据物理数据还在磁盘上只是由于元数据不存在所以不一定可以用也就是说得到的空闲磁盘需要另行格式化。注意此时就有一个特殊操作如果你刚执行完 vgremove且没有重启没有新建 VG 覆盖这块盘你就可以找对应时间的备份可以秒级恢复整个 VG[rootnode1 ~]# vgsVG#PV #LV #SN Attr VSize VFreealmalinux110wz--n-29.00g0my_vg210wz--n-1.99g0[rootnode1 ~]# vgremove my_vgDo you really want to remove volume groupmy_vgcontaining1logical volumes?[y/n]: y Do you really want to remove active logical volume my_vg/my_lv?[y/n]: y Logical volumemy_lvsuccessfully removed. Volume groupmy_vgsuccessfully removed[rootnode1 ~]# vgsVG#PV #LV #SN Attr VSize VFreealmalinux110wz--n-29.00g0[rootnode1 ~]# vgscanFound volume groupalmalinuxusing metadatatypelvm2[rootnode1 ~]# cd /etc/lvm/archive/[rootnode1 archive]# lltotal12-rw-------.1root root1337May514:51 almalinux_00000-1443742720.vg -rw-------1root root1128Jun2023:42 my_vg_00000-668102456.vg -rw-------1root root1695Jul1123:05 my_vg_00001-765524335.vg# my_vg_00001-765524335.vg 中 00001 是自动备份的序号765524335[rootnode1 archive]# vgcfgrestore -f my_vg_00001-765524335.vg my_vgRestored volume group my_vg.[rootnode1 archive]# vgsVG#PV #LV #SN Attr VSize VFreealmalinux110wz--n-29.00g0my_vg210wz--n-1.99g0[rootnode1 archive]# pvsPV VG Fmt Attr PSize PFree /dev/sda2 almalinux lvm2 a--29.00g0/dev/sdb my_vg lvm2 a--1020.00m0/dev/sdc my_vg lvm2 a--1020.00m0[rootnode1 archive]# lvsLV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert root almalinux -wi-ao----29.00g my_lv my_vg -wi-------1.99g当你删除的是 vg 、lv 上面的操作方式都可以恢复回来但对于 pvremove 要多一步因为 pvremove 会擦除磁盘的 LVM 标签Label这相当于把硬盘的“身份证”撕了# 1. 从归档文件中查出该 PV 原来的 UUIDgrep-A5/dev/sdb/etc/lvm/archive/my_vg_最新时间戳.vg# 2. 强制重新创建 PV并指定原来的 UUID 和备份文件pvcreate--uuid原来的UUID--restorefile/etc/lvm/archive/my_vg_最新时间戳.vg /dev/sdb# 3. 最后再恢复 VG 元数据这步会把 LV 的映射也修好vgcfgrestore-f/etc/lvm/archive/my_vg_最新时间戳.vg my_vg注意这个恢复手段严重依赖一个前提执行删除操作后没有对该磁盘进行过任何写入操作如新建 LV、格式化、拷贝文件等等