libvirt挂载Ceph RBD母盘必须用type='network' protocol='rbd'直连方式,而非rbd map映射的/dev/rbdX设备,因其独占性、不支持快照克隆链且绕过librbd逻辑;母盘需启用layering特性、禁用exclusive-lock等冗余特性,并在disk XML中显式声明readonly='yes'。

libvirt 挂载 Ceph RBD 块存储作为虚拟机母盘,本质是让 qemu 通过 librbd 直接访问 RBD 镜像,不经过本地文件系统或内核 RBD 模块映射。这种方式避免了中间层开销,也支持 OpenStack 场景下的快照克隆链(如 Glance RAW 镜像 + Cinder 卷克隆),但必须用 raw 格式、禁用 QCOW2、且镜像需启用 layering 特性。
为什么不能直接用 rbd map + /dev/rbdX 当作母盘?
能挂,但不适合当“母盘”——尤其涉及克隆、快照、多虚拟机共享基础镜像时:
- rbd map 映射出的 /dev/rbd0 是独占式块设备,无法被多个 qemu 进程同时以写方式打开
- libvirt 的 disk XML 中若填 type='block' + source dev='/dev/rbd0',会因设备锁冲突导致第二台虚拟机启动失败
- 更关键的是:它绕过了 librbd 的快照/克隆逻辑,无法支撑 rbd clone 生成的写时复制子镜像(即所谓“母盘 → 快照 → 克隆卷”链)
- 所以生产中真正用于母盘的,一定是 type='network' + protocol='rbd' 的直连方式
virsh 定义虚拟机时如何写 RBD 母盘的 disk XML?
核心是三要素:协议类型、镜像路径、认证密钥。示例片段如下:
<disk type='network' device='disk'>
<driver name='qemu' type='raw' cache='writeback'/>
<auth username='client.admin'>
<secret type='ceph' uuid='72ebf201-c2a7-4301-9291-95099b251d00'/>
</auth>
<source protocol='rbd' name='rbd_pool/my-base-image'>
<host name='10.1.254.11' port='6789'/>
</source>
<target dev='vda' bus='virtio'/>
</disk>注意要点:
- type='raw' 是硬性要求;Glance 上传镜像时也必须用 qemu-img convert -f qcow2 -O raw 转换
- cache='writeback' 可提升性能,但要求 guest 内核 >= 2.6.32 并开启 barrier(默认已满足)
- uuid 对应的 libvirt secret 必须提前定义,且 secret 内容是 base64 编码后的 Ceph 密钥(不是明文 keyring 文件内容)
- 若 Ceph 集群启用了 CRUSH rule 或非默认 pool,name 中的 pool 名必须显式写出,不能省略
母盘镜像必须开启哪些 RBD 特性?
仅 layering 一项不够,但它是克隆链存活的前提。实际部署中建议:
-
rbd feature enable mypool/my-base-image layering—— 必开,否则rbd clone报错 “image must have layering feature enabled” -
rbd feature disable mypool/my-base-image exclusive-lock object-map fast-diff deep-flatten—— 推荐关闭,这些特性在母盘场景下无意义,反而增加元数据负担和兼容风险 - 确认镜像未被 map 或正在被 qemu 使用:
rbd status mypool/my-base-image应返回 “No watchers” - 母盘本身不应有快照;若需克隆,先
rbd snap create再rbd clone,克隆出的子卷才可作为虚拟机盘
常见报错与定位点
启动虚拟机失败时,优先查这三处:
-
error: internal error: process exited while connecting to monitor: qemu-kvm: -drive ...: could not open disk image rbd:mypool/my-base-image: Invalid argument→ 多半是layering未启用,或 secret uuid 错误/未定义 -
libvirtError: Unable to find auth secret for username client.admin→virsh secret-list看不到对应 uuid,或virsh secret-get-value解码后不是正确的 base64 密钥 - 虚拟机启动后 I/O 极慢甚至卡死 → 检查 Ceph 客户端节点是否加载了
rbd内核模块(lsmod | grep rbd),librbd 在用户态运行,但某些旧版内核存在模块冲突
母盘最脆弱的地方不在配置,而在生命周期管理:一旦被某台虚拟机以 read-write 方式直接挂载,就失去了作为“只读母盘”的语义,后续克隆将失效。务必确保母盘镜像在 libvirt XML 中始终以 readonly='yes' 显式声明(即使没写,qemu 默认也是只读打开 network 类型 RBD)。

















