字数 1364,阅读大约需 7 分钟
虚拟化和容器是 LVM 的"高光场景"。本篇讲清 KVM 虚拟机使用 LV 作为磁盘、Thin Pool 给 VM 做超分配,以及 Docker/Podman 与 LVM 的集成。
一、KVM 与 LVM:天生一对
KVM 虚拟机默认使用 qcow2 文件作为磁盘镜像,但 qcow2 文件在文件系统上,性能有损失。直接使用 LVM LV 作为虚拟机磁盘:
┌──────────────────────────────────┐
│ KVM VM │
│ /dev/vda = /dev/vg_kvm/vm-001 │ ← 直接是 LV
├──────────────────────────────────┤
│ LVM(vg_kvm) │
├──────────────────────────────────┤
│ 物理盘 │
└──────────────────────────────────┘
优势:
二、给 VM 准备磁盘
2.1 创建专用 VG
# 创建专门给 VM 用的 VG
$ pvcreate /dev/sdb
$ vgcreate vg_kvm /dev/sdb
2.2 创建 VM 磁盘(普通模式)
# 100G 普通 LV
$ lvcreate -L 100G -n vm-web-001 vg_kvm
KVM 启动参数:
$ virt-install \
--name web-001 \
--ram 2048 \
--vcpus 2 \
--disk path=/dev/vg_kvm/vm-web-001,format=raw \
--cdrom /iso/centos.iso \
--os-variant rhel9 \
--network bridge=br0
format=raw 让 KVM 直接使用 LVM LV,无需 qcow2 包装层。
2.3 用 Thin Pool 给 VM 超分配
# 1. 创建 thin pool(实际 500G)
$ lvcreate -L 500G --thinpool tp_vms vg_kvm
# 2. 创建 VM 磁盘(虚拟 100G,每个 VM 可"占"100G,但实际只占用的)
$ lvcreate -V 100G --thin -n vm-db-001 vg_kvm/tp_vms
$ lvcreate -V 100G --thin -n vm-cache-001 vg_kvm/tp_vms
$ lvcreate -V 100G --thin -n vm-app-001 vg_kvm/tp_vms
这样 500G 的 pool 里可以"容纳"几个 100G 的 VM,总虚拟容量远大于 pool 真实容量。
KVM 用法不变:
$ virt-install \
--name db-001 \
--disk path=/dev/vg_kvm/vm-db-001,format=raw \
...
2.4 VM 快照(生产级用法)
# 普通 LV 快照
$ lvcreate -L 20G -s -n vm-db-001-snap /dev/vg_kvm/vm-db-001
# thin 快照(推荐,几乎不占空间)
$ lvcreate -s --thin -n vm-db-001-snap /dev/vg_kvm/vm-db-001
恢复快照(危险操作,回滚前必须先关闭 VM):
# 1. 关闭 VM
$ virsh shutdown vm-db-001
# 2. 删除原 LV(注意:先备份)
$ lvremove /dev/vg_kvm/vm-db-001
# 3. 合并快照(用 lvconvert --merge)
$ lvconvert --merge /dev/vg_kvm/vm-db-001-snap
# 4. 重启 VM
$ virsh start vm-db-001
或者用 libvirt 的快照管理(推荐):
# 创建快照(libvirt 帮你处理)
$ virsh snapshot-create-as vm-db-001 snap1 "before upgrade"
# 看快照
$ virsh snapshot-list vm-db-001
# 回滚
$ virsh snapshot-revert vm-db-001 snap1
三、Libvirt 自动管理 Thin Pool
Libvirt 可以自动管理 thin pool:
3.1 配置 pool
编辑 /etc/libvirt/storage.conf 或使用 virsh pool-define-as:
$ virsh pool-define-as vg_kvm logical --source-name vg_kvm --target /dev/vg_kvm
$ virsh pool-start vg_kvm
$ virsh pool-autostart vg_kvm
3.2 创建 thin pool volume
# 创建 100G 虚拟大小的 thin volume
$ virsh vol-create-as vg_kvm vm-thin-001 100G --format raw --allocation 0
--allocation 0 表示按需分配。
3.3 创建 VM 时直接指定
$ virt-install \
--name vm-thin-001 \
--disk vol=vg_kvm/vm-thin-001,format=raw \
...
四、Docker / Podman 与 LVM
4.1 Docker devicemapper 存储驱动(已废弃)
Docker 早期使用 devicemapper 驱动直接管理 LVM:
# /etc/docker/daemon.json
{
"storage-driver": "devicemapper",
"storage-opts": [
"dm.thinpooldev=/dev/mapper/vg_docker-thinpool",
"dm.use_deferred_removal=true",
"dm.use_deferred_deletion=true"
]
}
警告:Docker 18+ 强烈推荐使用 overlay2 而不是 devicemapper。后者已废弃。
4.2 推荐方式:Docker 用 overlay2,VM 磁盘用 LVM
现代 Docker/Kubernetes 的最佳实践:
Docker / K8s 物理卷 / 块存储
↓ ↑
overlay2 文件系统 LVM LV(thin)
↓
容器内文件系统
容器不需要直接用 LVM。但底层存储仍然可以是 LVM + thin pool:
[物理盘] → [LVM VG] → [Thin Pool] → [VM / DB / 容器持久化卷]
4.3 Kubernetes Local Persistent Volume
Kubernetes 用 local PV 绑定 LVM LV:
apiVersion: v1
kind: PersistentVolume
metadata:
name: lv-pv-data
spec:
capacity:
storage: 100Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: local-storage
local:
path: /dev/vg_kvm/lv-k8s-data
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- node-01
但生产 K8s 通常用 ceph / nfs / longhorn 等动态存储,本地 PV 不太灵活。
五、性能对比
生产推荐:LVM thin LV + format=raw。性能接近裸盘,快照/克隆能力强。
六、典型部署案例
案例:5 个 VM 的开发测试平台
# 物理资源:2 块 1TB SSD
# 1. 创建 RAID1
$ mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/sdb /dev/sdc
# 2. 直接用 RAID 设备做 PV(无加密)
$ pvcreate /dev/md0
$ vgcreate vg_kvm /dev/md0
# 3. 创建 thin pool(800G 实际空间,可"容纳"几个 TB 虚拟空间)
$ lvcreate -L 800G --thinpool tp_vms vg_kvm
# 4. 创建 VM 磁盘
$ lvcreate -V 100G --thin -n vm-control vg_kvm/tp_vms # 控制节点
$ lvcreate -V 100G --thin -n vm-worker1 vg_kvm/tp_vms # 工作节点
$ lvcreate -V 100G --thin -n vm-worker2 vg_kvm/tp_vms
$ lvcreate -V 200G --thin -n vm-db vg_kvm/tp_vms # 数据库
$ lvcreate -V 50G --thin -n vm-lb vg_kvm/tp_vms # 负载均衡
# 5. 安装 VM
$ virt-install --name control --disk path=/dev/vg_kvm/vm-control,format=raw ...
# 等等
七、容器持久化卷
7.1 Docker volume 用 LVM
# 创建 LV 给 Docker volume
$ lvcreate -L 50G -n lv-docker-data vg_data
$ mkfs.xfs /dev/vg_data/lv-docker-data
$ mount /dev/vg_data/lv-docker-data /var/lib/docker
# /etc/fstab
/dev/vg_data/lv-docker-data /var/lib/docker xfs defaults 0 0
或者用 thin pool:
$ lvcreate -L 100G --thinpool tp_docker vg_data
$ lvcreate -V 200G --thin -n lv-docker-data vg_data/tp_docker
$ mkfs.xfs /dev/vg_data/lv-docker-data
$ mount /dev/vg_data/lv-docker-data /var/lib/docker
7.2 Kubernetes 用 local-path-provisioner
# local-path-provisioner 自动在 /var/lib/... 下创建目录
# 但你可以配置它在 LVM LV 上创建:
# /var/lib/local-path-provisioner 放在 LV 上
$ lvcreate -L 50G -n lv-local-path vg_data
$ mkfs.ext4 /dev/vg_data/lv-local-path
$ mount /dev/vg_data/lv-local-path /var/lib/local-path-provisioner
八、本篇小结
KVM 场景:
容器场景:
核心建议:
- • VM 磁盘直接用 LVM LV(
format=raw)