Ceph 生产环境搭建 | 第 12 天:CephFS 分布式文件系统部署与挂载

第 12/20 天 · Ceph 生产环境搭建系列

引言:为什么需要 CephFS

在前面的篇章里,我们已经用 Ceph 承载了块存储(RBD)和对象存储(RGW)两类业务。RBD 适合给虚拟机/容器挂「虚拟磁盘」,RGW 适合 S3 兼容的海量小文件场景。但很多生产业务——AI 训练数据集、HPC 高性能计算、共享文档、容器镜像仓库——需要的是POSIX 语义的共享文件系统:多个节点能并发挂载同一目录树,并且支持 open/read/write/lsdir/chmod 这类标准文件操作。

这就是 CephFS 的用武之地。CephFS 是 Ceph 原生的分布式文件系统,直接跑在 RADOS 之上,元数据与数据分离存储,具备近乎无限的横向扩展能力和强一致性语义。本篇将基于 Ceph Squid (v19) 在 Ubuntu 24.04 LTS 上完成 CephFS 的全流程部署、多 MDS 高可用配置、内核/FUSE 挂载以及客户端鉴权,并给出生产环境的踩坑提示。

K8s Logo

一、架构与原理:CephFS 的三段式设计

理解 CephFS 必须抓住它的核心设计哲学:元数据与数据彻底分离。

1.1 组件拓扑

CephFS 的运行依赖三类 RADOS 资源与两类进程:

组件 作用 存储位置
数据池(data pool) 存放文件实际内容,按对象条带化 RADOS OSD,通常副本 3 或纠删码
元数据池(metadata pool) 存放 inode、dentry、目录树结构 RADOS OSD,必须副本 3,SSD 优先
MDS(Metadata Server) 处理元数据请求、维护客户端 caps cephadm 管理的容器化守护进程
CephFS 客户端 通过内核态或 FUSE 挂载访问 业务节点
Journal 对象 MDS 日志,崩溃后快速恢复 元数据池内的特殊对象

1.2 数据流向

CephFS 的精妙之处在于:客户端只与 MDS 交互元数据,数据读写直接走 OSD。

  1. 客户端执行 open("/data/train.csv"),先向 MDS 查询路径 → inode 映射,MDS 返回该文件的对象布局(stripe_unit、stripe_count)和capability(cap)授权。
  2. 客户端拿到 cap 后,直接向 OSD 读写对象,不再经过 MDS,从而把带宽压力从元数据节点卸载。
  3. 客户端关闭文件或 cap 被回收时,向 MDS 提交脏元数据(如 mtime/size 变更)刷盘。

这种「元数据集中、数据直连」的模型,使得 CephFS 能在数百个客户端并发读写时仍保持高吞吐——MDS 只承担「查找」而非「搬运」。

1.3 MDS 高可用与多活机制

从 Ceph Quincy (v17) 起,CephFS 原生支持多活 MDS(multi-active):

  • max_mds 决定同时活跃的 MDS 数量(默认 1,即 active-standby)。
  • 设置 max_mds=2 后,两个 MDS 同时为 active,各自负责目录树的一部分子树(subtree partitioning),元数据负载分担到多个节点。
  • 其余 MDS 作为 standby,active 宕机时秒级接管,元数据池的多副本保证不丢元数据。
  • 每个 active MDS 将日志写入元数据池的 journal 对象,standby 通过 replay journal 快速接管。

1.4 文件布局(File Layout)

CephFS 把文件切成等大的 stripe_unit(默认 64KB),按 stripe_count 个对象轮转写入:

💻 代码示例

file_content → [obj0][obj1][obj2]… 每个对象 stripe_unit 大小,跨 OSD 分布

stripe_count=1 时是简单分片;调大 stripe_count 可让单文件带宽跨越更多 OSD,适合大文件顺序读吞吐场景。

二、部署实战:从建池到挂载

假设集群已用 cephadm 引导完成(见第 3 天),MON/MGR/OSD 均已就绪,节点 node-1..node-5 运行 Ubuntu 24.04 LTS,OSD 采用 NVMe SSD。

2.1 创建专用存储池

CephFS 必须有两个池:元数据池用副本、数据池可选纠删码。元数据池严禁用纠删码——MDS 的原子性操作依赖对象覆盖写,纠删码不支持。

💻 代码示例

# 1. 元数据池:3 副本,PG 数按 OSD 规模估算(32 个 OSD 选 256)

ceph osd pool create cephfs_metadata 256 256 replicated

ceph osd pool set cephfs_metadata size 3

ceph osd pool set cephfs_metadata min_size 2

# 元数据对延迟敏感,强制落到 SSD class

ceph osd pool set cephfs_metadata crush_rule ssd_replicated_rule

 

# 2. 数据池:3 副本(也可换 EC profile,见第 9 天)

ceph osd pool create cephfs_data 512 512 replicated

ceph osd pool set cephfs_data size 3

ceph osd pool set cephfs_data min_size 2

 

# 3. 启用 pool 的自愈伸缩(Squid 默认 pg_autoscale,仍建议显式声明)

ceph osd pool set cephfs_metadata pg_autoscale_mode on

ceph osd pool set cephfs_data pg_autoscale_mode on

2.2 初始化文件系统并启用 MDS 服务

💻 代码示例

# 创建 CephFS(一次即可):参数顺序为 名称 元数据池 数据池

ceph fs new prod_fs cephfs_metadata cephfs_data –force

# 默认会启用 inline_data(小文件内嵌元数据对象),大数据场景可关闭

ceph fs set prod_fs inline_data false

 

# 部署 MDS:用 cephadm 的 service spec 方式声明式部署

cat > /tmp/mds-spec.yaml << 'YAML'

service_type: mds

service_id: prod_fs

placement:

count: 3

host_pattern: "node-*"

YAML

ceph orch apply -i /tmp/mds-spec.yaml

 

# 等待 MDS 进入 active 状态

ceph -s | grep mds

ceph fs status prod_fs

2.3 配置多活 MDS(生产推荐)

💻 代码示例

# 设置同时活跃的 MDS 数为 2,第三个为 standby

ceph fs set prod_fs max_mds 2

# 查看子树分担情况

ceph fs status prod_fs

ceph tell mds.prod_fs.0 session ls

# 配置 standby replay,让 standby 预热元数据以加速接管

ceph config set mds mds_standby_replay true

2.4 创建客户端并下发密钥

CephFS 客户端需要 cephx 凭据。生产环境永远不要用 admin keyring 给业务挂载,应按业务划分独立用户。

💻 代码示例

# 创建专用客户端 cephfs.prod,仅授权访问 prod_fs 的数据池与元数据池

ceph fs authorize prod_fs client.cephfs.prod / rw >> /etc/ceph/ceph.client.cephfs.prod.keyring

 

# 拷贝 keyring 到业务节点并修正权限

scp /etc/ceph/ceph.client.cephfs.prod.keyring client01:/etc/ceph/

ssh client01 "chmod 600 /etc/ceph/ceph.client.cephfs.prod.keyring"

 

# 同时下发 ceph.conf(客户端需要 mon_host 与 fs 名)

scp /etc/ceph/ceph.conf client01:/etc/ceph/

2.5 内核态挂载(推荐生产使用)

Ubuntu 24.04 内核 6.8+ 的 ceph 内核模块已支持 CephFS 最新特性,性能优于 FUSE,生产首选内核挂载。

💻 代码示例

# 在 client01 上:内核挂载,指定 fsname 与客户端密钥

mkdir -p /mnt/cephfs

mount -t ceph -o name=cephfs.prod,secretfile=/etc/ceph/ceph.client.cephfs.prod.keyring,fsname=prod_fs

10.0.0.10:6789 /mnt/cephfs

# 10.0.0.10 为 MON 的公共网络 VIP

 

# 验证挂载点

stat -f /mnt/cephfs

df -h /mnt/cephfs

echo "test" > /mnt/cephfs/health_check && cat /mnt/cephfs/health_check

开机自动挂载写入 /etc/fstab:

💻 代码示例

# /etc/fstab — CephFS 内核挂载(_netdev 表示网络就绪后挂载)

10.0.0.10:6789:/ /mnt/cephfs ceph name=cephfs.prod,secretfile=/etc/ceph/ceph.client.cephfs.prod.keyring,fsname=prod_fs,_netdev,noatime 0 0

2.6 用状态文件验证集群

部署完成后用一份 JSON 状态检查脚本输出关键指标,便于纳入监控:

💻 代码示例

#!/usr/bin/env python3

"""CephFS 部署后健康自检 — 输出 JSON 便于 Prometheus node_exporter textfile 采集"""

import json, subprocess, sys

 

def run(cmd):

return subprocess.run(cmd, shell=True, capture_output=True, text=True).stdout.strip()

 

fs = run("ceph fs status prod_fs –format=json")

status = json.loads(fs) if fs else {}

mds_active = [m for m in status.get("mdsmap", {}).get("by_rank", []) if m.get("state") == "active"]

print(json.dumps({

"fs_name": status.get("mdsmap", {}).get("fs_name", "prod_fs"),

"active_mds_count": len(mds_active),

"total_mds": len(status.get("mdsmap", {}).get("by_rank", [])),

"data_pool": status.get("mdsmap", {}).get("data_pools", []),

"standby_count": len(status.get("mdsmap", {}).get("standbys", [])),

}, indent=2))

运行后应有类似输出,确认 active+standby 都在位:

💻 代码示例

{

"fs_name": "prod_fs",

"active_mds_count": 2,

"total_mds": 2,

"data_pool": [3],

"standby_count": 1

}

三、关键配置参数详解

参数 默认值 生产建议 说明
max_mds 1 2~4 同时活跃 MDS 数,按元数据压力调
mds_cache_size 1GB 4~16GB 单 MDS 元数据缓存上限,SSD 节点可放大
mds_standby_replay false true standby 回放日志预热,加速接管
mds_log_max_segments 2 30~50 journal 段数,影响崩溃恢复时长
inline_data true false 大文件场景关闭,避免元数据对象膨胀
stripe_unit 64KB 1~4MB 大文件吞吐场景调大
stripe_count 1 4~8 单文件跨越 OSD 数,按带宽需求调
osd_pool_default_pg_autoscale on on 让 PG 自动伸缩,省去手动估算
💻 代码示例

# 批量设置 MDS 运行时参数(所有 MDS 生效)

ceph config set mds mds_cache_size 8589934592 # 8GB

ceph config set mds mds_standby_replay true

ceph config set mds mds_log_max_segments 30

# 单目录布局调整(针对大数据子目录)

ceph fs set-layout prod_fs –pool cephfs_data –stripe_unit 4M –stripe_count 8

四、生产环境注意事项与踩坑提示

  1. 元数据池必须 3 副本且落在 SSD。 纠删码池不支持 MDS 的覆盖写与 journal,一旦误用,集群会拒绝创建 fs 并报错 pool does not support overwrite。元数据延迟直接决定小文件 ls/open 体验,机械盘做元数据池是大忌。
  2. 多活 MDS 不是越多越好。 max_mds 超过 4 后子树迁移开销上升,反而拖慢元数据吞吐。生产 2~4 个 active 即可,并保持至少 1 个 standby replay。
  3. 客户端密钥分发要走配置管理。 不要把 admin keyring 复制到业务节点。用 Ansible/Secret 按业务下发独立 client keyring,权限按路径前缀最小化授权。
  4. 内核挂载优于 FUSE。 Ubuntu 24.04 的内核 ceph 模块支持 Squid 全部特性且零拷贝;FUSE(ceph-fuse)有用户态上下文切换开销,仅在内核模块缺失时使用。
  5. 大目录 readdir 风暴会打挂 MDS。 单目录百万级文件 readdir 会让单 MDS 内存暴涨;建议按业务分片成多级子目录,并开启 mds_bal_fragment 让大目录自动分裂到不同 MDS。
  6. 挂载点 noatime 必加。 默认 atime 每次读都回写元数据,对 CephFS 是放大元数据 I/O 的灾难,fstab 必须加 noatime。
  7. 跨机房灾备要搭配 Ceph 多活/快照。 CephFS 本身不支持跨 stretched cluster 的双写,异地灾备应使用 ceph fs snapshot + 异步 rbd mirror 思路,详见第 18 天。
  8. 不要在 CephFS 上跑随机覆盖写多的数据库。 CephFS 强一致但小对象随机写延迟偏高,DB 类业务请走 RBD(第 10 天)。

五、常见问题

Q1:挂载报错 “mount error 5 = Input/output error” 怎么排查?
A:九成是客户端 keyring 与 fsname 不匹配。用 ceph auth ls client.cephfs.prod 确认 caps 包含 mds "allow rw path=/" 与 osd "allow rw pool=cephfs_data",并核对挂载命令的 fsname= 与 name=。其次检查 MON 公共网络 VIP 是否可达,ceph -s --name client.cephfs.prod 能否拉到集群状态。

Q2:多活 MDS 后 standby 一直不转 active,正常吗?
A:正常。standby 仅在某个 active 故障时才晋升;想观察子树分担,用 ceph tell mds.prod_fs.0 dump_tree。若想让 standby 始终预热,确认 mds_standby_replay=true。

Q3:CephFS 数据池能否从副本改纠删码以省空间?
A:可以但需谨慎。CephFS 自 Quincy 起支持 EC 数据池,但 EC 延迟高、不支持覆盖写,小文件元数据内联会失效。建议先用副本池跑稳,再单独建 EC 池做冷数据归档,用 ceph fs subvolumes 做分层。

六、总结

本篇我们在已就绪的 Ceph Squid 集群上完成了 CephFS 的端到端部署:建立元数据/数据双池、声明式部署多 MDS、配置多活与 standby replay、生成最小权限客户端、内核态挂载并写入 fstab 开机自启。CephFS 把「元数据集中、数据直连 OSD」的设计落到 POSIX 语义上,使其成为大规模共享文件存储的生产级方案。掌握 pool 选型、MDS 缓存与子树分担调优,是让 CephFS 在百万文件、百客户端并发下稳定运行的关键。

下期预告

第 13 天我们将切入 Ceph 集群的网络架构:Ceph 网络架构:集群网络与公共网络分离。会拆解 cluster network 与 public network 的流量边界,讲解 BlueStore/OSD 心跳、客户端 IO 与 OSD 间副本流量如何分流,并给出双网卡绑定与 VLAN 隔离的实战配置。

系列目录

微信公众号二维码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像 - 恒星
欢迎您留下宝贵的见解!
提交
头像 - 恒星

昵称

取消
昵称表情代码图片快捷回复

    暂无评论内容