Ceph RBD 块存储实战:从池创建到镜像映射挂载与避坑指南
简介这份PDF文档面向具备一定存储架构经验的云服务管理人员与开源分布式存储爱好者系统讲解Ceph块存储的部署与应用。内容以三节点实验集群为背景在Ubuntu 18.04环境下完成RBD池与块设备镜像的创建并演示将镜像映射为Linux块设备、格式化挂载及集群健康检查的完整流程涵盖存储池与镜像操作指令、映射后读写操作和状态监控方法帮助读者掌握搭建稳定Ceph集群的能力为虚拟化环境提供高效块存储方案。资源包共1个PDF文件约286KB内容紧凑、命令示范具体适合运维人员对照实践。目前已有70人学习可作为快速上手Ceph块存储的参考材料。1. 从三节点实验集群说起Ceph 块存储到底解决什么问题很多团队第一次接触分布式存储都是被单机磁盘的容量和可靠性逼到墙角的。业务跑在几台虚拟化宿主机上本地盘写满就得停机扩盘宿主机一挂数据就跟着悬。Ceph 块存储RBD解决的正是这个场景把多台机器的裸盘聚合成一个统一存储池再切出一块块虚拟磁盘挂给 Linux 当本地盘用容量能横向扩副本自动分布坏一块盘不影响业务。本文基于 Ceph 14.2.22 和 Ubuntu 18.04默认集群已经部署完成重点讲清楚 RBD 池怎么建、镜像怎么切、怎么映射成/dev/rbd0并挂载读写以及过程中那些不踩一遍不会知道的坑。适合有 Linux 基础、正在做虚拟化或容器持久化存储选型的运维和云平台工程师。2. 集群规划与 RBD 池创建先把地基量准2.1 节点角色划分与前置检查动手之前先把集群拓扑理清楚不然后面命令在哪个节点执行会乱。本文的规划是node0192.168.3.10只跑 ceph-deploy 管理工具不装 Ceph 服务不算集群节点node1192.168.3.11承担 mon、mgr 和 osd.0node2192.168.3.12跑 osd.1node3192.168.3.13跑 osd.2。三个 OSD 分布在三台机器上保证副本能跨物理机分布这是实验环境里最小可用的高可用拓扑。在 node1 上执行任何 RBD 操作前先确认集群健康状态和 OSD 数量。常见做法是跑一条ceph -s看到health: HEALTH_OK、3 osds: 3 up, 3 in才算就绪。如果 OSD 数量不对或者有 down 的先别急着建池否则后面 PG 状态会一直卡在activeundersized之类的异常态。另外确认当前用户有权限读写/etc/ceph/ceph.client.admin.keyringRBD 命令默认走 admin 密钥权限不对会直接报auth: failed to load keyring。2.2 创建数据池与 PG 数量怎么定RBD 镜像必须放在一个 pool 里所以第一步是建池。在 node1 上执行# 创建名为 rbd_pool 的数据池pg 和 pgp 数量都设为 1 ceph osd pool create rbd_pool 1 1这里rbd_pool是池名后面两个1分别是 pgplacement group和 pgppg for placement的数量。实验集群只有 3 个 OSD把 pg 设成 1 是为了避免 PG 数量超过 OSD 导致分布不均。生产环境不能这么干pg 数量要按OSD 总数 × 100 / 副本数再向上取 2 的幂来估算比如 3 个 OSD、3 副本pg 至少给到 32 或 64。pg 太少会导致单个 PG 承载过多数据、恢复慢pg 太多则增加 mon 的元数据压力。这是选型时最容易拍脑袋的地方血泪经验是宁可前期多算一遍也别等数据写进去再调 pg 数量那个操作叫 pg 分裂代价不小。池建好后可以顺手确认一下# 列出集群中所有 pool确认 rbd_pool 已存在 ceph osd pool ls如果这条命令没输出rbd_pool说明创建失败常见原因是 mon 仲裁没达成或者权限不足回到ceph -s看集群状态。2.3 创建块设备镜像与 format 2 的意义池有了接下来在池里切一块虚拟磁盘也就是 RBD 镜像。在 node1 上执行# 在 rbd_pool 中创建 1024MB 的镜像 image1使用 format 2 并开启 layering 特性 rbd create --pool rbd_pool --image image1 --size 1024 --image-format 2 --image-feature layering参数逐个说清楚--pool rbd_pool指定池名--image image1是镜像名--size 1024单位是 MB也就是 1GiB--image-format 2是关键format 1 是早期格式不支持克隆、快照分层等特性新集群一律用 format 2--image-feature layering开启分层这是做快照和克隆的前提。如果不显式指定 format某些旧版本客户端可能默认走 format 1后面想用高级特性就得重建镜像属于典型的后悔药场景。创建完立刻验证# 列出 rbd_pool 中的所有镜像 rbd ls rbd_pool # 查看 image1 的详细信息 rbd info --pool rbd_pool --image image1rbd info的输出里重点看几个字段size 1 GiB in 256 objects说明镜像被切成 256 个 4MiB 对象order 22 (4 MiB objects)是对象大小order 22 对应 2^22 字节即 4MiBformat: 2和features: layering确认格式和特性正确block_name_prefix: rbd_data.xxxx是对象前缀后面用rados ls查底层对象时会看到这个前缀。如果features里没有 layering说明创建时参数没生效需要删掉重建。3. 镜像映射与挂载让 Linux 把 RBD 当本地盘用3.1 rbd map 映射成块设备镜像建好只是 Ceph 内部的对象Linux 还看不到它。要让系统识别成一块盘得做映射。在 node1 上执行# 将 rbd_pool 中的 image1 映射为本地块设备 rbd map --pool rbd_pool --image image1这条命令背后是内核的 rbd 模块在干活它把 RBD 镜像通过 librbd 暴露成一个/dev/rbdX设备。执行成功会直接输出设备路径比如/dev/rbd0。如果报rbd: sysfs write failed大概率是内核 rbd 模块没加载先modprobe rbd再重试。另一个常见报错是RBD image feature set mismatch意思是镜像开了当前内核不支持的 feature比如exclusive-lock、object-map这些老内核认不全要么升级内核要么创建镜像时只开 layering。映射完确认一下# 查看当前所有已映射的 RBD 镜像 rbd showmapped输出会列出 id、pool、namespace、image、snap、device 六列。正常应该看到0 rbd_pool - image1 - /dev/rbd0。如果 device 列是空的或者显示-说明映射没真正完成检查 dmesg 里有没有 rbd 相关报错。3.2 格式化与挂载拿到/dev/rbd0之后它跟普通裸盘没区别需要格式化文件系统再挂载。在 node1 上执行# 格式化为 ext4-m0 表示不保留 root 预留空间 mkfs.ext4 -m0 /dev/rbd0 # 创建挂载点并挂载 mkdir -p /mnt/rbd mount /dev/rbd0 /mnt/rbdmkfs.ext4 -m0里的-m0是把 ext4 默认给 root 预留的 5% 空间设为 0。实验环境盘本来就小1GiB 的盘预留 5% 就是 50MB设成 0 能多出可用空间。生产环境是否设 0 要看业务如果跑的是数据库这类对空间敏感又不需要 root 预留的服务可以设 0普通场景保留默认更稳妥。挂载后用df -h确认# 查看挂载结果 df -h输出里应该出现一行/dev/rbd0 976M 1.3M 959M 1% /mnt/rbd。注意容量显示是 976M 而不是 1024M这是 ext4 文件系统元数据占用的正常现象不是镜像大小不对。如果df -h里看不到/mnt/rbd先mount | grep rbd看挂载是否成功再检查/etc/fstab有没有写错。3.3 读写验证与集群状态观察挂载好之后写点数据进去验证整条链路通不通# 拷贝一个测试文件到挂载点 cp test /mnt/rbd # 查看集群整体状态 ceph -s # 查看数据池使用状况 ceph dfceph -s的输出里io段会显示client: 3.0 KiB/s wr之类的实时读写速率说明客户端确实在往集群写数据。pgs: 3 activeclean表示所有 PG 状态正常。ceph df则从池的维度看用量rbd_pool那行的STORED是实际数据量USED是包含副本后的占用MAX AVAIL是还能写多少。这里有个容易误判的点ceph df里USED通常是STORED的副本数倍3 副本就是 3 倍左右别看到 USED 比 STORED 大就以为出问题了。最后看一眼底层对象# 列出 rbd_pool 中的 rados 对象 rados -p rbd_pool ls会看到一堆rbd_data.xxxx.00000000000000c9这样的对象名前缀就是之前rbd info里的block_name_prefix。每个对象对应镜像的一个 4MiB 分片写进去的文件就是被切成这些对象存到 OSD 上的。这一步能直观理解 RBD 的分片机制也是排查数据分布问题的入口。4. 避坑与排查那些不踩一遍不会知道的细节4.1 映射后设备名不固定现象重启或者重新映射后/dev/rbd0变成了/dev/rbd1脚本里写死的路径失效。原因rbd 设备号是按映射顺序分配的先映射的拿 rbd0释放后再映射可能拿到别的号。解决不要依赖固定设备名用rbd showmapped动态取 device 列或者用/dev/rbd/rbd_pool/image1这种带池名和镜像名的稳定路径需要 udev 规则支持常见做法是配置/etc/udev/rules.d/下的 rbd 规则。4.2 内核 rbd 模块不支持镜像特性现象rbd map报RBD image feature set mismatch或者映射成功但读写报 I/O error。原因镜像开启了当前内核不认识的 feature比如exclusive-lock、object-map、fast-diff、deep-flatten这些Ubuntu 18.04 默认内核4.15对部分特性支持不全。解决创建镜像时只开layering或者用rbd feature disable关掉不支持的特性再映射。如果镜像已经建好且不想重建可以rbd feature disable rbd_pool/image1 exclusive-lock object-map fast-diff deep-flatten逐个关掉。4.3 PG 数量设成 1 导致分布不均现象实验环境把 pg 设成 1所有数据都落在同一个 PG 上而这个 PG 只映射到部分 OSD导致其他 OSD 空闲、集群容量利用率低。原因pg 数量太少CRUSH 算法无法把数据均匀打散到所有 OSD。解决实验环境可以接受生产环境必须按公式估算 pg 数并且用ceph osd pool set rbd_pool pg_num 64调整。调整后 PG 会进入activeremapped状态等它回到activeclean才算完成期间性能会受影响尽量在业务低峰做。4.4 挂载后容量比镜像小现象创建 1024MB 镜像df -h显示 976M以为镜像缩水了。原因ext4 文件系统本身要占元数据空间加上mkfs.ext4默认的 inode 表、日志区等开销实际可用容量就是会比裸设备小。解决这是正常现象不是 Ceph 的问题。如果对容量精度要求高可以调mkfs.ext4的-Ninode 数量和-m预留百分比参数但别指望能拿到 100% 的裸容量。4.5 客户端缓存导致数据不一致现象多台机器同时映射同一个镜像并挂载各自写入后互相看不到对方的数据甚至文件系统损坏。原因RBD 镜像默认不带集群文件系统语义多个客户端同时挂载同一个块设备会互相覆盖。解决一个 RBD 镜像同一时间只能挂给一个客户端除非上层用 GFS2、OCFS2 这类集群文件系统。如果确实要多客户端共享应该用 CephFS 而不是 RBD。这是块存储和文件存储的本质区别选型时就要想清楚。5. 进阶技巧用快照和克隆把 RBD 用出花基础流程跑通之后RBD 真正省事的地方在快照和克隆。快照是某个时间点的只读副本克隆是基于快照快速生成新镜像两者配合能做虚拟机模板、批量部署这类场景。先给 image1 打个快照# 创建名为 snap1 的快照 rbd snap create rbd_pool/image1snap1 # 列出镜像的所有快照 rbd snap ls rbd_pool/image1快照创建是秒级的底层用的是 COW写时复制不会立刻占额外空间。但要注意快照会阻止被引用的对象被删除如果镜像一直在写、快照一直不删底层对象会越积越多ceph df里的USED会持续上涨。常见做法是给快照设过期时间或者定期清理。基于快照克隆出新镜像# 保护快照未保护的快照不能克隆 rbd snap protect rbd_pool/image1snap1 # 基于快照克隆出 image2 rbd clone rbd_pool/image1snap1 rbd_pool/image2 # 查看克隆镜像的信息注意 parent 字段 rbd info rbd_pool/image2克隆出来的 image2 初始不占空间只有写入新数据时才分配对象这叫 thin clone。rbd info里会显示parent: rbd_pool/image1snap1说明它依赖父快照。如果要断开依赖用rbd flatten rbd_pool/image2但 flatten 会把父快照的数据全量拷贝过来空间占用立刻上去操作前确认池里有足够容量。验证克隆镜像能不能正常映射挂载流程跟前面一样rbd map、mkfs.ext4、mount。如果映射时报parent snapshot not protected说明快照保护没生效回去补rbd snap protect。另一个坑是删父镜像前必须先删所有克隆或者 flatten 克隆否则删不掉报image has snapshot或image has children。从那以后我每次建 RBD 镜像都强制走一遍检查先rbd info确认 format 2 和 features 只开 layering再rbd showmapped确认设备路径最后ceph -s确认 PG 全 clean 才敢往上面写业务数据。这套习惯帮我挡掉过好几次因为 feature 不匹配和 PG 异常导致的半夜排障。希望帮到你。本文还有配套的精品资源点击获取