
简介面向云服务运维人员及分布式存储技术爱好者这份PDF文档系统讲解Ceph块存储RBD的部署与实战应用。内容基于三节点实验集群在Ubuntu 18.04环境下完整演示了存储池创建、块设备镜像管理、映射至Linux系统块设备、格式化与挂载以及集群健康状态检查等关键操作。通过具体命令与输出样例帮助读者快速掌握搭建稳定Ceph集群的方法在虚拟化环境中落地高效块存储方案。资源为单个PDF文件压缩后仅286KB轻量易读适合按文档随学随练。目前已有70人学习内容聚焦实际运维场景尤其适合有一定存储架构基础、希望短期上手RBD的读者。整体来看其价值在于将部署与使用串联成完整链路既呈现了存储池、镜像等对象级操作也覆盖了映射、格式化、挂载后的读写验证和状态监控方法。文档在基础演示之上提示了面向数据中心规模扩展参数或研究高级特性的方向为进阶调优留有余地。1. CEPH块存储系统部署门槛不在“能装”而在“装完能不能用”CEPH 块存储系统把多台普通服务器的磁盘聚合成一个共享存储池客户端在网络上拿到一块可以格式化、可以挂载的“裸盘”而数据实际分散在集群中多个节点。很多人以为难点在安装实际上 cephadm 已经把安装压缩到一条 bootstrap 命令真正让人翻车的是装完之后的参数、挂载方式和故障排查。这篇文章写给虚拟化、OpenStack、Kubernetes RBD 以及想自建存储的运维按“选型 → 部署 → RBD 接入 → 避坑排查 → 压测验证”的顺序把 3 节点集群从零到压测跑通顺带标出几个我在生产环境里踩过的坑。2. 为什么块存储选 CEPH组件拆解与硬件规划CEPH 常说“一套软件三种接口”但实际部署时最怕的就是三种接口全开。先把选型讲清楚后面的部署命令才有意义。2.1 块存储、文件存储与对象存储的选型差别CEPH 对外同时提供 RBD 块存储、CephFS 文件存储和 RGW 对象存储。三者的适用场景差别很大接口典型场景客户端形态容易忽略的问题RBD 块存储虚拟机磁盘、数据库数据文件内核 rbd / librbd单盘延迟受网络和副本数影响CephFS 文件存储共享目录、大数据作业POSIX 挂载元数据频繁时压力集中到 MDSRGW 对象存储S3 兼容、备份归档REST API不适合低延迟小文件访问部署前先问自己两个问题。第一个问题客户端到底要通过哪种方式访问如果用 OpenStack Cinder 或 Kubernetes CSI实际走的是 librbd块设备的 feature 兼容性要求不同如果直接在 Linux 机器上用内核 rbd 模块就要避开内核不支持的 feature。第二个问题写负载是顺序为主还是随机为主。顺序写为主可以上 HDD 加大块甚至考虑纠删码随机写到数据库这个级别就要老老实实准备 SSD/NVMe否则后面调参很难救回来。常见误区是一个集群把三种接口全开。我见过不少团队为了让“Ceph 很全能”把 CephFS 也挂给数据库结果元数据操作一上来整个集群的慢查询就开始放大。实际落地时我通常先只开需要的接口比如虚拟化就只开 RBDRGW 那些等业务验证过再加。2.2 会用到的核心组件MON、OSD、MGR、RBD部署完成后ceph -s 看到的 service 基本就是这几个角色MON 是哨兵维护集群状态的 Map用 Paxos 保证一致性。生产至少 3 个超过一半存活才能选出新主如果只有 2 个 MON坏一个就进入只读保护。OSD 是真正落盘和参与数据复制的进程一个 OSD 通常对应一块数据盘。OSD 状态 down 会直接影响写入也是部署后最先要盯的对象。MGR 负责 Dashboard、Prometheus 指标和内部均衡生产中至少要两个否则坏了只影响观测不影响数据读写。RBD 是 pool 之上的 image也就是给客户端用的块设备。创建 image 时指定池、大小和 feature。再往下一层是 PGPlacement Group。所有数据按哈希分散到 PGPG 再映射到 OSD。pg_num 决定数据分布粒度和故障迁移速度太小会让单个 PG 数据量膨胀、恢复慢太大则元数据开销和恢复压力上升。我的经验值对 RBD 池在 9 个 OSD 的 3 节点集群上设 128 起步再开 pg_autoscale_mode on 让集群自动调整。手动估算的话可以按每 OSD 50~100 个 PG 的范围来但这不是绝对公式池越多、容量越大结论差得很远。最后说故障域。默认 CRUSH rule 是 host 级故障域三个副本分布在三个不同节点时容忍单节点故障如果只有两台机器却把副本数强行设成 3数据根本放不下集群会一直报 PG 异常。生产环境至少 3 节点起步这是硬约束不只是经验。2.3 一套够用的生产硬件规划常见做法是 3 节点起步每节点部署 MON MGR OSD。为什么一定是 3 台因为 RBD 默认 3 副本只有副本分布在 3 个独立节点上单节点故障时集群才仍然能写入。副本数降到 2故障时数据完整性和恢复速度都没保障。磁盘层面系统盘与数据盘分离。系统盘用双 SSD RAID1数据盘每 OSD 一块独立盘。一个 OSD 池内尽量不要混用 HDD 和 SSD否则整个池的延迟都会被慢盘拖住。预算够的话给每个 OSD 配一块独立 NVMe 或 SSD 放 WAL/DBHDD 只放数据块这是缓解随机写延迟最有效的硬件手段。部署时用 --block-db 参数指定高速盘但注意每个 OSD 的 block.db 必须是独立分区多个 OSD 共享同一个高速盘会变成新的竞争点。网络层面公开网络和数据网络分离。10GbE 起步两个网络独立时在集群配置里指定 cluster-network。存储网络一旦出现丢包OSD 心跳超时最直接的表现就是 osd down。内存规划OSD 进程至少 4-8GBMON 节点 8GB 以上。我见过把内存全留给计算、OSD 只有 2GB 的压测环境cephadm 能装起来但一跑 fio OOM 就开始杀进程。内存规划不是越大越好而是别让监控组件和业务抢资源。如果手头只有两台物理机做验证可以搭两节点加额外 monitor 的实验环境但别拿这个拓扑当生产结论。3. cephadm 部署集群最小命令与每个参数的含义选择 cephadm 的原因很直接它以容器方式拉起所有 daemon卸载干净对宿主机污染小后续升级也走统一入口。下面从环境准备开始。3.1 环境准备内核、时间、SSH 与防火墙部署前先做三件事主机名、时间同步、SSH 免密。时间不同步对 MON 共识的影响最隐蔽表现是偶发“mon is down”但网络一切正常排查时容易绕远路。# 三个节点都要执行改主机名开启时间同步并放行 ceph 相关端口 hostnamectl set-hostname ceph-node1 timedatectl set-ntp true # 生产环境建议只放行指定端口测试机直接停 firewalld 也行 firewall-cmd --permanent --add-port{6789,3300,8443,9283}/tcp firewall-cmd --reload # 在管理机上生成密钥并分发到三个节点 ssh-keygen -t ed25519 -N -f /root/.ssh/id_ed25519 for h in ceph-node1 ceph-node2 ceph-node3; do ssh-copy-id root$h; done端口说明6789 是老 msgr1 端口3300 是 msgr2 默认端口8443 是 dashboard9283 给 Prometheus 模块用。cephadm 通过 SSH 作为管理通道所以从管理机到所有节点必须免密。内核版本尽量使用当前发行版的主流 LTS太老的内核跑 bluestore 时在 discard、AIO 上容易出怪问题这类问题往往表现为数据面正常但性能上不去。3.2 cephadm bootstrap一个参数一个坑bootstrap 是整套部署的起搏器它会在当前节点拉起第一个 MON 和 MGR然后输出 dashboard 地址和初始密码。先准备一个 cluster.yaml声明 3 个 MON 和 2 个 MGRservice_type: mon placement: hosts: - ceph-node1 - ceph-node2 - ceph-node3 --- service_type: mgr placement: hosts: - ceph-node1 - ceph-node2然后拉取 cephadm 脚本并执行 bootstrap。URL 中的 要换成你选定的版本号我一般会锁定一个 z-stream不要追最新。curl -fsSL https://download.ceph.com/rpm-version/el9/RPMS/cephadm -o /usr/local/bin/cephadm chmod x /usr/local/bin/cephadm cephadm bootstrap \ --mon-ip 192.168.1.10 \ --cluster-network 192.168.2.0/24 \ --apply-spec /root/cluster.yaml \ --skip-monitoring-stack参数说明--mon-ip 必须写成当前节点真实地址写错集群直接选不出主--cluster-network 是数据网络如果不做双网分离可以省略--apply-spec 会在 bootstrap 后自动创建 SPEC 中声明的 MON/MGR--skip-monitoring-stack 用于最小化部署跳过 Prometheus、AlertManager 和 Grafana对只有几个节点的实验环境能省不少内存代价是 dashboard 的性能图表会变空。生产保留监控栈没问题但要提前规划内存。bootstrap 结束后会在当前节点生成 /etc/ceph需要把这个目录同步到其他节点否则 cephadm 无法从那些节点上管理 daemonfor h in ceph-node2 ceph-node3; do scp -r /etc/ceph root$h:/etc/ done然后执行 ceph -s 看集群是否 HEALTH_OK。如果没到 OK直接用 ceph health detail 看原因多数情况是 MON 数量不足或首次 OSD 没加。3.3 添加 OSD、创建池从空盘到可用的 poolcephadm 通过 orch 管理 OSD。先看设备再统一添加ceph orch device ls ceph orch apply osd --all-available-devices ceph -s--all-available-devices 会把每个节点上所有未分区、无文件系统的空盘都拿来做 OSD。如果不想让某块盘被占用在 apply 前给设备打标签或者写一份 device spec 只匹配 /dev/sdb 和 /dev/sdc。等 OSD 起来后确认每个 OSD 的 in 和 up 状态都正常。此时集群健康但还没有给 RBD 用的池。创建池的这一步要注意ceph osd pool create rbd-pool 128 replicated ceph osd pool application enable rbd-pool rbd ceph osd pool set rbd-pool pg_autoscale_mode onreplicated 是副本模式默认 size3。pg_num 设 128 适合 9 个 OSD 左右的小集群随后开 autoscale让集群按实际使用量自动扩缩 PG避免你一次性拍一个过大的值。application enable 不能省RBD 客户端发现池没有绑定 rbd 应用会直接拒绝访问。如果 OSD 数量不对常见原因是磁盘被分区或被旧文件系统占用用 lsblk -f 看盘上是否还有 PV/VG 遗留。4. RBD 块设备创建与客户端接入映射、格式化、自动挂载池建好后开始给业务分配块设备。这一章涉及命令最密集也是后面踩坑最多的地方。4.1 创建 imagesize、features 怎么选先确认池存在然后创建 imagerbd create rbd-pool/vm-disk-01 --size 100G --image-feature layering rbd ls -p rbd-pool rbd info rbd-pool/vm-disk-01--size 100G 直接带单位。--image-feature layering 是内核 RBD 能稳用的特性集合object-map、fast-diff、deep-flatten 这类特性在内核 mapping 时容易出兼容性问题如果客户端只是普通挂载建议创建时不带或者用 rbd feature disable 关掉。exclusive-lock 用于多客户端锁OpenStack、Kubernetes 这类集群场景需要它单机挂载可以关。创建完成后 rbd info 会输出 block_name_prefix、order 等参数。order 默认 22对应对象大小 4MB想优化随机读写可以调低到 21 或 20但对象越多元数据开销越大生产里我一般不默认动它。4.2 客户端侧map、mkfs 与挂载客户端不需要部署整套 Ceph装 ceph-common 并把管理机上的 keyring 拷过去即可。apt install -y ceph-common scp rootceph-node1:/etc/ceph/ceph.conf /etc/ceph/ scp rootceph-node1:/etc/ceph/ceph.client.admin.keyring /etc/ceph/ rbd map rbd-pool/vm-disk-01 lsblk | grep rbd mkfs.xfs -f /dev/rbd0 mount /dev/rbd0 /srv/datamap 前先确认内核 rbd 模块已加载lsmod | grep rbd没有就 modprobe rbd。map 成功后 /dev/rbd0 出现但设备号由内核分配不保证每次都是 rbd0。格式化之前务必确认磁盘是你要的镜像lsblk -f 看文件系统类型空盘显示为空已有数据会显示分区和文件系统避免把别的盘冲掉。这里有个最常见的生产事故有人把 fstab 直接写死 /dev/rbd0重启后设备变成 rbd1挂载直接失败。4.3 自动挂载rbdmap 与 systemd 依赖常见做法是用 rbdmap 服务在开机时做 map挂载交给 fstab 或 systemd。先在客户端改 /etc/ceph/rbdmap# /etc/ceph/rbdmap rbd-pool/vm-disk-01 idadmin,keyring/etc/ceph/ceph.client.admin.keyring systemctl enable --now rbdmaprbdmap 会把镜像映射成 /dev/rbdNN 由已有设备编号决定。接下来不要用设备名写 fstab用 blkid 拿 UUIDblkid /dev/rbd0 # /etc/fstab 追加一行注意 nofail 和 x-systemd.device-timeout UUIDxxxx-xxxx /srv/data xfs defaults,_netdev,nofail,x-systemd.device-timeout30 0 0_netdev 告诉 systemd 这个设备依赖网络nofail 保证网络存储不可用时系统照样能启动不会卡在 mount 阶段。x-systemd.device-timeout30 用于等待 rbdmap 完成映射。如果你在数据库容器里用块设备更推荐写一个独立的 systemd service在 Before 声明启动顺序先 map 再 mount 再启动数据库避免依赖 fstab 的启动时序。步骤多一些但重启后不需要人工干预。5. 避坑排查CEPH 部署中最常见的五个翻车点这一章是血泪经验每一条按“现象 → 原因 → 解决”写都是我在不同环境里实际遇到过的。5.1 OSD 反复 down先看网络再看内核现象部署完第二天开始ceph -s 里 OSD 状态在 up/down 之间跳客户端写入变慢ceph health detail 报 osd.X is down。原因三个方向排查优先级最高——网络丢包、内核模块版本、磁盘 SMART。很多“玄学”抖动最后都定位到交换机端口协商失败或管理网络广播风暴其次是内核太老bluestore 的 AIO 调用异常。解决先 ping 对端 IP 看丢包率再 ethtool 看协商速率用 dmesg 找 OSD 进程 abort 的堆栈lsblk 确认磁盘无 SMART 错误。网络和磁盘都没问题就把 OSD 重启观察恢复时间如果反复出现要检查管理网和存储网是否混用以及 cephadm 是否因为 SSH 超时误判 OSD 状态。5.2 写放大吃掉 SSDWAL/DB 分离是底线现象全闪集群跑数据库几个月后 SSD 寿命报告降到 60%读多写少但盘一直在写入。原因Ceph 默认 3 副本写一份数据至少放大 3 倍再加上 bluestore 自身的 WAL 和元数据更新写放大可能到 5 到 7 倍。如果 WAL/DB 和数据块共用同一块 SSD磨损速度会非常快。解决部署 OSD 时把 block.db 和 block.wal 指定到独立 NVMe 分区例如 ceph-volume lvm create --block-db /dev/nvme0n1p1 --data /dev/sdb。已有集群只能通过 bluestore 工具迁移过程比新装麻烦得多所以新集群一开始就要规划好。数据盘 HDD、缓存盘 SSD 的混构是性价比最高的方案。5.3 重启后 /dev/rbd0 消失别把设备名写进 fstab现象客户端服务器一重启数据库服务起不来发现 /dev/rbd0 不存在fstab 报 failed。原因内核 rbd 模块没有在启动阶段加载或者 rbdmap 服务在挂载前没有完成 map直接写死 /dev/rbd0 也不可靠设备号由内核动态分配。解决把 modprobe rbd 写入 /etc/modules-load.d/rbd.conf挂载引用改为 blkid 拿到的 UUID并在 fstab 加 _netdev,nofail或者干脆用 systemd unit 管理 map 顺序。我自己的习惯是数据库节点上绝不用裸设备名全部走 systemd 单元启动顺序写清楚避免开机竞态。5.4 OOM 把 OSD 杀了内存目标要手动锁现象跑压测时 ceph-osd 进程被 OOM killer 杀掉mon 也跟着起不来机器负载不高但内存耗尽。原因cephadm 默认开启 osd_memory_target_autotune会根据机器内存自动给每个 OSD 分配上限但 autotune 在混部场景下会跟监控组件抢内存再加上 MGR、Prometheus、Grafana 都在同一台节点内存就爆了。解决先关掉 autotuneceph config set osd osd_memory_target_autotune false再设具体目标ceph config set osd osd_memory_target 8GiB。同时确认监控栈是否真的需要实验环境 bootstrap 时用 --skip-monitoring-stack 最省心。内存问题在小集群上比性能问题更早出现所以我会在部署阶段就规划节点内存而不是等 OOM 再救。5.5 版本混跑升级前先 check再 start现象某次 yum update 之后ceph -s 显示不同节点运行不同版本甚至 MON 之间无法选举。原因cephadm 管理的是容器镜像版本宿主机包管理器自动更新不会让 Ceph 容器合理切换如果手动在多个节点重启容器很容易造成版本不一致、quorum 丢失。解决所有节点禁用 ceph 相关仓库的自动更新。升级走统一入口ceph orch upgrade check 确认目标版本可用再 ceph orch upgrade start --image 目标镜像。升级中途不要执行其它 daemon 重启发现版本不一致时先回滚到最近一次全量一致的镜像而不是继续往上升。生产集群只升不降降级基本靠备份所以升级前先备份 MON 的 db。6. 生产验证与调参fio 压测、内存参数与容量规划6.1 用 fio 验证 RBD 性能先随机后顺序上线前我会用 fio 打一遍先随机写再顺序写fio --namerandwrite \ --filename/dev/rbd0 \ --rwrandwrite \ --bs4k --iodepth16 --numjobs4 \ --runtime60 --time_based --group_reporting \ --direct1direct1 绕过客户端页缓存看到的是真实的块设备能力。4K 随机写是数据库场景最残酷的指标结果里重点看 iops 和 p99 延迟。9 个 OSD 的全闪小集群4K 随机写跑到几千 IOPS 算正常如果只有几百先怀疑副本数和网络再用 fio 分别打单 OSD 定位。fio --nameseqwrite --filename/dev/rbd0 \ --rwwrite --bs1M --iodepth32 --numjobs2 \ --runtime60 --time_based --group_reporting --direct1顺序 1MB 更考验网络和 OSD 聚合带宽。跑完后记录带宽和吞吐后续调整 pool 的 size 或压缩配置时拿这套数据当基线。6.2 上线前调好这三个参数参数默认建议说明osd_memory_target4GiB按节点内存 1/2 以内关掉 autotune 后手动设避免 OOMosd_max_backfills1-21控制数据回填占用的磁盘 IOosd_recovery_max_active32恢复期间降低对业务的影响设置方式统一走 ceph config set。这三个参数直接影响稳定性和故障恢复时间比纠结单个磁盘的 IOPS 更值得先调。PG 数量交给 autoscale 管理不要手动来回改。6.3 容量规划与上线前最后检查提示可用容量 ≈ 裸容量 ÷ 副本数 × 0.850.85 是为数据均衡、PG 迁移和未来扩容留的安全余量。20TB 裸容量、3 副本实际可分配约 5.6TB。对延迟不敏感的场景可以换纠删码提升可用容量但会引入计算开销块存储场景慎用。上线前最后检查四件事ceph -s 为 HEALTH_OKceph osd tree 确认 OSD 分布到不同主机fio 随机写跑 30 分钟以上观察内存曲线手动拔掉一块数据盘观察恢复时间和业务影响。我自己踩过最深的坑是第一次交付时没做故障演练结果一台机器下线时副本恰好落在同一机架整个虚机存储直接卡死。所以现在每次新集群交付前不管多忙我都会做一次拔盘演练把恢复时间记录到运维手册里。希望帮到你。本文还有配套的精品资源点击获取