聊到分布式存储,Ceph 是一个绕不开的名字。它既不是某个厂商的闭源黑盒,也不是仅供测试的玩具项目,而是一整套围绕“软件定义存储”构建起来的技术生态。这套生态的核心,是把块存储、文件存储、对象存储统一到同一套底层架构上,让运维人员用一套集群同时支撑虚拟化平台的硬盘、容器平台的持久化卷、以及海量非结构化数据的对象桶。
我在生产环境里跑 Ceph 集群已经有几年时间,从早期的 Nautilus 版本一路用到现在,期间踩过不少坑,也看着它的部署工具从 ceph-ansible 演进到 cephadm,容器化成为绝对主流。这篇文章不打算写成一份官方文档的复述,而是想以一个实际使用者的视角,把 Ceph 生态里那些真正重要的组件、设计思路、部署细节和排障经验从头梳理一遍。适合正准备选型分布式存储的运维同学,也适合已经跑着 Ceph 但想系统理解其生态构成的工程师。
1. 生态全景:Ceph 由哪些核心组件构成
1.1 五个守护进程,撑起一套存储系统
理解 Ceph 生态系统,第一步是认识它的几个核心角色。跟传统存储设备里固化的控制器固件不同,Ceph 的功能被拆散成多个守护进程,各司其职,跑在普通的 x86 服务器上。
- MON(Monitor):集群的“大脑”,维护整个集群的地图信息,包括 OSD 地图、PG 地图、CRUSH 地图等。MON 必须奇数个节点部署,通常至少 3 个,这样才能通过多数派投票选出 Leader,避免脑裂。生产环境中 MON 数量宜 3 或 5 个,再往上加没有太大意义,写盘压力反而会拖慢整个集群的元数据操作。
- OSD(Object Storage Daemon):真正干活的进程。每块物理磁盘上跑一个 OSD 进程,负责数据的存储、复制、恢复和平衡。OSD 数量是集群性能的最主要变量,多一个 OSD 就多一份吞吐,也多一份数据副本的分布基础。
- MGR(Manager):负责收集集群运行指标,提供 Dashboard、Prometheus 监控数据接口,还承载了 balancer 等高级模块。MGR 通常部署两个,一个活跃一个备用,故障时自动切换。
- MDS(Metadata Server):只有使用 CephFS 文件存储时才需要它。MDS 维护文件系统的目录树和文件元数据,把文件路径映射到底层的对象数据。它本身不存业务数据,只管“索引”,数据照样落在 OSD 上。
- RGW(RADOS Gateway):对象存储网关,对外提供 S3 和 Swift 兼容 API。RGW 相当于一层无状态的前端转换层,接收 HTTP 请求,把对象转换成 RADOS 对象写入 OSD。生产环境一般会在前面挂负载均衡器,多实例横向扩展。
这五个角色构成了 Ceph 生态的骨架。实际部署时,一个节点上可以同时跑多个角色,比如控制器节点同时跑 MON、MGR、RGW,存储节点就专心跑 OSD。理解这种“角色可混布”的灵活性,是理解 Ceph 生态设计哲学的第一步。
1.2 三大存储接口:块、文件、对象的统一底座
Ceph 生态最有魅力的地方,在于它向上层应用提供了三种完全不同的存储协议,底层却共用同一个 RADOS 对象存储核心。也就是说,你在虚拟机里看到的一块裸盘、在 Kubernetes 里挂载的一个 PVC、在应用代码里调用的一个 S3 PUT 请求,数据最终都是以对象的形式存储在同一个分布式的存储池里。
- RBD(RADOS Block Device):块存储,给 OpenStack、KVM、Kubernetes 提供持久化块设备。RBD 支持精简配置、快照、克隆、动态扩容,是生产环境用得最多的接口。
- CephFS:文件存储,提供符合 POSIX 语义的共享文件系统,适合多个客户端同时读写同一目录,比如大数据分析场景、共享家目录场景。
- RGW:对象存储,兼容 S3 API,适合存图片、视频、备份文件、日志归档这类海量非结构化数据。
这三大接口不是各搞一套底层,而是共享同一个存储池、同一套副本策略、同一个故障域模型。这意味着运维只需要管好一套 OSD 集群,就能同时支撑多种业务需求,这也是 Ceph 相比开一套 GlusterFS 再开一套 MinIO 这种组合拳的核心优势。
1.3 生态周边:部署框架、容器编排与 CSI 插件
围绕 Ceph 核心,还发展出了一整套周边生态工具。最核心的几个值得单独点出来。
- cephadm:Ceph 官方主推的部署与管理工具,基于容器和 systemd,用一条命令就能拉起整个集群,后续的扩容、升级、配置变更都可以通过 CLI 或 Dashboard 完成。
- Rook:运行在 Kubernetes 内部署 Ceph 的编排框架,把 Ceph 集群定义为 K8s 自定义资源(CRD),让 K8s 管理员用熟悉的方式管理存储。
- Ceph CSI:Container Storage Interface 插件,分为 RBD 和 CephFS 两套,让 K8s 集群里的工作负载可以动态创建、挂载持久化存储。
- radosgw-admin / rbd / cephfs 命令行工具:分别管理对象、块、文件三大接口的运维工具。
- Prometheus + Grafana + Ceph Dashboard:监控告警体系,Ceph 原生集成 prometheus 模块,把集群指标暴露给 Prometheus 抓取。
这些工具共同组成了一个完整的技术栈:底层是 RADOS 自愈分布式存储引擎,中间层是三大协议接口,上层是容器编排和监控运维工具。理解了这张生态全景图,后面看部署和排障就会轻松很多。
2. 核心设计思路:Ceph 凭什么能做到统一与自愈
2.1 数据分布的基础:CRUSH 算法与 PG 概念
传统分布式存储系统通常依赖一张中心的元数据路由表,记录每个数据块存放在哪台机器上,查询时先找元数据服务,再跳转数据节点。Ceph 没有走这条路,而是设计了CRUSH(Controlled Replication Under Scalable Hashing)算法。简单理解,CRUSH 是一个确定性的伪随机函数:给定一个数据对象的名称、当前集群的拓扑结构、副本策略,就能直接计算出这个对象的三个副本分别落在哪些 OSD 上。
这种设计最直接的收益是:客户端不需要访问中心元数据服务,自己根据集群地图就能定位数据位置,避免了大规模读写时的元数据瓶颈。集群扩容、OSD 故障、调整副本策略时,只需要重新计算受影响数据的新位置。
为了降低定位和调度的颗粒度,Ceph 引入了PG(Placement Group)的概念。数据对象先哈希映射到 PG,PG 再映射到 OSD。一个 PG 就是一个逻辑容器,里面装着一批对象。PG 数量是建池时指定的关键参数,PG 多则数据分布更均匀、故障恢复更细粒度,但过多的 PG 会消耗内存资源。社区经验值是一台 OSD 大约承载 100~300 个 PG,公式大致是:
PG 总数 ≈ OSD 总数 × 100 / 副本数这个数字再向上取整到 2 的幂次比较合适。比如 30 个 OSD、3 副本的场景,PG 总数取 1000 到 1500 之间,选 1024 就很合理。我见过有人贪心把 PG 数量设成 4096 甚至更多,结果 OSD 内存吃紧、启动变慢,性能反而不理想。
2.2 副本策略与故障域:从“数据不丢”到“数据中心级容灾”
Ceph 的数据可靠性建立在副本机制上,默认每个对象写 3 份副本。写请求会同步写入所有副本,只有全部确认完成才返回成功。副本数可以按存储池独立设置,经济型业务用 2 副本加纠删码,核心数据库可以开 3 副本甚至 4 副本。
更重要的是故障域(Failure Domain)的概念。CRUSH 算法在分布副本时,不仅考虑不同的 OSD,还考虑了 OSD 所在的物理位置。存储池的 size 和 crush rule 决定了副本怎么跨机器、跨机架、甚至跨机房分布。
我在生产环境就是这么配置的:核心业务存储池 size=3,crush rule 按 rack 做故障域,也就是说三个副本必须落在三个不同的机架里。这样即使一个机架的交换机挂了、整柜断电,数据依旧有两个副本存活,业务不中断。这是 Ceph 生态设计中我认为最精华的部分:自愈能力加上可控的故障域模型,让“数据安全”不再只是依赖某一块磁盘的可靠性。
2.3 为什么说 Ceph 是“软件定义存储”的典型样本
从架构层面回看,Ceph 几乎把所有传统存储的能力都软件化了。控制器逻辑变成了 MON 守护进程,RAID 冗余变成了 CRUSH 副本策略,快照和克隆变成了 RBD 的对象级操作,存储资源池化变成了存储池的动态创建和管理。
这种设计带来一个很实际的好处:硬件选型非常自由。商用机器、二手服务器、混合型号硬盘、单盘 RAID 0、甚至树莓派都能跑 Ceph。传统存储里“买一套控制器就要配套买同样型号扩展柜”的锁定效应在这里完全不存在。
当然,自由也意味着责任。软件定义存储把底层硬件的差异完全暴露给了运维,必须自己处理好磁盘寿命、网络带宽、节点资源等细节。这也是很多 Ceph 集群性能崩盘的原因——不是 Ceph 不行,而是使用者没有按它的游戏规则来。
3. 实操解析:从零部署一套生产级 Ceph 集群
3.1 环境规划与硬件建议
动手部署之前,必须先规划好硬件和网络。根据我这几年的经验,这里给出一个最小可行的生产配置参考。
| 角色 | 节点角色 | 建议配置 |
|---|---|---|
| 控制节点 | MON + MGR + RGW | 4 核 CPU / 16 GB 内存 / 60 GB 系统盘 |
| 存储节点 | OSD × N | 8~16 核 CPU / 32 GB 内存 / 每盘对应一块 OSD |
| 网络 | Public / Cluster | 万兆业务网 + 万兆集群内网,至少千兆起步 |
有一个经常被忽略但至关重要的细节:Ceph 集群内网必须独立规划。OSD 之间复制副本、心跳检测、数据恢复都走 clusternetwork;客户端读写走 public network。如果两者共用一张网卡和交换机,一旦业务流量打满,集群内网就会严重拥塞,OSD 心跳超时直接被 MON 标记 down,引发大规模数据重均衡,这是运维事故最常见的导火索。
磁盘规划上,OSD 数据盘直接使用裸盘(不带文件系统),cephadm 会自动格式化并挂载。不要用 RAID 卡做 RAID5 或 RAID10 阵列再交给 Ceph,这样既浪费容量,又搞乱了故障域。推荐用 HBA 卡直通模式,让 Ceph 直接管理每一块物理盘。系统盘和数据盘分离,系统盘不做数据存储。内存方面每 OSD 建议至少 4 GB 内存,PG 数较多时按 1 个 PG 约 200 KB 内存估算。
3.2 使用 cephadm 部署三节点集群
以三台 Ubuntu 22.04 服务器为例跑一套最小集群。先把节点时间同步好,chrony或ntp都行,这也是后边 OSD 心跳判断的重要基础。然后准备集群节点之间 root 免密登录,便于 cephadm 分发 bootstrap 信息。
首先是安装 cephadm,从官方源直接拉取发行包:
curl --silent --remote-name --location https://download.ceph.com/rpm-reef/el9/x86_64/cephadm chmod +x cephadm ./cephadm add-repo --release reef ./cephadm install初始化第一个控制节点:
cephadm bootstrap --mon-ip 192.168.10.11 --cluster-network 192.168.20.0/24bootstrap 命令会自动在节点上以容器方式拉起第一个 MON 和 MGR,生成 Dashboard 访问地址、admin 密钥、ceph.conf 等关键文件。--cluster-network参数指定集群内网网段,一定不要省。
然后加入另外两个节点作为 MON 节点:
cephadm shell -- ceph orch host add node2 192.168.10.12 cephadm shell -- ceph orch host add node3 192.168.10.13 cephadm shell -- ceph orch apply mon node2,node3接下来是给集群添加 OSD。这一步我会先用ceph orch device ls查看被识别的磁盘,再决定采用自动发现还是手动指定。生产环境推荐手动指定,避免把系统盘或正在使用的盘误加入集群:
cephadm shell -- ceph orch daemon add osd node1:/dev/sdb cephadm shell -- ceph orch daemon add osd node1:/dev/sdc cephadm shell -- ceph orch daemon add osd node2:/dev/sdb cephadm shell -- ceph orch daemon add osd node2:/dev/sdc cephadm shell -- ceph orch daemon add osd node3:/dev/sdb cephadm shell -- ceph orch daemon add osd node3:/dev/sdc到这一步,一个最简集群已经跑起来了。用ceph -s查看集群状态,正常情况下 HEALTH_OK,如果显示 HEALTH_WARN,最常见的提示是MON_MGR_CLOCK_SKEW(时钟偏差)或OSD_DOWN(OSD 未启动)。
3.3 创建存储池与三大接口接入
集群健康之后,开始给业务输出存储能力。先建一个副本数为 3 的存储池:
ceph osd pool create volumes 1024 replicated ceph osd pool application enable volumes rbdRBD 块存储的使用流程是这样的:创建块设备、映射到客户端主机、格式化文件系统。底层通过 libvirt、OpenStack 或 K8s 使用 RBD 时可以跳过手工映射,但直接调试时手工操作最直观:
rbd create --size 100G mypool/vm-disk-01 rbd map mypool/vm-disk-01 mkfs.xfs /dev/rbd0 mount /dev/rbd0 /mnt/ceph-block对象存储 RGW 在容器化时代变得异常简单,一条命令就能拉起来:
ceph orch apply rgw rgw.zone1 --placement="3 host1 host2 host3" --port 8000CephFS 需要先部署 MDS,再创建文件系统存储池:
ceph orch apply mds fs_name --placement="2 host1 host2" ceph fs new cephfs cephfs_data cephfs_metadata ceph fs authorize cephfs client.demo / rw这三套接口都打通之后,Ceph 生态的价值才真正体现:一个集群,三种协议,多套业务共用底层存储池。
3.4 监控运维体系:Dashboard 与 Prometheus 联动
cephadm bootstrap 会默认启用了 Dashboard,默认端口 8443。第一次登录后,需要依次启用 Prometheus、Grafana 和 AlertManager 组件。
ceph orch apply prometheus --placement="label:mon" ceph orch apply grafana --placement="label:mon" ceph orch apply alertmanager --placement="label:mon" ceph dashboard set-grafana-api-info部署完成后,Grafana 面板会直接从 Prometheus 拉取 Ceph 指标,包括 OSD 利用率、PG 分布、延迟、吞吐等核心数据。告警规则可以用现成的 ceph-mixins 规则集,里面预置了 OSD down、PG 状态异常、磁盘使用率过高等常见告警项。
我个人的习惯是每天早上一睁眼先扫一眼 Grafana 首页,重点看三个指标:OSD 是否全绿、PG 是否有 degraded 状态、最近一小时的恢复流量趋势。把这三个盯住,集群基本不会出大乱子。
4. 选型对比:什么场景适合 Ceph,什么场景要慎选
4.1 Ceph 与 GlusterFS、MinIO 的横向对比
聊 Ceph 生态绕不开竞品对比。选型如果从一开始就错了,后面运维成本会翻好几倍。
| 维度 | Ceph | GlusterFS | MinIO |
|---|---|---|---|
| 存储模式 | 统一块/文件/对象 | 分布式文件系统 | 对象存储 |
| 元数据管理 | MON + MDS,中心化但高可用 | 无中心化元数据,靠弹性哈希 | 元数据存本地盘 |
| 数据一致性 | 强一致,多副本同步写 | 强一致但恢复复杂 | 对象最终一致 |
| 动态扩容 | 在线扩容,数据自动重均衡 | 在线扩容 | 在线扩容 |
| 运维复杂度 | 高,需要专职维护 | 中 | 低 |
| 典型场景 | 虚拟化、容器、私有云统一存储 | 高性能文件共享 | 轻量对象存储、大数据湖 |
GlusterFS 最大的弱点是没有块存储接口,K8s 和虚拟化场景基本排不上号。MinIO 做对象存储确实足够优秀,部署简单、性能好、API 兼容度极高,但它解决不了统一存储的问题——虚拟机磁盘、共享文件、对象桶得拆成三套系统分别维护。Ceph 最大的宏观优势在于一套存储底座同时输出三种接口,对于体量适中的企业私有云环境,这种“一碗水端平”的能力非常珍贵。
4.2 Ceph 不擅长的场景与替代方案
Ceph 不是万能药,我见过不少把 Ceph 用在不合适场景然后吐槽“Ceph 太烂”的案例。梳理一下典型的不适合场景:
- 小文件海量场景:Ceph 的对象最小粒度是 4 KB,大量 1~10 KB 的小文件会产生海量小对象和管理压力,元数据开销极大。这种情况下更合适用传统的 NAS 网关或鲸鲨等专为小文件优化的分布式文件系统。
- 单副本场景:如果业务数据量极大但又没有冗余需求,直接用 HDFS 或单机存储更省心,开 Ceph 的单副本存储池纯属白白消耗机器。
- 强一致高并发事务型数据库:Ceph 作为 OLTP 数据库的底层块存储是可以的,但数据库本身要跑在可靠的文件系统上,不要直接用 CephFS 跑数据库文件,事务性能会有额外损耗。
- 极低延迟场景:Ceph 的网络和多副本写路径决定了它的极限延迟大约在亚毫秒到毫秒级。如果业务要求 50 微秒以内的超低延迟,应该走 NVMe over Fabric 这类专用协议。
选型时能想清楚“我要给什么业务提供什么能力”,往往比“我要用什么技术”重要得多。
5. 生产环境常见故障与排查技巧实录
5.1 网络抖动引发的 OSD 心跳超时
这是 Ceph 集群最典型的事故场景。某天集群突然进入 HEALTH_WARN,ceph -s看到一堆 OSD down,第一反应不要慌着把 OSD 拉起来,先看日志定位原因:
journalctl -u ceph-osd@* --since "10 minutes ago" | grep "heartbeat no reply" ceph daemon osd.12 dump_osd_network | jq最常见的结论是:内网交换机某个端口错包率高、网卡 MTU 不一致,或者 OSD 所在节点负载过高导致心跳处理超时。处理思路分两步:先恢复服务,再根治网络问题。恢复服务通常直接ceph orch daemon restart osd.*就能让 OSD 重新加入集群,但如果网络问题没解决,重启后很快又会再 down。所以关键根因排查必须做扎实,重点检查万兆网卡的 MTU(建议 9000 Jumbo Frame)和内网交换机拥塞情况。
重要经验:Ceph 的 OSD 心跳超时不是一瞬间就完成的,默认情况下 5 秒没收到心跳就开始报 WRONG_OR_CRASHED。所以集群内网网络稳定是所有高可用建设的前提,这一条怎么强调都不过分。
5.2 PG 状态异常:degraded、peered 与 inconsistent
ceph pg stat输出看到degraded说明有副本未处于正常状态。这时用ceph pg dump配合ceph pg map <pgid>定位具体 PG,再进一步检查对应 OSD:
ceph pg dump pgs_brief | grep degraded ceph pg map 10.1c ceph daemon osd.5 log flush常见原因有:某 OSD 磁盘空间超过mon_osd_full_ratio(默认 85% 接近满,95% 完全拒绝写入),或者 OSD 进程 IO 错误挂掉。磁盘接近满导致 degraded 是最容易被忽视的根因,因为这个状态不会第一时间打告警,只会在ceph -s里显示一条OSD_FULL或PG_AVAILABILITY信息。建议脚本巡检磁盘水位,80% 就触发扩容或清理。
inconsistent状态则代表 PG 内对象有校验不一致,需要做 PG 深度扫描修复。Ceph 的 scrub 机制会定期校验副本数据,发现不一致时,会用权威副本修复其他副本。但如果 repeated scrub 一直报错,可能就是磁盘出现了静默损坏 — 这种情况建议直接把该 OSD 持有的数据迁移出去,下线换盘。
5.3 RBD 客户端 IO 延迟突刺排查
应用反馈写盘速度突然变慢,iostat看到等待时间持续飙升。我在生产中总结的一套排查顺序是这样的:
- 先看 Ceph 侧:
ceph -s是否健康?ceph osd tree有没有 OSD 处于 down 或 rebalancing 状态? - 再看网络:业务网和集群网有没有丢包?
iftop -i eth0实时看流量。IO 延迟突刺很多时候不是磁盘慢,而是网络拥塞重传。 - 最后看盘:
ceph daemon osd.X ops查看该 OSD 的当前操作数,再用smartctl检查盘的健康度,SSD 的话还要留意温度。
有一次我们排查一个持续两周的间歇性写入变慢问题,最后发现是一块 SATA SSD 固件 bug 导致 Trim 指令处理异常,OSD 进程在日志里反复重试。换掉这块盘之后立即恢复。所以遇到 IO 异常不要把视角局限在 Ceph 配置上,硬件层面的坑同样不容忽视。
5.4 数据扩容与重平衡的节奏控制
给 Ceph 集群扩容时,新加入的 OSD 会立即触发数据重平衡。默认 osd_mclock_max_capacity 这类参数不加控制的话,全速恢复会把集群的 IOPS 打满,影响在线业务。推荐在业务低峰期扩容,并主动限速:
ceph config set osd osd_max_backfills 1 ceph config set osd osd_recovery_max_active 1恢复完成后再调回默认值。数据恢复和业务 IO 之间永远存在权衡,运维要做的是当好这个平衡器,而不是让 Ceph 自己全速狂奔。我在生产上的习惯是:把 max_backfills 设为 2,recovery_max_active 设为 2,实测对业务影响可控制在 10% 以内,恢复速度也能接受。
6. 运维心得与长期视野
跑 Ceph 生态这几年,我最深刻的体会是:这是一个上限极高、下限也很低的技术栈。硬件和网络到位、配置合理、告警完善的话,一个 200 TB 的生产集群可以稳稳当当跑两三年没有任何事故;相反,如果磁盘乱插、网络复用、PG 失控,那再好的架构也会在某个深夜给你上残酷的一课。
给正在规划存储能力的团队几个实用建议。
第一,先把网络做扎实,再谈 Ceph。集群内网独立、万兆起步、MTU 统一、交换机关闭流控和广播风暴防护,这些基础的优先级高于任何 Ceph 参数调优。
第二,统一用 cephadm 管理集群。老旧的 ceph-ansible 方案虽然成熟,但已经不再演进。cephadm 把复杂的管理逻辑容器化之后,日常运维的命令复杂度大幅下降。Rook 适合 K8s 深度绑定的场景,但如果你的集群不只在 K8s 体系内用,用 cephadm 直接管控更灵活。
第三,告警宁可多不要少。OSD down、PG 异常、磁盘水位、心跳丢失、Monitor 时钟偏差这些告警规则务必全量开启,宁可告警疲劳也不能漏报。我们最惨烈的一次事故,就是告警阈值设置过高,等到业务同事反馈才发现 OSD 已经断了快四小时。
最后想提醒的是:把 Ceph 当一个长期运维的伙伴来经营,而不是搭建完就撒手不管的项目。定期做 scrub、保留足够的备用容量、推进容器化部署、观察官方 LTS 版本节奏并制定升级计划,这些繁琐的日常工作,才是 Ceph 生态稳定运行背后的真正密码。