想象你要为一座城市建一座“图书馆”。但你没有选择建一个巨大的中央书库,而是把书分散到全城几十个街区的分馆里。每本书都不只放在一个分馆,而是复印两三份放在不同位置;每个分馆的图书管理员会定期向管理总局“报平安”;任何一位读者借书,不需要打电话问管理员书在哪,只需要拿一个算法地图自己一算——几毫秒就能知道该书在哪座分馆、哪个书架。这就是Ceph的世界观:用一堆完全普通的服务器硬盘,搭出一座会自动平衡、自动修复、永不单点故障的“分布式图书馆”。 Ceph是如今云时代最重要的开源分布式存储系统之一。它把“存储”从一台专用设备变成一套可无限扩展的软件系统,同时提供三种服务:像磁盘一样使用的块存储、像网盘一样的对象存储、像共享文件夹一样的文件存储。本文将以“城市分布式图书馆”为比喻,带你理解Ceph的架构、CRUSH算法、RADOS对象存储、PG映射、OSD管理、数据可靠性、集群扩展与部署运维。

岗位关联

职业价值:掌握Ceph,就掌握了云存储底座的通用语言——无论是搭建AI训练数据湖、私有云云硬盘,还是海量文件归档,分布式存储工程师的核心能力都建立在这套体系之上。

目录
  1. 可视化演示
  2. 1. Ceph架构
  3. 2. RADOS对象
  4. 3. CRUSH算法
  5. 4. PG映射
  6. 5. OSD管理
  7. 6. 数据可靠性
  8. 7. 集群扩展
  9. 8. 部署管理
  10. AI 应用场景
  11. Python 演示
  12. 常见误区
  13. 面试题

可视化演示

演示Ceph的CRUSH数据分布算法、副本与纠删码冗余策略、Quorum读写仲裁机制,交互调节冗余级别查看可用性与容量利用率变化。

本节配有交互动效(进入视口后自动加载,约 3KB)。

CRUSH数据分布算法 CRUSH: 可计算的数据分布算法,无需查表 PG映射:数据对象→归置组→OSD OSD = CRUSH(PG, ClusterMap) CRUSH算法通过计算而非查表实现数据分布,支持加权与故障域隔离

1. Ceph架构

城市图书馆的图书总量早已超过中央仓库的容量,于是我们决定改造成“分布式图书馆网络”:一台普通服务器配上几块硬盘,就是一个街区分馆。分馆数量不断增多,但读者并不需要关心书放在哪座分馆,他们面对的始终是同一个“馆藏系统”。

Ceph的架构正是这样:底层是 RADOS(Reliable Autonomic Distributed Object Store,可靠的自主分布式对象存储)——相当于整个馆藏管理系统,负责把所有分馆组织起来,让数据自动分布、自动修复;MON(Monitor)是管理总局,维护一张全城地图,记录每个OSD的状态、集群配置和运行规则;OSD 则是街区分馆,每个OSD进程负责管理一块物理磁盘,真正落盘保存数据;最上层是客户端接口,包括RBD块存储(像一块虚拟硬盘)、RGW对象网关(兼容S3协议)、CephFS文件系统(像共享文件夹)。

用户写入一个大文件时,Ceph不会把这个文件整体塞进某个分馆,而是先把文件切成多个小对象,再交给RADOS统一调度:

回到图书馆的比喻:再宏大的书库,也要先把书拆成一册册可管理的小册子,才能在全城分馆自由流通。Ceph 架构的设计哲学,就是用分层角色把“藏书”“地图”“分馆”各司其职,让整个系统像一座自动运转的图书馆。

File={Obj1,Obj2,⋯ ,Objn}File = \{Obj_1, Obj_2, \cdots, Obj_n\}
这个公式表示:一个文件(File)在逻辑上会被拆解成一个对象集合。每个对象默认大小约 4MB,彼此独立,由系统分配到不同OSD上。
  1. 文件分解用户上传的任意文件,如一段 4GB 的视频,Ceph 会按固定大小把它切成上千个小数据块。
    File={Obj1,Obj2,⋯ ,Objn}File = \{Obj_1, Obj_2, \cdots, Obj_n\}
  2. 对象序列大括号里的每个 Obj_i 代表第 i 个对象,它们共同组成完整的文件;读取时按顺序拼回即可。
    Obji∼4MB 数据块Obj_i \sim 4MB \text{ 数据块}
  3. 独立分布每个对象可独立映射到不同OSD,这为后文的CRUSH算法提供了“可搬运的最小单元”。
    Obji→CRUSHOSDjObj_i \xrightarrow{\text{CRUSH}} OSD_j

2. RADOS对象

图书馆的馆藏管理系统不管理“整本书”,而是管理“一册标着编号的小书”。每一册由三部分构成:索书号(OID)、书的正文(Data)、借阅卡(Metadata)。这种“小书”就是RADOS中的对象。

RADOS 之上还有“池”(Pool)的概念,相当于图书馆的藏书区:不同类型的数据放进不同池子,每个池可单独配置副本数、PG数量、数据安全策略。比如“视频池”配置3副本保证高可靠,“日志池”配置2副本以节省空间。RADOS 的核心承诺是:只要至少一个副本存活,写入的数据就一定能被读回,且对客户端完全透明。

这样,外部世界看到的不再是几十台服务器和几千块硬盘,而是一个干干净净的“对象海洋”。借阅人只要报出索书号,馆藏系统就能在几十个分馆中找到这本书。

对象=(OID,Data,Metadata)对象 = (OID, Data, Metadata)
RADOS 对象是 Ceph 存储的最小单元:OID 是对象的唯一标识,Data 是实际保存的数据二进制流,Metadata 是一组描述数据的键值对。三者共同构成一个自治的存储单元。
  1. OID 唯一编号类似图书馆索书号,由“池名 + 对象名 + 命名空间”组合而来,保证全局唯一,客户端靠它定位数据。
    OID=PoolName+ObjectName+NamespaceOID = PoolName + ObjectName + Namespace
  2. Data 数据主体对象真正保存的内容,默认以 4MB 为一片;可以存放图片、视频、日志等任意二进制数据。
    Data=字节序列Data = \text{字节序列}
  3. Metadata 元数据以键值对形式保存的附加信息,如创建时间、访问权限、自定义标签,相当于书的借阅卡。
    Metadata={key:value,⋯ }Metadata = \{key: value, \cdots\}

3. CRUSH算法

分布式图书馆最巧妙的设计是“每个分馆不用问管理总局就能知道某本册子该放哪”。读者借书时,只需拿一张“算法地图”:报上书名,按地图上的规则一算,精确的分馆号和书架号就出来了。这就是 CRUSH 算法——Controlled Replication Under Scalable Hashing,一种可扩展哈希控制副本放置的算法。

CRUSH 的两个核心优势:一是确定性,客户端在本地就能算出数据位置,无需维护一张巨大的中央索引表,这避免了集中式元数据服务器的瓶颈;二是可控性,通过放置规则实现故障域隔离——机架A宕机不会影响机架B的副本,让系统可靠性不再被局部故障拖垮。

就像校门口的算法地图:谁都能算、几毫秒出结果、规则可以随时调整。这种去中心化正是 Ceph 能扩展到上千节点而性能不衰减的秘密。

{OSD1,OSD2,⋯ ,OSDr}=CRUSH(PG_ID,ClusterMap,Rule)\{OSD_1, OSD_2, \cdots, OSD_r\} = CRUSH(PG\_ID, ClusterMap, Rule)
CRUSH 算法的本质:给定编目盒编号、集群拓扑地图和放置规则,输出一组 OSD 编号作为副本的落盘位置。它完全确定性——相同输入永远得到相同输出。
  1. PG_ID 输入编目盒编号,由对象哈希算出的逻辑分组编号,是 CRUSH 的第一个输入参数。
    PG_ID=对象所属编目盒PG\_ID = \text{对象所属编目盒}
  2. ClusterMap 集群地图分层记录了从根到机架、主机、OSD 的拓扑结构,并为每个 OSD 标注权重。
    ClusterMap={Root→Rack→Host→OSD}ClusterMap = \{Root \to Rack \to Host \to OSD\}
  3. Rule 放置规则定义副本如何分布,例如“3 副本必须跨 3 个不同机架”或“2 副本必须在不同主机”。
    Rule=故障域约束集合Rule = \text{故障域约束集合}
  4. 输出 OSD 组算法输出一个包含 r 个 OSD 的列表,每个副本分布在其中一个 OSD 上。
    {OSD1,OSD2,⋯ ,OSDr}=CRUSH(PG_ID,ClusterMap,Rule)\{OSD_1, OSD_2, \cdots, OSD_r\} = CRUSH(PG\_ID, ClusterMap, Rule)

4. PG映射

图书馆不会把每一册书直接派送到分馆,而是先把书装进一个个“编目盒”(Placement Group,PG),整盒运往分馆。这样分馆只需要管理有限数量的盒子,而不是上百万册零散的书。PG 是 Ceph 中对象与OSD之间的逻辑中间层。

PG 数量是 Ceph 集群规划的关键参数:PG 太少,单个 PG 管理的数据过多,分布可能不均;PG 太多,每个 PG 的元数据开销会消耗大量内存。实践经验通常建议“每个 OSD 上约 100~200 个 PG”。

编目盒机制把“海量对象”压缩成“有限盒子”。馆藏管理系统不再需要关心每一本小册子,只需知道每个盒子去了哪个分馆。当某个分馆故障时,系统也只需恢复该分馆上的几个盒子,效率极高。

PG_ID=hash(OID) mod PG_NUMPG\_ID = hash(OID) \bmod PG\_NUM
这个公式说明对象到 PG 的映射方式:对对象的 OID 做哈希,再对池配置的 PG 总数取模。结果是确定性的——同一个对象永远进入同一个 PG。
  1. 哈希输入hash(OID) 对对象的唯一标识做伪随机散列(如 CRC32),保证不同对象均匀散落。
    h=hash(OID)h = hash(OID)
  2. 取模运算\bmod PG\_NUM 将哈希值映射到 0 到 PG_NUM-1 的范围,得到 PG 编号。
    PG_ID=h mod PG_NUMPG\_ID = h \bmod PG\_NUM
  3. 物理映射每个 PG 再通过 CRUSH 算法映射到一组 OSD(如 3 副本对应 3 个 OSD),形成“对象→PG→OSD”两级映射链。
    PG_ID→CRUSH{OSD1,OSD2,OSD3}PG\_ID \xrightarrow{CRUSH} \{OSD_1, OSD_2, OSD_3\}

5. OSD管理

每个街区分馆的门卫都要定期向管理总局“报平安”:是否在岗、能否继续服务。管理总局则根据这些汇报维护全城各分馆的状态,并在分馆出现问题时做出调度。Ceph 的 OSD 管理机制与此完全一致。

OSD 之间通过心跳机制互相监控:默认每 6 秒互相发送心跳包,若一个 OSD 超过阈值(如 300 秒)未响应,MON 会将其标记为 down。同时,Ceph 会根据各 OSD 的权重(与磁盘容量、性能相关)自动均衡 PG 分布。新盘加入后,系统会将部分 PG 从过载 OSD 迁移到新盘。

管理总局通过“心跳考勤”动态掌握全城分馆状态。哪个分馆关门,系统自动把它负责的编目盒复制一份到其他分馆——读者完全感知不到这场“救援行动”。

OSD状态∈{up,down}×{in,out}OSD状态 \in \{up, down\} \times \{in, out\}
OSD 的状态由两个独立维度组合而成:up/down 表示进程是否在线;in/out 表示是否参与数据分布。两个维度组合成四种状态,决定了该 OSD 的职责。
  1. up / down进程和磁盘是否在线,类似门卫是否在岗;离线则无法响应读写请求。
    up=在线服务down=离线up = \text{在线服务} \quad down = \text{离线}
  2. in / out是否参与数据分配,类似分馆是否对外开放接收新书;out 表示不接收新 PG。
    in=参与分布out=退出分布in = \text{参与分布} \quad out = \text{退出分布}
  3. 四种组合up+in 可正常读写;down+out 彻底下线;up+out 在线但不接收新数据;down+in 需要立即迁移恢复。
    {up+in正常服务down+out彻底下线up+out排空数据down+in降级等待恢复\begin{cases}up+in & \text{正常服务}\\down+out & \text{彻底下线}\\up+out & \text{排空数据}\\down+in & \text{降级等待恢复}\end{cases}

6. 数据可靠性

图书馆的“防火灾策略”非常明确:重要文献复印多份,分散存放在不同街区、不同建筑;甚至把一本书拆成若干段,再加一段“校验段”,任何一段丢失都能逆推出来。Ceph 提供了两种数据冗余方案:副本和纠删码。

三副本模式下,每个对象写 3 份,占用 3 倍空间,可容忍任意 2 个 OSD 同时故障。纠删码则不同:以 4+2 策略为例,把数据拆成 4 个数据块加 2 个校验块,任意丢失 2 块都能恢复,存储开销仅 1.5 倍,远低于三副本的 3 倍。代价是读写时需要更多计算与网络带宽。此外,副本是否真的可靠还取决于故障域隔离——若 3 个副本都在同一机架,整个机架断电,数据照样全丢。

有了防火灾策略,即使某个街区分馆因断电或故障掉线,只要其他分馆还存有相关册子的副本,馆藏系统就能把书“借出来”并自动补印新副本。

A=1−(1−p)rA = 1 - (1 - p)^r
这个公式计算的是:当每块磁盘的故障概率为 p、有 r 份副本时,至少有一份副本存活的概率,即数据的可用性。
  1. 单盘故障概率p 表示一块 OSD 磁盘在给定时间窗内的故障概率,例如年故障率 4%。
    p=P(单个OSD故障)p = P(\text{单个OSD故障})
  2. 副本全故障概率(1-p)^r 是所有 r 份副本都正常工作的概率,即系统不出故障的概率。
    (1−p)r=P(所有副本正常)(1-p)^r = P(\text{所有副本正常})
  3. 系统可用性用 1 减去全故障概率,即至少有一个副本可用。
    A=1−(1−p)rA = 1 - (1-p)^r

7. 集群扩展

城市人口增长,图书馆系统决定兴建新的分馆。新分馆落成后,为了让各分馆的藏书量保持均衡,一部分书需要搬到新分馆。读者好奇地问:要把整个图书馆搬空吗?答案是否定的——只需要搬动一小部分书,而且搬书时图书馆照常营业。

这个特性来自 CRUSH 的“确定性 + 最小扰动”设计。扩容时 Ceph 会把 PG 迁移任务排成后台队列,逐个将部分 PG 从旧 OSD 迁到新 OSD,期间 PG 保持可读写。运维建议:一次不要加入过多 OSD(避免剧烈迁移),也不要太少(数据均衡效果不明显)。

“搬家不搬空全馆”是分布式存储最美的特质之一。扩容不是推倒重建,而是润物无声地让新书架渐渐装满书。

迁移比例≈CnewCtotal迁移比例 \approx \frac{C_{new}}{C_{total}}
扩容时迁移的数据比例,约等于新增容量占扩容后总容量的比例。集群越大,新增节点带来的数据迁移比例越小。
  1. 新增容量C_new 为新加入集群的存储容量,比如新增 5 台各 4TB 的服务器共 20TB。
    Cnew=20TBC_{new} = 20TB
  2. 扩容后总容量C_total 是扩容后整个集群的容量,如原来 80TB 加 20TB 等于 100TB。
    Ctotal=Cold+Cnew=100TBC_{total} = C_{old} + C_{new} = 100TB
  3. 迁移比例两者相除得到约 20% 的数据需要迁移到新 OSD,其余 80% 原地不动。
    CnewCtotal=20100=20%\frac{C_{new}}{C_{total}} = \frac{20}{100} = 20\%

8. 部署管理

图书馆落成后,馆长每天需要看一块“健康仪表盘”:全城分馆是否在线、编目盒是否都排列整齐、系统整体是否处于健康状态。Ceph 的运维管理同样围绕这样一块仪表盘展开。

部署工具从早期的 ceph-deploy、ceph-ansible,已演进到如今主流的 cephadm 容器化部署。日常运维关键命令包括:ceph -s 查看集群整体状态;ceph osd tree 查看 OSD 拓扑与权重;ceph osd pool set <池> size <副本数> 调整副本数;ceph pg stat 查看 PG 状态分布。故障处理黄金三步:先看 ceph -s 健康度,再看 ceph health detail 定位原因,最后按告警执行重建或撤离。

馆长不需要每天跑遍全城分馆,一张仪表盘就能掌握全局。Ceph 的价值,正是把复杂的分布式管理逻辑自动化、工具化、标准化——这也是分布式存储工程师的核心工作日常。

HEALTH_OK  ⟺  MON∈正常∧OSD∈up+in∧PG∈active+cleanHEALTH\_OK \iff MON \in 正常 \land OSD \in up+in \land PG \in active+clean
这个公式说明 Ceph 集群健康(HEALTH_OK)的判定条件:MON 监视器正常、OSD 在线参与服务、所有 PG 处于活跃且干净状态,三者同时满足。
  1. MON 正常管理总局的监视器服务存活,集群地图可读取——这是所有调度的前提。
    MON∈正常MON \in \text{正常}
  2. OSD up+in存储节点在线并参与数据分布,异常节点会被标记并在 ceph -s 中亮黄灯。
    OSD∈{up,in}OSD \in \{up, in\}
  3. PG active+clean编目盒处于“活跃且干净”状态,即没有被卡在恢复中,也没有副本缺失。
    PG∈{active,clean}PG \in \{active, clean\}
  4. 三者同时满足任何子项不满足,健康状态降级为 WARN 或 ERROR,系统提示定位排障。
    HEALTH_OK  ⟺  所有组件正常HEALTH\_OK \iff \text{所有组件} \text{正常}

AI 应用场景

场景1:AI私有云的云硬盘底座

阶段:基础设施层

解决的问题:传统存储阵列(SAN)一次性采购成本高、扩容必须停机、容量天花板明显。Ceph RBD 将多台普通服务器的本地盘抽象成分布式块设备,虚拟机与容器可直接挂载为云硬盘;扩容只需加服务器,数据自动再平衡,系统全程在线。

具体案例:某企业用 OpenStack + Ceph 搭建私有云,为 AI 训练团队提供 GPU 服务器的高性能云硬盘。数据 3 副本分布在不同物理机,一台机器宕机时,云硬盘自动切换到其他副本,训练任务几乎无感知。

场景2:AI训练数据湖的对象存储

阶段:数据采集与归档

解决的问题:AI 训练需要存储海量图片、视频、日志,传统 NAS 文件系统在文件数量达到千万级后索引膨胀、性能急剧下降。Ceph RGW 提供 S3 兼容接口,数据以对象形式存储,支持生命周期分层与版本管理。

具体案例:某自动驾驶公司每天产生数十 TB 道路采集视频,通过 S3 协议写入 Ceph 对象存储,按摄像头 ID 和日期分桶存储。训练前用并行读并发拉取样本,模型训练完再将结果归档回 Ceph,实现了高效的存算分离。

场景3:大数据平台的持久化存储层

阶段:数据处理与计算

解决的问题:HDFS 的 NameNode 在大量小文件场景下吞吐受限,且副本机制导致磁盘成本偏高。将 Ceph 作为计算存储分离后的持久层,Spark 通过 S3A 协议直接访问对象数据。

具体案例:某数据分析平台将 HDFS 上的冷数据迁入 Ceph 对象存储,保留热数据在 HDFS,存储成本下降约 40%,同时利用 Ceph 的多副本策略免去了 NameNode 单点风险。

Python 演示

python75 行
import hashlibfrom collections import defaultdict  class SimpleCrush:    """简化版 CRUSH 模拟器:确定性映射对象到 OSD"""     def __init__(self, osd_list, replicas=2):        self.osd_list = list(osd_list)        self.replicas = replicas        self.stats = defaultdict(list)     def _hash(self, text):        return int(hashlib.md5(text.encode("utf-8")).hexdigest(), 16)     def place(self, obj_id):        """返回对象 obj_id 应放置的 OSD 列表(确定性打分)"""        h = self._hash(obj_id)        scored = []        for osd in self.osd_list:            score = h ^ self._hash(osd)            scored.append((score, osd))        scored.sort(reverse=True)        return [osd for _, osd in scored[: self.replicas]]     def write(self, obj_id):        osds = self.place(obj_id)        for osd in osds:            self.stats[osd].append(obj_id)        return osds     def add_osd(self, osd):        if osd not in self.osd_list:            self.osd_list.append(osd)            self.stats[osd] = []     def migrate(self):        """扩容后重新计算映射,统计位置变化的对象数量"""        all_objs = set()        for objs in self.stats.values():            all_objs.update(objs)        old_place = {}        for osd, objs in self.stats.items():            for obj in objs:                old_place.setdefault(obj, set()).add(osd)        new_stats = defaultdict(list)        moved = []        for obj in all_objs:            new_osds = self.place(obj)            for osd in new_osds:                new_stats[osd].append(obj)            if old_place.get(obj, set()) != set(new_osds):                moved.append(obj)        self.stats = new_stats        return len(moved)  def main():    crush = SimpleCrush(["osd-1", "osd-2", "osd-3", "osd-4"])    for i in range(100):        crush.write("obj-%03d" % i)     before = {k: len(v) for k, v in crush.stats.items()}    print("扩容前各 OSD 对象数:", before)     crush.add_osd("osd-5")    moved = crush.migrate()    after = {k: len(v) for k, v in crush.stats.items()}    print("扩容后各 OSD 对象数:", after)    print("发生迁移的对象数:", moved)    print("迁移比例: %.1f%%" % (moved / 100 * 100))  if __name__ == "__main__":    main()
目的:演示 CRUSH 式的确定性映射与扩容时的数据再平衡,运行后你能直观看到加入第 5 个 OSD 后,仅有约 1/5 的对象搬了家。
  1. score = h ^ self._hash(osd)将对象哈希与 OSD 名字的哈希做异或,得到该 OSD 的“得分”,得分越高越优先。
  2. scored.sort(reverse=True)把所有候选 OSD 按分数降序排序,取前 replicas 个作为副本落点。
  3. old_place.setdefault(obj, set()).add(osd)建立旧副本位置的倒排索引,记录每个对象当前所在 OSD。
  4. if old_place.get(obj, set()) != set(new_osds): moved.append(obj)新旧落点集合不一致,说明该对象在扩容后需要迁移。
  5. crush.add_osd("osd-5")模拟扩容操作:加入第 5 个 OSD 并触发重分布。

常见误区

误区Ceph 既然全称和对象存储有关,那它只适合存图片、视频这些对象文件,数据库和虚拟机用不了它。

正解Ceph 是真正的统一存储平台,同时提供三种接口:对象存储(RGW,兼容 S3)、块存储(RBD,可挂载为云硬盘,数据库、虚拟机都能用)、文件存储(CephFS,可当共享网盘)。“一套系统,三种服务”正是它的核心卖点,也是它区别于 MinIO、HDFS 等单接口系统的地方。

为何常见:Ceph 的底层核心 RADOS 确实以“对象”为最小单位,网上讨论也多是对象存储场景,初学者容易只见树木不见森林。

误区CRUSH 和 Redis 的一致性哈希差不多,就是把对象名做哈希再取模,映射到一个节点上。

正解CRUSH 的输入是 PG_ID、集群拓扑地图和放置规则,输出是符合规则的一组 OSD;它天然支持故障域约束(如副本必须跨机架),并通过权重精确控制数据分布。和一致性哈希最本质的区别是:CRUSH 是“规则驱动+拓扑感知”的确定性映射,而一致性哈希只是简单的环状哈希加上虚拟节点。

为何常见:两者表面都是“hash→节点”,且都能解决增删节点时的数据迁移问题,很容易被混为一谈。

误区为了保险我把副本数设成 5,数据应该万无一失了吧?

正解副本增加会成倍放大写流量、占用存储成本,并拖慢写入性能;更重要的是,若 5 个副本都放在同一机架甚至同一交换机下,整个机架断电时数据照样全部丢失。可靠性的关键是“故障域隔离”——副本必须分布在相互独立故障的域中,而不是副本数量本身。

为何常见:直觉上“多几分备份就多几分安全”,忽略了故障相关性(同一机架、同一电源、同一机房),这是分布式系统新手最典型的思维盲区。

误区看到 `ceph -s` 里有 OSD down 的告警,我是不是应该赶紧恢复数据?数据是不是已经损坏了?

正解OSD down 只表示该进程或硬盘暂时不可服务,盘上的数据依然完整。只要该 PG 的其他副本 OSD 正常,集群仍可正常读写、自动重建副本。只有同一个 PG 的所有副本同时故障,数据才真正丢失——这就是多副本的意义。

为何常见:把“服务不可用”和“数据损坏丢失”混为一谈,加上监控告警的红色状态容易引发恐慌。

误区集群要扩容,加一台新 OSD,是不是所有数据都要拷一遍?那扩容一次服务器要撑不住了吧?

正解CRUSH 的确定性映射保证扩容只迁移约“新容量 / 总容量”比例的数据。例如 100 个 OSD 扩到 125 个,大约只有 20% 的对象会迁移;而且迁移在后台按 PG 逐个进行,期间数据照常可读写。

为何常见:从传统数据库“加索引导致全量重建”的经验迁移而来,或者误以为“重新计算映射”等价于“全量复制数据”。

面试题

Q1. Ceph 中真正落盘保存用户数据的核心组件是?

单选题 · easy

  • A.MON 监视器
  • B.OSD 存储节点← 正确答案
  • C.MDS 元数据服务
  • D.RGW 对象网关

答案:B。OSD(Object Storage Daemon)负责直接管理物理磁盘、持久化存储数据,相当于图书馆的街区分馆;MON 只维护集群地图,类似管理总局;MDS 是 CephFS 的元数据服务;RGW 是对象存储网关,三者都不直接落盘。

Q2. Ceph 提供哪几类存储接口?

多选题 · easy

  • A.块存储 RBD← 正确答案
  • B.对象存储 RGW← 正确答案
  • C.文件存储 CephFS← 正确答案
  • D.表格存储 HBase

答案:ABC。Ceph 的三大接口是块存储(RBD)、对象存储(RGW,兼容 S3)、文件存储(CephFS),对应图书馆的“分馆借书”“网盘下载”“共享书架”三种服务。HBase 是独立的 NoSQL 数据库,不属于 Ceph 接口。

Q3. 对象写入 Ceph 后,第一步先映射到哪个逻辑单元?

单选题 · mid

  • A.OSD
  • B.PG← 正确答案
  • C.MON
  • D.Pool 池

答案:B。对象先通过 PG_ID = hash(OID) mod PG_NUM 映射到 PG(编目盒),再由 PG 通过 CRUSH 映射到具体 OSD 组。Pool 是池的配置容器,MON 是监视器,都不是对象映射的直接目标。

Q4. CRUSH 算法的输入不包括以下哪项?

单选题 · mid

  • A.PG_ID
  • B.集群拓扑地图
  • C.放置规则
  • D.对象内容← 正确答案

答案:D。CRUSH 的输入是 PG_ID、集群地图(ClusterMap)、放置规则(Rule),输出是 OSD 列表。对象内容并不参与 CRUSH 计算——Ceph 只用对象的哈希值确定 PG,再用 PG_ID 做 CRUSH,数据内容在分布决策中无关紧要。

Q5. 关于 OSD 状态机的说法,正确的是?

多选题 · mid

  • A.up 表示进程在线← 正确答案
  • B.in 表示参与数据分发← 正确答案
  • C.up+in 才能正常读写← 正确答案
  • D.down 的数据一定丢失

答案:ABC。up/down 和 in/out 是两个正交维度。up+in 是正常服务状态;down 只表示该盘暂不可用,数据仍保存在盘上,副本机制保证了数据不丢。D 把“进程离线”误等同于“数据丢失”,是典型误区。

Q6. 某池配置 3 副本,若 3 个副本均位于同一机架,该机架故障时会发生什么?

单选题 · hard

  • A.数据自动切换到其他机架
  • B.该 PG 数据全部丢失← 正确答案
  • C.只影响部分读写性能
  • D.系统自动从副本重建

答案:B。虽然配置了 3 副本,但 3 个副本都在同一故障域(同一机架)内,机架整体故障时所有副本同时不可用,数据必然丢失。这也是为什么 CRUSH 的放置规则必须配置“跨机架分散”——副本数量不等于可靠性,故障域隔离才是关键。

Q7. 一个 3 副本池,最多能容忍几个 OSD 同时故障而不丢失数据?

单选题 · mid

  • A.0 个
  • B.1 个
  • C.2 个← 正确答案
  • D.3 个

答案:C。3 副本意味着同一份数据有 3 份拷贝,只要至少 1 份存活即可读。因此在故障域隔离的前提下,最多可容忍 2 个 OSD 同时故障。类比图书馆:一本书复印 3 份放在不同分馆,只要还有 1 个分馆没烧掉就能借到。

Q8. 关于纠删码(Erasure Code)说法正确的是?

多选题 · hard

  • A.以空间换可靠性
  • B.可用性高于同容量三副本← 正确答案
  • C.数据块+校验块可恢复任意丢失块← 正确答案
  • D.写入性能通常低于副本模式← 正确答案

答案:BCD。纠删码以 CPU 计算换取空间利用率(如 4+2 策略仅 1.5 倍开销),A 错误;相同裸容量下纠删码的可用性高于三副本,B 正确;数据块与校验块结合可重建丢失块,C 正确;写入需计算校验块,性能低于副本,D 正确。

Q9. 现有 100 个 OSD 的 Ceph 集群,扩容均匀增加 25 个 OSD,数据迁移比例约为?

单选题 · extreme

  • A.25%
  • B.80%
  • C.20%← 正确答案
  • D.100%

答案:C。迁移比例约等于新增容量占扩容后总容量的比例:25 ÷ (100 + 25) = 20%。这是 CRUSH 最小扰动特性的直接推论——扩容不是全量重排,而是只有约五分之一的数据需要搬家。

Q10. 下列哪些是 Ceph 集群常见的部署或运维工具?

多选题 · easy

  • A.ceph-deploy← 正确答案
  • B.cephadm← 正确答案
  • C.ceph 命令行← 正确答案
  • D.Dockerfile

答案:ABC。ceph-deploy 是早期部署工具,cephadm 是当前主流的容器化部署工具,ceph 命令行是日常运维的核心入口。Dockerfile 只是构建镜像的配置文件,不是 Ceph 的运维工具。