Skip to content

Ceph 块与文件

Ceph 集群对外提供三类接口:RBD 块设备、CephFS 文件系统、RGW 对象存储。这篇覆盖 RBD 和 CephFS,RGW 和 S3 语义放到对象存储里单独看。

RBD 暴露的是一块远端块设备,客户端格式化成 ext4/xfs 后挂载,常见场景是虚拟机磁盘、单实例数据库数据盘、K8s RWO 卷。CephFS 暴露的是一个已有的共享文件系统,多台客户端直接挂目录,常见场景是共享文件、日志归档、多 Pod 读写的共享目录。二者底层数据都存在 Ceph OSD 里,但访问语义完全不同。

RBD 镜像创建和挂载

创建 Pool 并启用 RBD:

bash
ceph osd pool create rbd-pool 32
ceph osd pool application enable rbd-pool rbd
rbd pool init rbd-pool

创建镜像:

bash
# 相当于申请一块 10G 的远端块设备
rbd create rbd-pool/app-data --size 10G
rbd info rbd-pool/app-data

客户端挂载:

bash
rbd map rbd-pool/app-data --name client.admin
rbd showmapped
lsblk                       # 出现 /dev/rbd0
mkfs.xfs /dev/rbd0
mkdir -p /data/app
mount /dev/rbd0 /data/app

RBD 镜像默认按单客户端读写设计。多台机器同时把同一个 RBD 当普通文件系统挂载会写坏数据——除非上层用了支持共享块设备的集群文件系统或应用协议(如 Oracle RAC 配合特定配置)。

两种映射方式:

方式路径场景
krbd内核 RBD 驱动,rbd map 默认普通 Linux 挂载
rbd-nbd通过 NBD 暴露块设备,用户态老内核或特定 feature 兼容

老内核不支持新 RBD feature 时 rbd map 会直接失败。排查时看客户端内核版本、Ceph 版本和镜像 feature:

bash
rbd info rbd-pool/app-data

为老内核创建更保守的镜像:

bash
# layering 是基础 feature,兼容性最好
rbd create rbd-pool/legacy-data --size 10G --image-feature layering

RBD 快照、回滚和克隆

快照记录某个时间点的块设备状态,不是备份的全部——Pool 坏、集群误删、逻辑数据早已损坏时,光靠快照不够。

bash
# 创建快照前最好先静默应用写入(fs freeze 或应用层处理)
rbd snap create rbd-pool/app-data@snap-20260522
rbd snap ls rbd-pool/app-data

回滚:

bash
# 执行前停写入、umount、unmap
umount /data/app
rbd unmap /dev/rbd0
rbd snap rollback rbd-pool/app-data@snap-20260522

rbd map rbd-pool/app-data --name client.admin
mount /dev/rbd0 /data/app

克隆依赖父快照,先 protect 再 clone:

bash
rbd snap protect rbd-pool/app-data@snap-20260522
rbd clone rbd-pool/app-data@snap-20260522 rbd-pool/app-data-clone

需要完全摆脱父快照时 flatten:

bash
# flatten 把依赖数据摊平到克隆镜像自身,耗时和数据量相关
rbd flatten rbd-pool/app-data-clone

镜像删不掉时,原因通常是还有快照、克隆依赖或客户端 watcher——rbd status 能看到谁在占用。

RBD 扩容

扩容镜像本身:

bash
rbd resize rbd-pool/app-data --size 20G
rbd info rbd-pool/app-data

然后扩文件系统(两步都要做,先 resize 镜像再扩文件系统):

bash
xfs_growfs /data/app    # xfs 在线扩容

ext4 用 resize2fs /dev/rbd0。RBD 扩容比较顺手,缩容很危险——顺序是文件系统先缩再缩块设备,顺序反了直接破坏数据。

RBD 客户端权限

给业务客户端分配最小权限,避免随手发放 client.admin

bash
ceph auth get-or-create client.app \
  mon 'profile rbd' \
  osd 'profile rbd pool=rbd-pool' \
  mgr 'profile rbd pool=rbd-pool' \
  -o /etc/ceph/ceph.client.app.keyring

chmod 600 /etc/ceph/ceph.client.app.keyring

使用:

bash
rbd map rbd-pool/app-data --name client.app

RBD 持久化挂载

手动 rbd mapmount 在重启后会消失。用 systemd unit 固化:

ini
[Unit]
Description=Map Ceph RBD app-data
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/rbd map rbd-pool/app-data --name client.app
ExecStart=/usr/bin/mount /dev/rbd/rbd-pool/app-data /data/app
ExecStop=/usr/bin/umount /data/app
ExecStop=/usr/bin/rbd unmap /dev/rbd/rbd-pool/app-data

[Install]
WantedBy=multi-user.target

生产里要加等待 Ceph 网络和 keyring 的依赖。RBD 数据盘挂上之前如果应用先启动了,数据会写到本地空目录而不是真正的数据盘上。

CephFS 核心组件

CephFS 的文件内容存在 OSD 的数据池里,目录树、文件名、权限、inode 这类元数据由 MDS 管理:

两个底层 Pool:

Pool存放内容
metadata pool目录树、inode、文件权限和元数据
data pool文件内容数据块

MDS 异常时,目录遍历、创建、删除、rename 这类元数据操作会直接受影响——不一定是数据池慢。

MDS 常见状态:

状态含义
active当前提供服务
standby待命,active 故障后接管
standby-replay跟随 active 回放日志,接管更快
replay/resolve故障恢复中间态

创建 CephFS

bash
# metadata pool 用较少的 PG,data pool 用较多的 PG
ceph osd pool create cephfs_data 64
ceph osd pool create cephfs_metadata 32
ceph osd pool application enable cephfs_data cephfs
ceph osd pool application enable cephfs_metadata cephfs

ceph fs new cephfs cephfs_metadata cephfs_data
ceph fs ls

部署 MDS(至少保留 standby):

bash
ceph orch apply mds cephfs --placement="3 ceph01 ceph02 ceph03"
ceph fs status cephfs

挂载 CephFS

内核客户端(性能和稳定性通常更好):

bash
mkdir -p /mnt/cephfs

# MON 地址写多个,客户端能在 MON 之间切换
mount -t ceph 192.168.10.41:6789,192.168.10.42:6789,192.168.10.43:6789:/ /mnt/cephfs \
  -o name=admin,secretfile=/etc/ceph/admin.secret

ceph-fuse(用户态,部署和调试更方便,适合老内核):

bash
mkdir -p /mnt/cephfs
ceph-fuse -n client.admin /mnt/cephfs

CephFS 权限

CephFS 权限分两层:CephX 控制能不能访问文件系统或特定路径,Linux 文件权限控制具体读写的目录和文件。两层都通过才真正能写。

bash
# 限制只能访问 CephFS 下 /app 路径
ceph fs authorize cephfs client.app /app rw
ceph auth get client.app -o /etc/ceph/ceph.client.app.keyring

CephFS 快照

bash
ceph fs set cephfs allow_new_snaps true

mkdir -p /mnt/cephfs/app
mkdir /mnt/cephfs/app/.snap/snap-20260522
ls /mnt/cephfs/app/.snap

删除快照:rmdir /mnt/cephfs/app/.snap/snap-20260522。快照会占用后端容量——文件删了但快照还在,空间不会立刻释放。

CephFS 运行时排查

bash
ceph fs status cephfs
ceph mds stat
ceph tell mds.* status
ceph tell mds.cephfs:0 client ls   # 看哪些客户端连着 MDS,排查卡住客户端
现象方向
ls 很慢MDS 负载、目录文件过多、metadata pool 延迟
客户端卡住session/caps 异常、网络中断、MDS 切换
MDS 频繁切换MDS 进程异常、内存不足、metadata pool 慢
空间不释放快照未删、客户端仍持有已删除文件
单目录特别慢单目录下文件过多,元数据集中

CephFS 的慢不一定是数据池慢。目录遍历和元数据操作更偏向 MDS 和 metadata pool,大文件顺序读写才更偏 OSD 数据池和网络。

常见故障汇总

RBD:

现象方向
rbd map 失败ceph.conf、keyring、内核模块、MON 网络
挂载文件系统失败未格式化、文件系统损坏、重复挂载
无法删除镜像有快照、有 watcher、被克隆依赖
扩容后空间不变文件系统还没扩——镜像 resize 和 fs 扩容是两个步骤
老系统 map 失败RBD feature 和内核版本不兼容

CephFS:

现象方向
挂载失败MON 地址、key 文件存在、MDS 状态、客户端版本
目录操作慢MDS 负载、单目录文件数量、metadata pool 延迟
文件读写慢OSD 延迟、网络、客户端缓存不足
权限异常CephX 权限和 Linux 文件权限各查各的
MDS active 不稳定MDS 日志、内存、metadata pool、standby 是否正常接管

客户端排查入口:

bash
mount | grep -E 'ceph|rbd'
dmesg | grep -i ceph | tail -50
lsblk

集群侧排查入口:

bash
ceph -s
ceph health detail
ceph osd perf
ceph fs status cephfs
rbd status rbd-pool/app-data

客户端报 IO 慢时,根因常常在 OSD slow ops、PG recovery、某块 OSD 磁盘延迟或 MDS 负载。同时看客户端和集群状态,不要只看一边。