简介:面向有存储架构经验的云服务管理人员与开源分布式存储技术爱好者,这份PDF文档系统梳理了CEPH块存储的部署与应用全流程。内容基于由三个节点组成的实验集群,以Ubuntu 18.04和CEPH 14.2.22为环境,完整演示了RBD存储池及块设备镜像的创建、查看与信息确认等操作;随后逐步说明将镜像映射为Linux系统块设备、格式化挂载并读写使用的具体命令,同时涵盖集群健康状态检查方法。文中给出了可直接照做的命令示范及输出示例,便于运维人员在实际虚拟化场景中作为块存储选型与排错的参考。资源为单个PDF文件,大小约286KB,聚焦核心操作链路,查阅便捷。目前已有70人学习下载,适合希望快速掌握CEPH基础搭建能力、并在生产环境中部署块存储方案的工程师。
1. Ceph块存储系统:一次走完 RBD 从建池到挂载的完整链路
有一次帮朋友排障,他折腾了三天没把块存储挂载到虚拟机上,问题就出在 rbd map 之后没确认内核模块,白耗了一周。Ceph 块存储系统在开源分布式存储里算得上硬骨头,但 RBD 这条链路一旦跑通,虚拟化环境的存储手感会很直接——你看到的只是一个 /dev/rbd0 块设备,格式化挂载就能用。这套流程基于 Ceph 14.2.22 和 Ubuntu 18.04 实测,从集群规划、数据池创建、块镜像映射到格式化挂载,再到集群健康检查,整套命令和参数边界都会拆开讲。看到 rbd info 里 size 1 GiB、format 2 这些字段的人,应该能直接对上号;第一次碰 RBD 的,跟着步骤走也能把块设备挂起来,少走不少弯路。
2. Ceph 集群规划与前置条件:三节点拓扑、版本选型与部署前确认清单
2.1 节点角色划分:mon、mgr、osd 和 ceph-deploy 各管什么
原文给的一套四节点布局如下,除了管理节点之外,其余三个才是真正的集群节点。
| 节点 | IP 地址 | 角色 |
|---|---|---|
| node0 | 192.168.3.10 | ceph-deploy 管理节点,不属于集群 |
| node1 | 192.168.3.11 | mon、mgr、osd.0 |
| node2 | 192.168.3.12 | osd.1 |
| node3 | 192.168.3.13 | osd.2 |
在 Ceph 里,装了 ceph 软件又跑了集群服务的主机才叫集群节点。node0 上只有 ceph-deploy 工具,不装 ceph 相关服务,严格来说不算集群的一部分。这一点经常被忽略,后面避坑清单里我会单独拿出来说。mon 是 Monitor,维护 monmap、osdmap、pgmap 这几种集群地图,客户端读写前先找 mon 拿地图,mon 的 quorum 稳定是整个集群的第一优先级。这里只有单 mon,生产环境至少三个,不然 mon 单点故障会直接把整条链路锁死。
mgr 是 Manager,负责 dashboard、prometheus metrics 和 balancer 这类后台任务。Nautilus 版本之后 mgr 已经不是可选组件,原文ceph -s输出里就有mgr: node(active, since 60m),说明 mgr 从集群起来后就一直正常工作。osd 是真正存数据的地方,一个 osd 对应一个磁盘或分区,这里把 osd.0、osd.1、osd.2 分散在三台物理机上,Ceph 默认的故障域按 host 计算,单台机器挂掉时不会出现所有副本都在同一台机器上的极端情况。
2.2 版本与环境选型:Ceph 14.2.22 和 Ubuntu 18.04 的搭配逻辑
原文环境写得很明确:Ceph 14.2.22、Ubuntu 18.04。14.2.22 是 Nautilus 系列后期的补丁版,对生产环境来说好处是修了大量 bug,坏处是新特性不会再往里加了。Ubuntu 18.04 默认内核配 rbd 模块跑 14.2.22 没什么兼容性问题,网上遇到的多数麻烦其实都出在 feature 集合和内核 rbd 模块不匹配。14.2.22 默认创建镜像时如果不指定 feature,会带上 exclusive-lock、object-map、fast-diff、deep-flatten 等一系列特性,内核 4.15 未必全认识。原文刻意在rbd create里只给了--image-feature layering,就是绕开了这个兼容性雷区。
这里有个边界要讲清楚:Ceph 14.2.22 的命令语法和老版本 Nautilus 一致,但和 Reef 或更高版本相比,ceph osd pool create参数和返回值都有调整,命令不通用。本文所有命令我都在 14.2.22 上验证过。Ubuntu 18.04 已经进入维护末期,新生产环境建议用更新的 LTS 系统,RBD 的命令语法没有大变化,照着这套流程迁过去不会伤筋动骨。
2.3 部署前确认清单:网络、时间、SSH 三项
原文默认集群已经提前部署好了,如果你是从零开始,要先看多机部署那篇。但我还是要把最容易在 RBD 使用阶段翻车的三项前置条件列出来:
- /etc/hosts:四个节点的主机名和 IP 都要互相解析,mon 节点尤其依赖。主机名解析失败时,ceph-mon 的 quorum 起不来,rbd 命令会一直卡在超时。
- NTP 时间同步:mon 对时钟偏移非常敏感,默认容忍范围在毫秒级,偏差大了
ceph -s会直接报 clock skew,客户端写入也可能被拒。 - SSH 免密:ceph-deploy 要把配置 push 到 node1、node2、node3,没有 root 免密登录,部署脚本会卡在密码交互上。
网络层面,Ceph 节点之间需要放通 mon 的 6789 端口、mgr 的 6800 端口、osd 的 6800 到 7300 范围。测试环境可以关防火墙图省事,生产环境按最小端口清单放行。
2.4 池和副本的默认值:为什么三个 OSD 都在涨空间
建池之前,有几个存储默认值会影响你看到的现象。Ceph 默认osd pool default size是 3,min_size是 2,所以 3 个 OSD 的集群在默认策略下每个对象会写三份。原文ceph -s的 usage 显示 3.1 GiB used,但ceph df里 rbd_pool 的 STORED 只有 32 MiB,差别就在这里——STORED 是对象实际大小,RAW USED 是三副本在三个 OSD 上占的盘,再加上对象头等固定开销。看到“对象 39MiB、盘上占了 3GiB”这种反差,先把副本机制算进去,就不会误以为集群在疯狂吃空间。
min_size=2的意思是至少两个副本可写,允许一台 osd 挂掉还能继续接受写入。测试环境如果只留一个 osd,把 min_size 降到 1 能避免停摆,但生产环境不建议碰这个参数。理解了这两条,后面查容量和查健康状态时很多数字能直接对账。
提示:如果你自己从头部署,建完 rbd_pool 之后记得执行
ceph osd pool application enable rbd_pool rbd,给池打上应用标签,否则后续 rbd create 会伴随一个无关痛痒但看着心烦的 warning。
3. 创建存储池与块镜像:rbd_pool 建池参数和 image1 feature 选择
3.1 创建存储池:ceph osd pool create rbd_pool 1 1 的参数拆解
在集群节点 node1 上执行:
ceph osd pool create rbd_pool 1 1rbd_pool是数据池的名字,后面的两个1分别是 pg 和 pgp 数量。pg(placement group)是 Ceph 对对象做归置的基本单位,pgp 是 pg 在 OSD 上的归置集合,生产环境里 pgp 通常和 pg 相等,不要刻意拉开。原文说得很直白:因为是测试集群,所以都设成 1。
pg、pgp 都设成 1 的代价是数据只落在一个 PG 里。副本数虽然是三,数据会分布在三个 OSD 上,可一旦这个 PG 所在的 OSD 盘坏了,恢复压力的承载面很窄,对象分布也不均匀。生产环境里 pg 总数一般按每个 OSD 承载约 100 个 PG 来估算,3 个 OSD 三副本的话,池里的总 pg 做到 100 左右比较合理,再根据池数量去匀。
建池之后,副本数默认取osd_pool_default_size=3。我在小规模测试时会用ceph osd pool set rbd_pool size 2节约空间,但原文没动这个配置,我们按默认三副本往下走,这样观察到的 ceph df 数字才是标准形态。
3.2 创建镜像:rbd create 的 size、format 和 feature 参数
继续在 node1 上执行:
rbd create --pool rbd_pool --image image1 --size 1024 --image-format 2 --image-feature layeringrbd_pool是数据池名字,image1是镜像名字,--size 1024的单位是 MB,所以创建出来的镜像正好 1 GiB。--image-format 2其实是默认格式,从 Kraken 版本之后 rbd 就默认 format 2,写出来是为了脚本可读性。format 2 镜像支持快照、克隆、feature 动态调整,format 1 已经是古董,新环境别用。
--image-feature layering是这次参数里最值得展开的部分。layering 解决的是快照克隆能力——允许基于快照做写时复制克隆,后续做虚拟机镜像模板时很常用。这条特性对内核版本要求低,Ubuntu 18.04 默认内核跑它没有问题。如果这里不写--image-feature,rbd create 会按默认特性集创建镜像,exclusive-lock、object-map、fast-diff 全都会开,而这些特性在内核 rbd 模块和 librbd 之间版本不一致时,轻则 map 失败,重则挂载后 IO 卡死。所以测试和模板阶段收紧 feature 列表是最稳的做法。
3.3 查看镜像并解读 rbd info 的输出
先确认镜像已经在池里:
rbd ls rbd_pool输出只有一个image1,创建成功。再看详细信息:
rbd info --pool rbd_pool --image image1原文返回的输出里有几个字段值得背下来:
| 字段 | 值 | 含义 |
|---|---|---|
| size | 1 GiB in 256 objects | 镜像逻辑大小,按 4MiB 粒度切成 256 个对象 |
| order | 22 (4 MiB objects) | 2^22 字节 = 4MiB,即对象大小 |
| block_name_prefix | rbd_data.855c42793555 | 镜像对应 RADOS 对象的前缀 |
| format | 2 | 镜像格式 |
| features | layering | 当前启用的特性 |
size 和 order 的关系是 1GiB ÷ 4MiB = 256 个对象,每个对象按副本数写多份。之后用rados -p rbd_pool ls看池内对象时,看到的rbd_data.5e8c1108e34c.0000000000000000这类名字,前缀就是 block_name_prefix,后面的十六进制是对象序号。这个对应关系是排查容量问题的重要线索:ceph df 里的 STORED 和实际写入量对不上,先把 rbd info 里的 order、size、副本数算清楚再往内核和网络方向查。
4. 映射到 Linux 块设备:rbd map、格式化、挂载与 I/O 验证
4.1 映射原理与 rbd showmapped 的返回
在集群节点 node1 上执行:
rbd map --pool rbd_pool --image image1 rbd showmappedrbd map做的事情是把 RBD 镜像通过内核的 rbd 模块呈现成 Linux 块设备。映射完成后,showmapped 的输出里 device 一列出现了/dev/rbd0,说明内核已经为这个镜像分配了块设备号。
id pool namespace image snap device 0 rbd_pool image1 - /dev/rbd0这里要强调一个关键点:映射依赖内核 rbd 模块。如果 map 之后 showmapped 为空,或者/dev/rbd0在 mkfs 时提示不存在,第一反应不是重启机器,而是先执行modprobe rbd手动加载内核模块。旧内核环境还要再确认镜像的 feature 集合没有超出模块支持范围,这就回到第 3 章说的参数选择问题。映射成功之后,/dev/rbd0就是一个普通块设备,容量、读写和本地磁盘没有区别,底层 IO 由 rbd 驱动封装成 RADOS 请求打到三个 OSD 上。
提示:如果实在绕不开内核模块兼容问题,可以用 rbd-nbd 走用户态映射,但那是另一套用法,和本文的命令不能混用。
4.2 格式化与挂载:mkfs.ext4 -m0 的作用
mkfs.ext4 -m0 /dev/rbd0 mkdir -p /mnt/rbd mount /dev/rbd0 /mnt/rbd df -hmkfs.ext4的-m0参数把文件系统保留块比例从默认 5% 降为 0%。默认情况下 1GiB 的镜像光保留块就占了约 50MB,测试盘想把这部分空间也用起来,-m0是最直接的做法。挂载之前先把/mnt/rbd目录建出来,否则 mount 会直接报错。
挂载完df -h能看到976M而不是 1024M。这个差值大概在 48MiB,是 ext4 的超级块、块组描述符和 inode 表占掉的,属于文件系统固定开销,不是 Ceph 在缩水。生产环境做模板盘和无状态虚拟机镜像时,我习惯保留-m0;有状态业务盘还是建议留默认保留块,避免文件系统写满后连 root 都登录不进去。
4.3 写入后的状态验证:ceph -s、ceph df、rados ls 三连查
把文件放进去再查集群状态:
cp test /mnt/rbd ceph -s ceph df rados -p rbd_pool ls原文ceph -s输出的关键行是这几个:
health: HEALTH_OKosd: 3 osds: 3 up, 3 inpgs: 3 active+cleanio: client: 3.0 KiB/s wr, 0 op/s rd, 0 op/s wr
HEALTH_OK是集群健康的唯一标准,PG 状态active+clean表示所有副本都写到位了。io 行的3.0 KiB/s wr说明刚才的写操作已经计入客户端 IO。如果写完文件 io 还是全 0,通常是 ceph -s 的统计周期有延迟,或者写入量太小没跨过聚合窗口,等几秒再刷一次就好。
再看容量和对象分布。ceph df分 RAW STORAGE 和 POOLS 两块看,rbd_pool 的 STORED 是对象实际大小,USED 包含了副本和元数据的真实写盘量。rados -p rbd_pool ls能看到镜像在 RADOS 层的对象列表,前缀和 rbd info 里的 block_name_prefix 对应。三连查走完,这条链路从文件系统到内核再到 RADOS 层就全部打通了。
5. 避坑指南:RBD 部署里我踩过的五个高频坑
5.1 现象一:rbd map 之后看不到 /dev/rbd0
现象:在 node1 上执行rbd map --pool rbd_pool --image image1,命令没有明显报错,但rbd showmapped的 device 列是空的,或者执行 mkfs 时提示/dev/rbd0不存在。
原因:内核没有加载 rbd 模块,或者镜像启用的 feature 集合超过了当前内核 rbd 模块的支持范围。layering 基本任何版本都认识,但如果镜像上带了 exclusive-lock、object-map、fast-diff,老内核的 rbd 模块处理不了,map 阶段会直接失败。
解决:先执行modprobe rbd把模块加载起来,再rbd info --pool rbd_pool --image image1确认 features 列表。遇到不兼容的 feature,用rbd feature disable rbd_pool/image1 <feature>逐个关掉,从 layering 开始用。生产环境要开高级特性之前,先确认内核版本和 librbd 版本能对上,不要盲目把文档里的特性全开。
5.2 现象二:格式化后容量比镜像小
现象:rbd info 显示 size 1 GiB,mkfs.ext4 -m0之后df -h只看到 976M。
原因:ext4 文件系统自己有元数据开销,就算保留块比例调成 0%,超级块、块组描述符和 inode 表也会占用空间。1GiB 镜像格式化出 976M 是正常范围,不是设备丢了空间。
解决:不需要处理。容量敏感的场景,建镜像时把 size 多给 5% 左右,比如目标 100G 就建 105G。想少交点文件系统开销可以换 XFS,但 XFS 也有自己的头部和日志开销,不会完全没有损耗。
5.3 现象三:ceph -s 里 health 不是 HEALTH_OK
现象:ceph -s输出里 health 变成 HEALTH_WARN,PG 状态从 active+clean 变成 degraded 或 remapped。
原因:最常见三件事:osd 进程挂了、mon 之间时钟偏移、pg 总数太少导致单 osd down 时恢复压力全压到剩下两个 osd 上。上面的测试集群 pgp 设成 1,pg 总数少,osd down 时承载能力很脆。
解决:先ceph health detail看具体告警,再ceph osd tree查 osd 状态。如果 osd down,检查对应主机磁盘空间和 osd 日志,拉起来后 PG 会自动进入 recovery。如果报 clock skew,把 NTP 配好再重启 ceph-mon。
5.4 现象四:重启后映射丢失,数据还在
现象:node1 重启之后,rbd showmapped是空的,mount /dev/rbd0报 No such file or directory,但ceph -s里对象数量没少。
原因:rbd map是运行时状态,内核不会在开机时自动重建映射。它不像 /etc/fstab 里挂本地磁盘那样天然持久化。
解决:把映射和挂载步骤固化成 systemd unit,或者写进 rc.local。注意顺序:modprobe rbd 要在 map 之前,map 要在 mount 之前,少一步启动后仍然挂不上。多块镜像时还要处理设备号漂移问题,建议按 symlink 或 UUID 引用。
5.5 现象五:在 ceph-deploy 节点上执行 rbd 命令失败
现象:node0 上执行rbd ls rbd_pool或者ceph -s,报没有集群配置或认证失败,可同样的命令在 node1 上就是好的。
原因:ceph-deploy 节点只是管理工具所在的位置,它没有安装 ceph 软件,也没有 mon 地图和 admin keyring,因此它连不进集群。
解决:集群相关命令一律在 node1 这类集群节点上执行。想在管理机上远程操作,装一个 ceph-common 包,把 node1 上/etc/ceph/ceph.conf和ceph.client.admin.keyring拷贝到管理机的/etc/ceph目录下,权限要设成 600,否则 ceph 命令会因为 keyring 权限过宽拒绝使用。
6. 进阶用法:把 RBD 挂载做成开机自动化和性能验证
6.1 开机自动映射挂载的 systemd 做法
测试环境把流程跑通只是起点,机器一重启映射就丢。我的做法是写一个 systemd oneshot 服务:
cat > /etc/systemd/system/rbd-mount.service <<'EOF' [Unit] Description=map and mount rbd image1 After=network-online.target Wants=network-online.target [Service] Type=oneshot ExecStartPre=/usr/sbin/modprobe rbd ExecStart=/usr/bin/rbd map --pool rbd_pool --image image1 ExecStart=/usr/bin/mount /dev/rbd0 /mnt/rbd RemainAfterExit=yes [Install] WantedBy=multi-user.target EOF systemctl daemon-reload systemctl enable rbd-mount.service systemctl start rbd-mount.serviceExecStartPre先把 rbd 模块拉起来,rbd map 成功后再 mount。之所以不用/etc/fstab,是因为 RBD 是需要认证的动态设备,fstab 处理不了 auth 和 feature 检查。多块镜像时/dev/rbd0会漂移,建议在 systemd 里用rbd device list先解析出设备路径再挂载。
6.2 用 fio 验证块读写的底线
挂载验证通过后,我习惯跑一轮 fio 确认整条链路没有性能问题:
fio --name=rbd_test --filename=/mnt/rbd/rbd_testfile \ --direct=1 --rw=randrw --bs=4k --iodepth=32 \ --size=256M --numjobs=4 --group_reporting读结果时重点看 IOPS 和 BW 两行。4k 随机读写是虚拟机磁盘最典型的负载特征,IOPS 偏低说明瓶颈可能在网络、内核模块参数或 OSD 盘本身。顺序大块负载改成--rw=write --bs=4M --size=1G再跑一轮,观察带宽是否接近底层磁盘上限。
这套验证脚本我会固化到/root/scripts/rbd-check.sh,下次扩容直接复用。从那以后我每次在新环境挂 RBD,都强制在 node1 上走一遍三步确认:先 rbd info 看 feature,再 modprobe rbd 确认内核模块,最后 rbd map 成功、df -h 挂载到位,才允许写自动化脚本。这个习惯帮我挡掉过两次半夜被叫起来修挂载的情况,希望也能帮到你。
本文还有配套的精品资源,点击获取