ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

LVM存储与K8s PV/PVC/StorageClass核心概念详解

LVM存储与K8s PV/PVC/StorageClass核心概念详解 做运维的人应该都有过这种经历某个业务目录空间告急df一看已经 97%头开始大。如果这套环境用的是传统分区那接下来的剧本往往是“停机、加磁盘、迁移数据、重新挂载”如果当初用了 LVM 逻辑卷情况就会从容很多——因为有了PV、VG、LV这套三层抽象你可以在线把空间“补”上去甚至跨物理盘调整。我看到最近还有人在搜“pv pvc storageclass 这三者关系是什么”再加上另一个热搜“lv内核下载”说明不少同学在概念和内核层面都有疑问。这篇文章就把 LVM 的 PV/VG/LV 讲透顺带把 K8s 那套 PV/PVC/StorageClass 的关系也捋清楚最后补几个我实际运维中踩过的坑。1. 分区困境为什么业务系统最终会选择 LVM 这套抽象1.1 传统分区方案的三个硬伤很多新手会觉得“磁盘管理”不就是fdisk分个区、mkfs格式一下、然后挂载吗维护个两年你就能体会到传统分区的痛空间固定调整成本高。一个分区是 100G业务涨到 120G除非旁边有未分配空间否则你只能加新盘、重新建分区、拷贝数据再卸载旧分区。这中间必然产生停机窗口。跨盘能力为零。两块盘各 500G想弄出一个 800G 的“单目录”传统分区做不到只能靠 RAID 或者更上层的文件系统去拼。盘和目录绑定太死。在传统模式下/dev/sdb1就是sdb这块盘上的分区你没法在保持文件系统不变的情况下把它背后的物理载体悄悄换掉。这就是为什么大一点的服务器、数据库主机、虚拟化宿主机几乎默认都会上 LVM。LVM 的全称是 Logical Volume Manager它要解决的核心问题就是不要把业务看到的存储形态直接锁死在物理磁盘的固定布局上。1.2 LVM 的解题思路把磁盘拆成“积木”LVM 的抽象并不复杂一共三层PVPhysical Volume物理卷把一块物理磁盘或分区初始化成 LVM 认识的“标准原料”。VGVolume Group卷组把多块 PV 汇总成一个大的“资源池”。LVLogical Volume逻辑卷从 VG 这个池子里切出的一块块“业务卷”相当于传统概念里的分区。你可以这样类比PV 是“一袋袋水泥”VG 是“把所有水泥倒进一个大搅拌池”LV 是从池子中按需取出来的“预制板”。业务看到的是预制板不用关心水泥来自哪个袋。这个抽象带来一个天然好处LV 不再和某一块物理盘绑定。它可能跨了两块盘或者只用了某块盘的一部分。后续任何一块盘空间不够只要 VG 里还有余量LV 就能在线“长个”VG 也不够时再塞一块新盘进去做 PV扩容就完成了。1.3 LVM 带来的三大红利聚合、在线调整、快照具体收益我用三条来总结聚合多块小盘汇成一个大池子。比如四块 2T 盘组成一个 VG就可以分出一个 6T 的 LV 给备份目录而不用管那 6T 到底落在哪块盘上。在线调整大多数场景下lvextend扩 LV、vgextend扩 VG 都能在系统运行中完成配合resize2fs或xfs_growfs业务几乎无感。快照LVM 支持创建 LV 快照对数据库备份、虚拟机磁盘备份非常有用。快照利用的是 copy-on-write 机制创建速度极快不会长期占用与源卷等量的空间。如果你还不清楚这三个红利在实际运维里意味着什么后面第 4 节的实操会带你完整走一遍。2. 解开 LVM 三层模型PV、VG、LV 的职责、限制与命令对照2.1 PV把物理磁盘改造成“可入库原料”PV 是最底层的基础设施。执行pvcreate /dev/sdb /dev/sdc之后LVM 会在盘头写入一段元数据并把这个盘纳入自己的管辖范围。从这以后这块盘不再是一个“裸分区”而是一块有 LVM 身份的物理卷。执行后我们可以用pvs或pvdisplay查看。常见输出类似$ pvs PV VG Fmt Attr PSize PFree /dev/sdb vg_data lvm2 a-- 500.00g 500.00g /dev/sdc vg_data lvm2 a-- 500.00g 500.00gPV 内部是被划分成一个个PEPhysical Extent物理扩展块的。默认 PE 大小是 4MB也就是 4MB 的整数倍来“切”磁盘。PE 可以理解为 LVM 分配磁盘空间的最小“筹码”后面 LV 的大小和 VG 的容量统计都和 PE 有关。一个常被忽略的限制创建 PV 时最好明确整块盘是否已有重要数据。pvcreate会把磁盘头部的元数据区域覆盖掉如果你拿一块有旧分区的盘直接做 PV旧数据会变得不可见属于高风险操作。2.2 VG把原料汇成资源池VG 是把多个 PV 合并后的“空间蓄水池”。执行vgcreate vg_data /dev/sdb /dev/sdc系统就把这两个 PV 划入同一个卷组。VG 里有空闲空间才能继续创建 LV。VG 的元数据会记录在它包含的 PV 上并不是存在某个全局数据库中。所以当你把一组 PV 全部拔掉再插回同一台机器LVM 也能通过vgscan重新发现 VG。VG 需要特别注意的点一个 PV只能属于一个 VG。如果你想让某块盘离开当前组加入另一个组得先vgextract或pvmove再pvchange。VG 名字在系统内必须唯一否则激活时会混乱。VG 的可用空间是所有 PV 剩余 PE 的总和所以vgs里的VFree才是你真正能继续分给 LV 的余量。用vgs查看$ vgs VG #PV #LV #SN Attr VSize VFree vg_data 2 1 0 wz--n- 999.99g 800.00g2.3 LV从池子里切出“业务分区”LV 是真正挂载给业务使用的块设备。它由若干LELogical Extent逻辑扩展块组成每个 LE 会映射到某个 PE。因为有了这层映射LV 可以跨 PV并且在扩容时新 PE 只需追加到映射关系里就好对文件系统透明。创建命令很直接lvcreate -L 200G -n lv_www vg_data-L指定大小-n指定逻辑卷名。创建完成后设备路径通常是/dev/vg_data/lv_www同时也会在/dev/mapper/vg_data-lv_www下出现一个映射设备。我们来看小例子$ lvs LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert lv_www vg_data -wi-a----- 200.00g这一步的“逻辑卷”三个字很关键虽然它看起来像分区但它不再关心底层物理盘是谁。你可以把 LV 随便搬到别的 PV 上也可以在线扩大业务进程毫无感知。2.4 命令、设备文件与三层映射关系速查下面这张表是我给团队培训时常用的对照一眼能看明白命令和三层的对应关系层级作用常用命令查看命令设备形式PV把物理盘初始化为 LVM 可用单元pvcreatepvs/pvdisplay/dev/sdb等VG把多个 PV 汇总成一个资源池vgcreatevgs/vgdisplayvg_data等卷组名LV从 VG 中切出可用的逻辑卷lvcreatelvs/lvdisplay/dev/vg_data/lv_www文件系统在 LV 上格式化并挂载mkfs.ext4/mountdf -h/www等挂载点三者依赖关系是自上而下的PV 是基础VG 靠 PV 组成LV 靠 VG 的空间切出。删除时顺序相反先删 LV再删 VG最后才处理 PV。3. 透过内核看 LVM“lv内核”到底依赖什么模块3.1 Device MapperLVM 为什么必须依赖内核很多初学者只学了lvm命令却不知道 LVM 在内核层面依赖一个叫Device Mapper的机制。Device Mapper 是 Linux 内核提供的一个通用块设备映射框架它允许用户空间程序定义“虚拟块设备”的映射关系。LVM 的 LV 本质上就是 Device Mapper 设备。当你执行lvcreate整个链路是用户空间的lvm2工具计算好 LV 到 PV 的映射关系。通过 ioctl 或 netlink 机制把这个映射关系交给内核的dm_mod驱动。内核创建出一个新的映射设备在/dev/mapper/下出现对应节点。所以一个系统要使用 LVM必须同时具备两个条件内核里有 Device Mapper 相关模块常见的是dm_mod、dm_mirror、dm_snapshot等用户空间安装了lvm2工具包。如果你在精简内核或容器宿主机上发现 LVM 命令明明存在但vgs、pvs报“设备不存在”或“Volume group not found”第一反应就应该是检查内核模块lsmod | grep dm_ modprobe dm_mod3.2 “lv内核下载”背后的真实语义“lv内核下载”这个搜索词看起来像在找与 LVM 相关的“内核下载”但其实更准确的理解是用户需要的不是某个叫“lv”的内核而是支持 LVM 的内核驱动 配套的 lvm2 用户空间工具。在常规发行版里你不需要单独“下载内核”来启用 LVM只需要确认两件事内核是否编译了 Device Mapper。大部分发行版默认是m也就是模块方式能动态加载。用户空间工具是否安装。Debian/Ubuntu 下是lvm2包RHEL/CentOS/Rocky 下是lvm2包SUSE 下也一样。安装命令大致是# Debian/Ubuntu apt-get install -y lvm2 # RHEL/CentOS/Rocky dnf install -y lvm2如果只是想在系统里查看内核配置可以这样确认# 查看当前加载的模块 lsmod | grep dm_ # 查看内核是否启用 Device Mapper取决于发行版 grep -i dm /boot/config-$(uname -r) 2/dev/null出现类似CONFIG_BLK_DEV_DMy或m就说明内核本身支持。m时由modprobe dm_mod加载即可。3.3 initramfs 与启动阶段内核、LVM 工具、激活顺序这里值得多说一段因为“lv内核下载”这个搜索背后很多用户其实是卡在了 Linux 启动阶段内核找得到磁盘但挂在 LVM 上的根分区无法激活系统进入 emergency mode。这往往不是“内核没下载”而是initramfs初始内存盘里没有包含 LVM 工具和 dm 模块。Linux 启动时根文件系统还没有挂载必须先靠 initramfs 里的工具去识别存储、激活 LVM、再挂载真正的根分区。如果 initramfs 里没有 lvm2 或没有dm_mod自然就失败。遇到这种问题常规修复方式是# 重新生成 initramfsDebian/Ubuntu update-initramfs -u # 重新生成 initramfsRHEL/Rocky dracut -f然后重启验证。我见过不少用 LVM 做根分区的机器系统大版本升级时忘了重建 initramfs升级后一重启就卡住。这是 LVM 运维中非常典型的“非数据损坏但系统起不来”场景。所以“lv内核下载”如果翻译成运维动作其实就是确保内核模块存在、lvm2 工具存在、initramfs 里包含 LVM 支持。4. 从零实操初始化 PV 到创建 LV并完成扩容缩容全流程4.1 环境预检与 PV/VG/LV 初始化假设机器上有两块新盘/dev/sdb、/dev/sdc都是 500G我们要把它们组成一个卷组vg_data然后切一个 200G 的逻辑卷给 Web 目录/www用。第一步先用lsblk确认盘符和容量避免搞错设备$ lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sdb 8:16 0 500G 0 disk sdc 8:32 0 500G 0 disk然后用pvcreate初始化两块盘pvcreate /dev/sdb /dev/sdc如果你给整块盘做 PV某些系统会有提示“Device /dev/sdb not found (or ignored by filtering)”或者“device not a partition”。这是正常现象整块盘没有分区表时 LVM 也能工作只是部分老工具会多打一行警告。可以用pvcreate --force处理但我一般建议如果磁盘是专用数据盘整块盘直接做 PV 是安全的如果后续可能还要配合其他分区工具最好先用fdisk建一个 LVM 类型的分区再对分区做 PV。初始化完创建 VGvgcreate vg_data /dev/sdb /dev/sdc再用vgs看可以看到 VG 总容量约 1000G。这里要注意磁盘容量看起来是 500G实际可用会略小一点因为 PV 头部要写元数据且 PE 对齐也会吃掉一点点空间。不要对 1000G 这个数字有强迫症。接下来创建 LVlvcreate -L 200G -n lv_www vg_data这时候lvs就能看到lv_www了。4.2 格式化挂载与开机自启LV 创建后它只是一个块设备还需要文件系统mkfs.ext4 /dev/vg_data/lv_www如果是给大数据或数据库场景用也可以考虑 xfsmkfs.xfs /dev/vg_data/lv_www然后建挂载点并挂载mkdir -p /www mount /dev/vg_data/lv_www /www为了让重启后自动挂载需要写入/etc/fstab。这里我强烈建议用UUID而不是设备名因为 LVM 设备名在迁移或扩容后虽然一般不变但万一 LV 被删除重建设备名可能还是同一个UUID 却是新的。通过blkid获取 UUID$ blkid /dev/vg_data/lv_www /dev/vg_data/lv_www: UUID3b8f1c2a-xxxx-xxxx-xxxx-xxxxxxxxxxxx TYPEext4在/etc/fstab里加一行UUID3b8f1c2a-xxxx-xxxx-xxxx-xxxxxxxxxxxx /www ext4 defaults 0 2然后执行mount -a验证没有报错再重启测试。4.3 扩容先加盘还是先加卷扩容是 LVM 最常被问的操作。场景一VG 里还有空间LV 扩就可以了。比如要把lv_www从 200G 扩到 250Glvextend -L 50G /dev/vg_data/lv_www然后根据文件系统类型执行在线扩容# ext4/ext3 resize2fs /dev/vg_data/lv_www # xfs xfs_growfs /www注意xfs 在线扩容时参数是挂载点而不是设备路径这一点老手也会偶尔弄混。场景二VG 本身也没空间了那就得先加一块新盘进 VG。比如再插入一块/dev/sddpvcreate /dev/sdd vgextend vg_data /dev/sdd然后回到刚才的lvextend和文件系统扩容命令。整个过程可以做到业务不中断前提是文件系统支持在线扩容ext4、xfs 都支持。4.4 缩容与快照能做的和不能做的缩容比扩容麻烦得多。ext4 文件系统可以缩容但 xfs不行xfs 官方只能增肥不能瘦身。如果必须要缩容只能备份数据、删 LV、重建 LV、恢复数据。ext4 缩容的正确顺序是卸载文件系统umount /www强制检查e2fsck -f /dev/vg_data/lv_www先缩小文件系统resize2fs /dev/vg_data/lv_www 100G再缩小 LVlvreduce -L 100G /dev/vg_data/lv_www重新挂载mount /www这里最容易出错的是顺序必须先缩小文件系统再缩小 LV。如果你先lvreduce文件系统元数据可能会被截断数据直接损坏。我见过不止一次因为“图省事”先缩 LV 导致整个目录读不出来的案例。快照操作相对简单lvcreate -s -n snap_www -L 20G /dev/vg_data/lv_www创建后可以把/dev/vg_data/snap_www挂载到临时目录用于备份一致性检查。快照本身只在源卷发生变化时才慢慢消耗空间所以你不能拿一个 10G 快照去覆盖一个 100G 的大库长期变化场景。快照卷一旦写满会自动失效千万别把快照当长期备份。5. 跨领域对比同样是 PVK8s 里的 PV 和 LVM 里的 PV 有什么关系5.1 为什么两个领域的 PV 会撞名热门搜索词“pv pvc storageclass 这三者关系是什么”说明很多人被 PV 这个缩写搞晕了。LVM 里的 PV 是 Physical VolumeK8s 里的 PV 是 PersistentVolume两个完全不同的概念只是恰好都叫 PV。要区分并不难看上下文就行在 Linux 终端里敲pvcreate、vgs、lvs那是 LVM。在 K8s 的 YAML 里看到kind: PersistentVolume、kind: PersistentVolumeClaim、kind: StorageClass那是云原生存储抽象。但为什么有人会把它们放一起搜因为两者都解决同一个问题把“物理存储资源”和“业务使用请求”解耦。LVM 解耦的是“业务卷”和“物理盘”K8s 解耦的是“Pod 的存储请求”和“底层真实存储设备”。5.2 K8s 中 PV、PVC、StorageClass 的关系简单说K8s 的三件套是这样的PVPersistentVolume集群管理员预先准备好的一块存储可以来自 NFS、Ceph RBD、云盘、本地目录等。它描述“我有一块多大的存储支持什么访问模式”。PVCPersistentVolumeClaim应用提交的存储需求比如“我要 5GiReadWriteOnce”。它本身不是存储资源而是一张“申请单”。StorageClass动态制备的模板。PVC 指定了 storageClassName 后StorageClass 对应的 provisioner 会自动创建并配置 PV再和 PVC 绑定。没有 StorageClass 时管理员只能手动创建 PV然后等待 PVC 来绑定。三者关系用一个快递场景类比PV 是仓库里已经打包好的包裹PVC 是客户下的订单StorageClass 是生产包裹的自动化流水线。没有流水线你得提前人工包好包裹放仓库有流水线客户一下单机器自动打包。在 YAML 里申请存储的典型写法是apiVersion: v1 kind: PersistentVolumeClaim metadata: name: www-pvc spec: accessModes: - ReadWriteOnce storageClassName: fast resources: requests: storage: 10Gi如果集群里有名为fast的 StorageClass并且其 provisioner 正常系统会自动创建对应的 PV并把 PVC 绑定到 PV。5.3 用 LVM 的思维理解 K8s 存储再回到 LVM 本地存储插件用 LVM 思维来类比 K8s 存储会发现很多地方是相通的维度LVM 概念K8s 概念底层存储单元PV物理卷实际存储后端NFS、Ceph、本地盘等资源池/模板VG卷组StorageClass按模板动态制备最终给业务用的卷LV逻辑卷PV 对应的真实卷使用申请无直接类比PVCPersistentVolumeClaim挂载给上层应用mount 到目录挂载到 Pod 容器路径严格来说K8s 的 PV 更接近 LVM 的 LV 加上实际存储载体而 StorageClass 更接近 VG 的“分配策略”。但这不影响我们用 LVM 的思考方式去理解 K8s先有资源池再按需切卷业务只认挂载点不关心底层出处。更有趣的是这两套体系在真实产品里还会直接叠加。比如 TopoLVM、OpenEBS LocalPV 这类存储插件就是在 Kubernetes 节点上调用 Linux LVM 来创建逻辑卷然后把逻辑卷映射给 Pod。也就是说你写一个 PVC 申请 5Gi 空间K8s 的 StorageClass 会触发插件在节点上执行lvcreate最终把一个 LV 挂给 Pod 使用。这时候K8s 的 PV/PVC/StorageClass、Linux 的 PV/VG/LV就在同一条链路里真实相遇了。如果你只是想在 K8s 里跑有状态服务建议先理解好 PVC 和 StorageClass 的绑定逻辑再决定底层是用本地 LVM、NFS 还是云盘不要一上来就被缩写绕晕。6. 运维日常LVM 高频故障与排查现场6.1 重启后 VG 无法自动激活症状系统启动到一半卡在类似A start job is running for LVM...的界面最后进入 emergency mode。常见原因有三个/etc/fstab里写了 LVM 设备路径但 LVM 服务还没激活时就尝试挂载initramfs 里缺少 LVM 工具导致启动阶段无法激活 VG多路径环境下设备路径没有及时出现。排查顺序# 先看 LVM 是否能识别 VG vgscan # 手动激活所有卷组 vgchange -ay # 如果 lvs 能看到 LV说明数据还在 lvs临时救起来后要根治就重建 initramfs并且检查/etc/lvm/lvm.conf里的auto_activation_volume_list确保没有过滤掉这个 VG。有些发行版默认只自动激活根卷组其他 VG 需要手动设置。6.2 明明有 free 空间却创建失败有时候vgs显示VFree还有几十 G但执行lvcreate -L 100G却报“Insufficient free space”。这多数是PE 对齐导致的。假设 PE 大小为 4MB一个 VG 的可用空间是 100.2G但你恰好想分配 100.5GLVM 会告诉你空间不足。解决办法是不要用带小数的容量尽量用整数 G或者用百分比# 使用剩余空间的百分比 lvcreate -l 80%FREE -n lv_www vg_data-l后面跟的是 PE 数或百分比-L后面跟的是容量。用-l 100%FREE可以瞬间把 VG 剩余空间全划给一个 LV。这个命令很常用也很危险因为划完就没了。6.3 缩容踩坑文件系统顺序前面提到过缩容顺序这里再展开说一个真实案例。我处理过一台 MySQL 服务器运维同学想从 500G 数据卷里分出 100G 给别的业务他看到文档说“先缩文件系统再缩 LV”但实际操作时他用umount后直接执行了lvreduce -L 400G /dev/vg_data/lv_mysql然后才去执行resize2fs。结果是 LV 已经变成 400G但文件系统认为还是 500Gresize2fs直接报错并且因为卷尾的数据被截断部分数据目录出现 IO 错误。最后花了一整天才从备份恢复。所以这里必须明确# 正确缩容 ext4 流程 umount /data e2fsck -f /dev/vg_data/lv_data resize2fs /dev/vg_data/lv_data 400G lvreduce -L 400G /dev/vg_data/lv_data mount /data如果是 xfs直接放弃缩容这条路换方案。6.4 删除 PV 与 VG 时的连锁反应删除 PV 或 VG 时最常见的错误是“想删一个 PV但它正被 LV 占用”。系统会提示PV /dev/sdc is used by LV告诉你这个 PV 上还有数据映射。此时不能直接pvremove否则会导致 LV 数据丢失。正确做法是先把该 PV 上的数据迁移走# 把 /dev/sdc 上的数据搬到同 VG 其他 PV pvmove /dev/sdc # 确认没有数据后从 VG 里移除 vgreduce vg_data /dev/sdc # 再删除 PV pvremove /dev/sdc如果删的是整个 VG也必须先删掉 VG 里所有 LV再执行vgremove最后对 PV 执行pvremove。顺序反了LVM 会阻止你或者直接产生孤儿 VG。我还遇到过一个情况用pvremove删掉一个很久不用的旧盘系统提示成功但vgs里还残留旧 VG 信息。这通常是/etc/lvm/archive和/etc/lvm/backup里的元数据缓存执行vgscan --cache或重启后即可刷新。最后再分享一个实际体会我用 LVM 这么多年最大的感受是它真的能救急但也真的需要敬畏。扩容、加盘、做快照这些操作虽然命令简单一旦遇到“数据还在盘上但元数据乱了”的场景恢复起来相当费劲。我的个人习惯是第一涉及缩容、删 LV、删 VG 这类逆向操作永远先备份第二改了/etc/fstab之后一定要mount -a验证再重启第三给根分区用 LVM 的机器升级内核或重新生成 initramfs 后务必检查启动能否识别 dm 和 lvm 工具别让系统永远卡在启动阶段。这几点听起来都是小事但往往就是它们决定了你下一个凌晨是被电话叫醒还是安稳睡到天亮。
返回列表