AI Infra 训练营
总览
  • Day 1 · 集群起步 + CNI
  • Day 2 · 控制面 + etcd
  • Day 3 · CRD + Operator + Webhook
  • Day 4 · 存储深度
  • Day 5 · 卷扩容 + 安全
  • Day 6 · 调度 + 可观测
  • Day 7 · Harbor + ArgoCD + Mesh
  • Day 8 · AI Infra
  • Day 9 · Triton + GPU
  • Day 10 · MIG + HPA + 量化
  • Day 11 · AI Agent 端到端
  • Day 12 · 灾备
  • Day 13 · Operator + 联邦 + Mesh + RAG
  • Day 14 · CKA / CKS + 总结
  • LLM 训练手册
  • RAG + Agent 手册
  • 推理优化手册
  • 上下文工程手册
  • Agent 开发手册
  • 面试深度复盘
  • 训练 v2 深度手册
  • 心智模型
  • 看懂命令输出
  • 容器网络底层
  • K8s 网络深入
  • DNS 全套
  • 故障排查方法论
  • 心智模型
  • 容器挂载完整指南
  • K8s Volumes 大全
  • PV/PVC/CSI 深入
  • NFS 深入
  • 分布式存储概览
  • 故障排查 runbook
HiHuo 主站
GitHub
总览
  • Day 1 · 集群起步 + CNI
  • Day 2 · 控制面 + etcd
  • Day 3 · CRD + Operator + Webhook
  • Day 4 · 存储深度
  • Day 5 · 卷扩容 + 安全
  • Day 6 · 调度 + 可观测
  • Day 7 · Harbor + ArgoCD + Mesh
  • Day 8 · AI Infra
  • Day 9 · Triton + GPU
  • Day 10 · MIG + HPA + 量化
  • Day 11 · AI Agent 端到端
  • Day 12 · 灾备
  • Day 13 · Operator + 联邦 + Mesh + RAG
  • Day 14 · CKA / CKS + 总结
  • LLM 训练手册
  • RAG + Agent 手册
  • 推理优化手册
  • 上下文工程手册
  • Agent 开发手册
  • 面试深度复盘
  • 训练 v2 深度手册
  • 心智模型
  • 看懂命令输出
  • 容器网络底层
  • K8s 网络深入
  • DNS 全套
  • 故障排查方法论
  • 心智模型
  • 容器挂载完整指南
  • K8s Volumes 大全
  • PV/PVC/CSI 深入
  • NFS 深入
  • 分布式存储概览
  • 故障排查 runbook
HiHuo 主站
GitHub

LVM —— pvcreate / vgcreate / lvcreate 三件套

一句话定义

LVM (Logical Volume Manager) 把多个物理盘虚拟化成"逻辑卷",提供动态分区 / 在线扩容 / snapshot / 跨盘聚合 等能力。企业 Linux 95% 系统都用 LVM——比传统分区灵活十倍。

典型场景

  • 装机时让系统盘可以动态扩容(不预先划死)
  • K8s Local PV 用 LVM 动态切给不同 PV
  • 数据盘加大:扩物理盘 → LVM 扩 LV → 文件系统扩
  • 生产 snapshot(备份 / 测试)
  • 多盘聚合成一个大 LV

1. LVM 心智模型

graph TB
    subgraph 物理层
        D1["/dev/sda"]
        D2["/dev/sdb"]
        D3["/dev/sdc"]
    end

    subgraph LVM层[LVM 抽象层]
        PV1[PV /dev/sda]
        PV2[PV /dev/sdb]
        PV3[PV /dev/sdc]
        VG["VG: data-vg<br>(三个 PV 合一)"]
        LV1["LV: mysql<br>(50G)"]
        LV2["LV: logs<br>(30G)"]
        LV3["LV: kafka<br>(100G)"]
    end

    subgraph 文件系统
        FS1["ext4 on /dev/data-vg/mysql"]
        FS2["xfs on /dev/data-vg/logs"]
        FS3["ext4 on /dev/data-vg/kafka"]
    end

    D1 --> PV1
    D2 --> PV2
    D3 --> PV3
    PV1 --> VG
    PV2 --> VG
    PV3 --> VG
    VG --> LV1
    VG --> LV2
    VG --> LV3
    LV1 --> FS1
    LV2 --> FS2
    LV3 --> FS3

    style 物理层 fill:#e1f5ff
    style LVM层 fill:#ffe1f5
    style 文件系统 fill:#fff4e1

三层抽象

层命令前缀干什么
PV (Physical Volume)pv*把物理盘 / 分区"标记"成 LVM 可用
VG (Volume Group)vg*把多个 PV 聚合成"存储池"
LV (Logical Volume)lv*从 VG 里切出"逻辑卷"给应用用

对应关系:

PV (物理盘)       VG (存储池)        LV (逻辑卷)         应用
/dev/sda     ┐                  ┌─ mysql (50G) ─→ MySQL 数据
/dev/sdb     ├─→ data-vg ──────►├─ logs  (30G) ─→ 日志
/dev/sdc     ┘                  └─ kafka (100G)─→ Kafka

与传统分区的区别

维度传统分区 (fdisk / parted)LVM
大小创建时固定动态扩缩
跨盘❌✅(多盘合一)
Snapshot❌✅
在线操作受限✅
复杂度简单中等

2. 一次完整 LVM 操作

完整流程
# 0. 看现有盘
lsblk
# NAME   SIZE   TYPE
# sda    100G   disk            ← 我们要用这块新盘

# 1. 让 LVM "接管" 物理盘(创建 PV)
pvcreate /dev/sda
# Physical volume "/dev/sda" successfully created

# 2. 把这块盘放进一个 VG(存储池)
vgcreate data-vg /dev/sda
# Volume group "data-vg" successfully created

# 3. 从 VG 里切个 LV 出来
lvcreate -n mysql -L 50G data-vg
# Logical volume "mysql" created

# 4. 在 LV 上建文件系统
mkfs.ext4 /dev/data-vg/mysql

# 5. 挂载
mkdir -p /var/lib/mysql
mount /dev/data-vg/mysql /var/lib/mysql

# 6. 持久化(fstab)
echo "UUID=$(blkid -s UUID -o value /dev/data-vg/mysql) /var/lib/mysql ext4 defaults,nofail 0 2" >> /etc/fstab
看状态
# 看所有 PV
$ pvs
  PV         VG       Fmt  Attr PSize    PFree
  /dev/sda   data-vg  lvm2 a--  100.00g  50.00g     ← 50G 剩余

# 看所有 VG
$ vgs
  VG       #PV #LV #SN Attr   VSize    VFree
  data-vg  1   1   0   wz--n- 100.00g  50.00g

# 看所有 LV
$ lvs
  LV    VG       Attr       LSize   Pool Origin Data%
  mysql data-vg  -wi-ao---- 50.00g

# 详细信息
pvdisplay
vgdisplay
lvdisplay
用块设备名
/dev/<VG>/<LV>          # 友好路径 (符号链接)
/dev/mapper/<VG>-<LV>   # 真实路径

# 比如:
/dev/data-vg/mysql
/dev/mapper/data--vg-mysql   ← 注意 -- (因为 VG 名含 -)

3. 扩容(LVM 最杀手锏的能力)

在线扩 LV + 文件系统

# 看当前
$ lvs
  LV    VG       LSize
  mysql data-vg  50.00g

# 扩到 80G(绝对值)
$ lvextend -L 80G /dev/data-vg/mysql
  Size of logical volume data-vg/mysql changed from 50.00 GiB to 80.00 GiB

# 或者增加 30G(相对值)
$ lvextend -L +30G /dev/data-vg/mysql

# 或者用所有剩余空间
$ lvextend -l +100%FREE /dev/data-vg/mysql

# ⚠️ 文件系统还是 50G!要扩文件系统
$ df -h /var/lib/mysql
/dev/mapper/data--vg-mysql  50G  10G  40G  20%

# ext4 扩容
$ resize2fs /dev/data-vg/mysql

# xfs 扩容(参数是挂载点不是设备)
$ xfs_growfs /var/lib/mysql

# 再看
$ df -h /var/lib/mysql
/dev/mapper/data--vg-mysql  80G  10G  70G  13%

一步搞定:-r 自动 resize 文件系统

$ lvextend -L +30G -r /dev/data-vg/mysql
                   ^^
                   --resizefs 自动检测 fs 类型 + 扩文件系统

生产推荐 -r——避免忘扩 fs。

扩 VG(加新盘到现有 VG)

# 1. 新盘 /dev/sdb 接入
$ lsblk
sdb  200G  disk     ← 新盘

# 2. 创建 PV
$ pvcreate /dev/sdb

# 3. 加进现有 VG
$ vgextend data-vg /dev/sdb

# 4. 现在 VG 多了 200G 可用
$ vgs
  VG       #PV #LV  VSize   VFree
  data-vg  2   1    300g    250g    ← 多了 200G 余量

# 5. 可以继续 lvextend
$ lvextend -L +200G -r /dev/data-vg/mysql

扩 PV(底层云盘扩了之后)

# 云控制台扩了云盘从 100G 到 500G

# 1. 重新扫盘(让内核认到新大小)
$ partprobe /dev/sda
# 或:
$ echo 1 > /sys/block/sda/device/rescan

$ lsblk /dev/sda
sda  500G   disk    ← 看到新大小

# 2. 让 PV 用新大小
$ pvresize /dev/sda
  Physical volume "/dev/sda" changed
  1 physical volume(s) resized

$ pvs
  PV         VG       PSize    PFree
  /dev/sda   data-vg  500g     400g    ← VG 自动得到新空间

# 3. lvextend + resize2fs/xfs_growfs

4. 缩容(慎用)

缩容是有风险的操作

LVM 缩 LV 操作顺序不能错,错了数据丢。

xfs 不能缩。ext4 可以但要 umount。

ext4 缩容步骤

# 1. umount(**必须**)
umount /var/lib/mysql

# 2. fsck 检查
e2fsck -f /dev/data-vg/mysql

# 3. 先缩文件系统(**必须先于 LV**)
resize2fs /dev/data-vg/mysql 40G

# 4. 再缩 LV
lvreduce -L 40G /dev/data-vg/mysql
# 提示确认

# 5. 挂回
mount /dev/data-vg/mysql /var/lib/mysql

# 6. 一致性最终检查
e2fsck -f /dev/data-vg/mysql

或者用 -r 一气:

umount /var/lib/mysql
lvreduce -L 40G -r /dev/data-vg/mysql        # -r 自动处理 fs
mount /dev/data-vg/mysql /var/lib/mysql

生产几乎不缩 LV——除非真要释放空间。改"少用一点"通常更安全。


5. Snapshot(LVM 的另一杀手锏)

# 创建快照(10G 空间存储变化数据)
$ lvcreate -L 10G -s -n mysql-snap /dev/data-vg/mysql
                 ^^
                 --snapshot
  Logical volume "mysql-snap" created.

$ lvs
  LV          VG       Attr        LSize   Pool Origin Data%
  mysql       data-vg  owi-aos---- 50.00g
  mysql-snap  data-vg  swi-a-s---- 10.00g       mysql  0.05%
                                                ^^^^^^
                                                snapshot 的源

Snapshot 怎么工作

graph LR
    A[mysql<br>原始 LV] -->|开 snapshot 时<br>所有数据共享| B[mysql-snap<br>10G COW 空间]

    A -.开始变化.-> A2[mysql 修改后<br>新数据写到 mysql]
    B -.保留原始.-> B2[mysql-snap<br>仍然看 snapshot 时刻的数据]

LVM snapshot 是 Copy-On-Write (COW):

  • snapshot 创建时几乎瞬间(只是记录元数据)
  • 原始 LV 数据变化时、旧数据被复制到 snapshot 空间
  • snapshot 大小 = 你预留的"变化空间"

用 snapshot 做一致性备份

# 1. 创建 snapshot(瞬间)
lvcreate -L 10G -s -n mysql-snap /dev/data-vg/mysql

# 2. 挂 snapshot(**read-only**)
mkdir -p /mnt/snap
mount -o ro /dev/data-vg/mysql-snap /mnt/snap

# 3. 备份 snapshot 内容
rsync -a /mnt/snap/ /backup/mysql-$(date +%F)/

# 4. 备份完成、卸载 + 删 snapshot
umount /mnt/snap
lvremove -y /dev/data-vg/mysql-snap

好处:备份时不影响线上 MySQL——MySQL 继续写、snapshot 是冻结的时间点视图。

Snapshot 空间用完会怎样

$ lvs
  LV          ...  Data%
  mysql-snap       100.00%       ← 满了!

→ snapshot 失效(不再能读 snapshot 内容)→ 原始 LV 正常。

记得监控 snapshot 用量、定期清。


6. 删除操作

# 删 LV
$ umount /var/lib/mysql              # 先卸载
$ lvremove /dev/data-vg/mysql
Do you really want to remove active logical volume mysql? [y/n]: y

# 从 VG 移除 PV(先确保 PV 上没数据)
$ pvmove /dev/sdb                    # 把数据移到其它 PV
$ vgreduce data-vg /dev/sdb          # 从 VG 移除

# 删 PV 标记(让盘回归普通)
$ pvremove /dev/sdb

# 删 VG
$ vgremove data-vg                    # 必须先 lvremove 所有 LV

7. 生产实战场景

场景 1:根分区用 LVM、可扩容

装机时把根分区做成 LVM——以后空间不够直接扩。

# 装机时分区:
/dev/sda1   /boot      1G      ext4 (普通分区、不是 LVM)
/dev/sda2   PV (rest)  99G    → 整个 VG: ubuntu-vg
              ├─ LV: root     30G    → /
              ├─ LV: swap     4G     → swap
              └─ LV: home     65G    → /home

# 现在 / 满了 → 怎么办?
# 方案 A: 扩底层盘 / 加新盘到 VG、扩 LV
# 方案 B: 缩 /home、扩 /

场景 2:K8s Local PV via LVM

# 每个节点上预先用 LVM 切多个 LV
$ lvcreate -L 100G -n pv-001 data-vg
$ lvcreate -L 100G -n pv-002 data-vg
$ lvcreate -L 100G -n pv-003 data-vg

$ mkfs.ext4 /dev/data-vg/pv-001
# ... pv-002, pv-003 同

$ mount /dev/data-vg/pv-001 /mnt/disks/pv-001
# fstab 持久

# K8s Local PV
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-001-m4
spec:
  capacity:
    storage: 100Gi
  local:
    path: /mnt/disks/pv-001
  nodeAffinity:
    required:
      nodeSelectorTerms:
        - matchExpressions:
            - key: kubernetes.io/hostname
              operator: In
              values: [m4]

详见 03-pv-pvc-storageclass.md。

场景 3:TopoLVM —— 自动用 LVM 做 K8s 动态 Local PV

TopoLVM 是 K8s CSI driver,自动:

  • 节点上的 LVM VG 看作 K8s 存储池
  • PVC 创建时自动 lvcreate 一个 LV
  • 调度时把 pod 调度到 VG 有足够空间的节点
# StorageClass
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: topolvm-ssd
provisioner: topolvm.io
parameters:
  csi.storage.k8s.io/fstype: ext4
  "topolvm.io/device-class": "ssd"
volumeBindingMode: WaitForFirstConsumer

生产 Local PV 自动化的最优解。

场景 4:用 snapshot 做"安全升级"

# 升级数据库之前 snapshot
lvcreate -L 50G -s -n mysql-presnap /dev/data-vg/mysql

# 升级
mysql_upgrade

# 升级失败 → 回滚(merge snapshot)
umount /var/lib/mysql
lvconvert --merge /dev/data-vg/mysql-presnap
mount /dev/data-vg/mysql /var/lib/mysql

# 升级成功 → 删 snapshot
lvremove -y /dev/data-vg/mysql-presnap

数据库 / 关键服务的"安全升级"标准动作。


8. LVM 与文件系统选择

LV 用途文件系统理由
通用 / 系统ext4稳定、生态成熟
大文件 / 数据库xfs大文件性能好、动态 inode
容器 overlayext4containerd 默认
不要btrfs跟 LVM snapshot 概念重复、复杂

详见 mkfs.md。


9. 看 LVM 状态的命令汇总

# 简略
pvs              # 物理卷
vgs              # 卷组
lvs              # 逻辑卷

# 详细
pvdisplay
vgdisplay
lvdisplay -m     # -m 显示 segment 详情

# 看 LV 的盘 mapping(哪些 PV 上有这个 LV 的数据)
lvs -o +devices

# 看某 LV 详细 + segment 分布
lvdisplay -m /dev/data-vg/mysql

# 看一个 PV 上有哪些 LV
pvdisplay -m /dev/sda

# JSON 输出(脚本用)
lvs --reportformat json

lvs 常看的列

$ lvs -a -o +devices,segtype
  LV    VG       Attr        LSize   Pool Origin Data%  Devices             Type
  mysql data-vg  -wi-ao----  50.00g                     /dev/sda(0)         linear
  logs  data-vg  -wi-ao----  30.00g                     /dev/sda(12800)     linear
  kafka data-vg  Vwi-aotz-- 100.00g pool        25.00%                       thin
列含义
Attr9 位状态码(详见下面)
LSize逻辑大小
Poolthin pool 的 pool name
Originsnapshot 的源
Data%thin pool / snapshot 用量
Devices数据实际在哪些 PV 上
Typelinear / striped / mirror / thin

Attr 9 位(按位置):

位含义取值
1volume 类型-=linear, s=snapshot, m=mirror, t=thin pool, V=thin volume
2权限w=可写, r=只读
3allocationi=inherited, a=allocate anywhere
4fixed minor-=不固定
5状态a=active, s=suspended
6设备打开o=open(被用着)
7target typet=thin, s=snapshot
8一致性z=zeroed
9健康p=partial, -=正常

实战经验:

  • -wi-ao----:linear、可写、active、open(正常用着)
  • -wi-a-----:linear、可写、active、没人 mount
  • Vwi-aotz--:thin volume、可写、active、open、thin、zeroed(thin LV 正常)

10. Thin Provisioning —— 进阶

普通 LV 是 thick provision——创建时立刻占用 VG 空间。

Thin LV 是 稀疏分配——创建 100G LV 但实际只用 10G 时只占 10G。

# 1. 创建 thin pool(占用真实空间)
lvcreate -L 100G -T data-vg/thin-pool
                 ^^
                 thin pool

# 2. 从 thin pool 创建 thin volumes
lvcreate -V 50G -T data-vg/thin-pool -n vol1     # 50G "虚拟"
lvcreate -V 50G -T data-vg/thin-pool -n vol2     # 50G "虚拟"
lvcreate -V 50G -T data-vg/thin-pool -n vol3     # 50G "虚拟"

# 总共 150G 声明、但 pool 只 100G
# 只要实际使用 ≤ 100G 就 OK

好处:

  • 过度分配 —— 给用户 / 应用承诺更大空间、按需扩展
  • 快照高效 —— Thin snapshot 占用更小
  • storage class 灵活 —— 适合 K8s

风险:

  • 超额使用 —— 用户真用满了、所有 LV 一起挂
  • 监控关键 —— 看 Data%、超 80% 必须扩
$ lvs
  LV         VG       Attr        LSize   Pool      Data%
  thin-pool  data-vg  twi-aotz-- 100.00g                75.00%        ← 75% 用了
  vol1       data-vg  Vwi-aotz-- 50.00g  thin-pool      30.00%
  vol2       data-vg  Vwi-aotz-- 50.00g  thin-pool      40.00%

监控 Data% < 80%。满了扩 pool:

lvextend -L +50G data-vg/thin-pool

11. 反面教材

反面 1:扩 LV 但忘扩文件系统

lvextend -L +30G /dev/data-vg/mysql
df -h /var/lib/mysql
# 还是老大小

修:加 -r:

lvextend -L +30G -r /dev/data-vg/mysql

养成习惯:lvextend 永远加 -r。

反面 2:缩容顺序错

# 错的:先缩 LV
lvreduce -L 30G /dev/data-vg/mysql
# 文件系统还是 50G、但底层 LV 只 30G → 文件系统损坏

正确顺序:

umount + resize2fs 缩 fs → lvreduce
# 或用 lvreduce -r 自动处理

xfs 根本不能缩。

反面 3:snapshot 空间太小、忽然失效

lvcreate -L 1G -s -n mysql-snap /dev/data-vg/mysql

# 几个小时后 mysql 写了 2G 数据
$ lvs
  mysql-snap  ...  100.00%        ← 满了,失效

snapshot 大小应该是预期变化量 + 余量。50G LV 一天可能变化 5-10G、snapshot 给 20G。

或者用 thin snapshot(用 thin pool 资源、不预分配)。

反面 4:误删 PV 标记

pvremove /dev/sda                     # 在还在用的 PV 上跑!

PV 标记没了 → VG metadata 损坏。生产事故级。

防御:pvremove 永远在 vgreduce 之后、确认没在用。

恢复:

# 看 VG 备份
ls /etc/lvm/backup/
ls /etc/lvm/archive/

# 还原 metadata(如果有备份)
vgcfgrestore -f /etc/lvm/backup/data-vg data-vg

反面 5:用 sudo 远程 lvextend 但忘了

$ ssh m4 lvextend -L +30G -r /dev/data-vg/mysql
# Permission denied

ssh m4 'sudo lvextend ...' 或者直接 ssh root 进去。

反面 6:thin pool 数据满 = 所有 thin LV 挂

$ lvs
  thin-pool   ...  100.00%        ← 满了
  vol1        ...  -p--------    ← partial!数据写入失败

修:紧急扩 thin pool:

lvextend -L +50G data-vg/thin-pool

预防:监控 thin pool Data% < 80%。

反面 7:不知道 LVM 配置位置

# 系统配置 (LVM 行为):
/etc/lvm/lvm.conf

# 备份 (自动)
/etc/lvm/backup/<vg-name>      ← 当前 VG 配置
/etc/lvm/archive/<vg-name>     ← 历史版本

# 看 LVM 全局参数
lvmconfig

VG 损坏时 /etc/lvm/backup/ 是救命的。别误删。


12. 排查 cheatsheet

"LV 看不到 / 设备不存在"

# 1. PV / VG / LV 都正常吗
pvs
vgs
lvs

# 2. LV active 吗
$ lvs
  LV    Attr        ...
  mysql -wi-a-----                  ← 第 5 位 a = active;- = inactive

# 3. 激活
$ vgchange -ay data-vg                # active 所有 LV
# 或
$ lvchange -ay /dev/data-vg/mysql     # 单个

# 4. 设备节点
ls /dev/data-vg/
ls /dev/mapper/

"VG metadata 损坏"

# 看 VG 状态
$ vgs --foreign --readonly
$ vgs -v

# 强制激活
$ vgchange -ay --partial

# 从备份恢复
$ vgcfgrestore -f /etc/lvm/archive/data-vg_xxx.vg data-vg

最坏情况:找 LVM 专家或者从备份恢复整个盘。

"PV missing"

$ vgs
  WARNING: ... PV /dev/sdb is missing
  VG       #PV #LV
  data-vg  2   3                    ← 但显示只有 1 PV 可用

# 看缺哪个
$ vgs -o +pv_uuid_attr

# 修复
$ vgreduce --removemissing data-vg   # 移除 missing PV(数据会丢)
# 或
$ vgcfgrestore data-vg               # 如果有备份

13. 关联命令

  • lsblk —— 看块设备 / LV 一起看
  • mkfs —— LV 上建文件系统
  • mount / fstab —— 挂载 LV
  • parted —— LVM 之前的分区
  • iostat —— 看 LV I/O 性能
  • findmnt —— 看挂载视角
  • dmsetup —— LVM 底层 device-mapper 命令
  • vgcfgbackup / vgcfgrestore —— VG 配置备份恢复
在 GitHub 上编辑此页