简介:这份 Linux 环境下的 Ceph 中文文档合集面向云存储运维、分布式存储学习者和需要部署 Ceph 集群的开发人员,围绕 Ceph 节点、网络与存储集群的搭建展开,覆盖对象存储、块设备、文件系统等常见使用方向,适合从入门查阅到部署实践的多层级读者。压缩包共 482 个文件,约 4.04MB,以 346 个 rst 文档为主体,辅以 txt 说明、conf 配置样例、sh 脚本、py 工具以及 png、jpg、svg 等图示,另有少量 html、json、yml 等文件,便于按主题检索配置与概念说明。已有 422 人学习,说明其在 Ceph 中文资料中具有一定参考价值。读者可从中获得集群部署相关的配置思路、组件说明与图示材料,借助脚本和样例加深对 Ceph 节点、网络及存储服务的理解,也能为对象存储、块设备和文件系统等场景的资料查阅提供较完整的文档基础。
1. 一套三节点集群卡在 HEALTH_WARN 之后,我把这份 Ceph 中文文档翻烂了
在 Linux 开发这个大类目下翻资料,「Ceph 中文文档」几乎是绕不开的一站。我最初接触它是因为一套三节点测试集群:装完敲ceph -s满屏 HEALTH_WARN,英文文档要连跳十几个页面才能把 mon、osd、pg 三件事对上号。这套中文文档把架构分层、部署流程、RBD/CephFS/RGW 三种接口、CRUSH 规则和运维排障用同一套术语串了起来,命令和默认值就挨着概念放。它适合要在内网自建块存储或共享文件系统的 Linux 运维,也适合读源码前先补概念的开发。下面按我实际拆包、照做的顺序写。
2. 文档骨架怎么读:把 RADOS、CRUSH、PG 三层概念对齐
2.1 先认底座:RADOS 是存储层,三种接口只是外壳
很多人一上来就找「怎么挂载 CephFS」,翻到挂载命令抄完就撤,结果一遇到 MDS 起不来、PG 卡在undersized就彻底没方向。这份文档的编排逻辑是先讲 RADOS——由 MON、OSD、MGR 组成的那层可靠的分布式对象存储,再往上才是三种访问接口:RBD 提供块设备,CephFS 提供 POSIX 文件系统,RGW 提供 S3/Swift 对象网关。底座不稳,上面三种接口全是幻觉。
我一般的读法是先看文档里的组件职责表,把每个守护进程「管什么、不在了会怎样」记住:MON 维护集群图(Cluster Map)和仲裁,三个 MON 挂两个就写不进去;OSD 才是真正存数据、做副本、做恢复的,一个 OSD 对应一块盘;MGR 不参与数据路径,但 dashboard、pg autoscaler、模块化指标全靠它;MDS 只服务 CephFS 的元数据,RBD 和 RGW 完全不需要它。这个对应关系记熟了,后面看到ceph orch ps的输出才不会一头雾水。
提示:如果你只是要块存储,别顺手把 MDS 也拉起来。多一个常驻守护进程,就多一份要盯的日志。
2.2 CRUSH 与 PG:数据放哪、放几份,是两个问题
文档里最容易读快的就是这一段。CRUSH 决定「副本往哪些故障域放」,PG 决定「数据先切成多少份再映射到 OSD」。两件事混在一起想,就会出现「我 size 设了 3,为什么还是undersized」这种经典翻车。
先看 CRUSH。默认的replicated_rule以 host 作为故障域,意思是同一份 PG 的三个副本必须落在三台不同主机上。这意味着三副本的最小可用规模就是三台机器(或者三台以上的机器、每台至少一块 OSD)。你要是拿两台机器、各插四块盘凑 size=3,CRUSH 根本凑不出三个 host,PG 会一直卡在undersized,而且永远不自动恢复。
再看 PG 数。池创建时pg_num和pgp_num两个参数经常被一起抄,但含义不同:pg_num是 PG 总数,pgp_num是参与数据分布的 PG 数,正常情况下两者相等。改的时候必须pgp_num跟着pg_num走,跳着改会触发大规模重平衡。
常用的池参数我整理成一张表,照着改不容易出错:
| 参数 | 作用 | 三节点测试环境建议值 | 改错的后果 |
|---|---|---|---|
size | 每份数据的副本数 | 3 | 大于故障域数量则永远 undersized |
min_size | 允许写入的最小副本数 | 2 | 设成 3 时,单盘故障即全池只读 |
pg_num | PG 总数 | 按 OSD 数算,取 2 的幂 | 过小导致单 PG 过大、恢复慢 |
pgp_num | 参与分布的 PG 数 | 与pg_num相同 | 不一致时数据分布停滞 |
pg_autoscale_mode | 自动调 PG | on | 关掉后要人工盯容量 |
min_size 设成 3 是新手最常犯的错:三节点集群里挂掉一块盘,整池立刻变成只读,业务侧报的是「写不进去」,而ceph -s只是 HEALTH_WARN,看着不像大事。
2.3 把文档当查表用:三个定位默认值的命令
文档里散落着大量配置项名,osd_max_backfills、mon_osd_nearfull_ratio、osd_pool_default_size这些,光记住名字没用。我习惯用三条命令把「文档里写的」和「机器上生效的」对上:
# 1. 查某个守护进程当前生效的配置(含默认值与来源) ceph config get osd osd_max_backfills # 2. 查这个配置项的说明、类型、默认值,比翻文档快 ceph config help osd_max_backfills # 3. 直接读本机 ceph.conf 合并后的结果,适合排查"改了没生效" ceph-conf --name osd.0 --lookup osd_mclock_profile第一条命令返回的是该守护进程实际生效值,可能是默认值、可能是ceph config set设的、也可能是集中式配置库里下发的;第二条会打印类型(比如uint)、默认值、可选取值范围,遇到「文档写了可以设 0 但设了报错」这种情况,用它一查就知道是不是有下限;第三条读的是本地配置文件,用来判断「我明明改了 ceph.conf 为什么没生效」——因为集中式配置库的优先级高于本地文件,这是血泪经验。
注意:
ceph config set默认写的是全局段,加--daemon只对单个守护进程生效,加--who可以指定到osd.*或client.*。级别选错,改完ceph -s没变化就以为命令失效了。
3. 照着文档起集群:三节点从裸机到 HEALTH_OK
3.1 前置检查:主机名、时间同步、端口三件事
部署章节我会先跳到「前置条件」那一页,因为九成的 bootstrap 失败都出在这三件事上,跟 Ceph 本身没关系。
主机名必须能正反解析,而且节点之间要用同一个名字互相认识。临时用/etc/hosts顶一下可以,但ceph orch host add用的名字要和hostname输出完全一致,带不带域名后缀都算两个不同主机。
时间同步是硬要求。MON 之间时钟偏差过大会直接掉仲裁,表现是ceph -s卡住不返回、ceph mon stat报 quorum 只有 1。我一般统一用 chrony,检查一条命令就够:
# 三个节点都执行,确认本机已被上游授时源同步(^* 开头那行) chronyc sources -v chronyc tracking | grep -E "System time|Leap status" # 主机名与解析自检 hostnamectl --static getent hosts node1 node2 node3端口方面,MON 用 3300(v2)和 6789(v1),OSD、MDS、MGR 共用 6800-7300 这段范围。测试环境图省事可以直接关掉防火墙,生产环境必须按段放行:
# 以 firewalld 为例,三节点都执行 sudo firewall-cmd --permanent --add-port=3300/tcp sudo firewall-cmd --permanent --add-port=6789/tcp sudo firewall-cmd --permanent --add-port=6800-7300/tcp sudo firewall-cmd --reload sudo firewall-cmd --list-ports放行完记得在两个节点之间用nc -zv node2 3300这种笨办法验一遍。别问为什么,我曾经因为云厂商安全组只开了 6789 没开 3300,排查了一个下午。
3.2 cephadm bootstrap 与节点纳管
文档里通常给了两条部署路线:早期的ceph-deploy手工装包,和现在主推的cephadm。测试环境我建议直接走 cephadm,容器化部署把依赖问题挡在外面,出问题也好清理。
在首发节点执行引导,注意--mon-ip必须是其他节点能访问到的地址,不是 127.0.0.1:
# 三个节点统一从发行版仓库装 cephadm sudo dnf install -y cephadm # 首发节点引导集群:--mon-ip 为本机对外地址,--cluster-network 是后端复制网段 sudo cephadm bootstrap \ --mon-ip 10.0.0.11 \ --cluster-network 10.0.1.0/24 \ --dashboard # 输出会打印 dashboard 地址和初始密码,同时生成 /etc/ceph/ceph.client.admin.keyring ceph -s三个参数值得说清楚:--mon-ip决定 MON 对外暴露的地址,写错了后面加节点一律失败;--cluster-network是可选的独立后端网络,OSD 之间的复制、恢复流量走这个网段,实验环境没有第二块网卡就别加,加了不通会表现为 OSD 起得来但 PG 一直peering;--dashboard把 MGR 的图形界面一并拉起来,排障时看容量和 PG 分布比命令行舒服。
引导成功后,把其他两台纳管进来。需要先让新节点信任首发节点的公钥,再执行orch host add:
# 在 node1 上把公钥分发到 node2/node3 ssh-copy-id -f -i /etc/ceph/ceph.pub root@node2 ssh-copy-id -f -i /etc/ceph/ceph.pub root@node3 # 纳管,第二个参数是节点地址,必须和主机名解析一致 sudo ceph orch host add node2 10.0.0.12 sudo ceph orch host add node3 10.0.0.13 # 核对:三个节点都应该在列表里,且状态不是 offline ceph orch host ls也可以用声明式的方式一次性描述整个集群,把 host、mon、mgr、osd 全写进一个 spec 文件,ceph orch apply -i cluster-spec.yaml一把下发。这种方式的好处是可版本化,坏处是一旦写错会批量执行。文件大概长这样:
# cluster-spec.yaml:声明式描述守护进程布局 --- service_type: host hostname: node1 addr: 10.0.0.11 --- service_type: mon placement: count: 3 # MON 必须奇数个,3 是能容忍 1 台故障的最小规模 --- service_type: mgr placement: count: 2 # MGR 一主一备,多了浪费 --- service_type: osd service_id: all_drive_group placement: host_pattern: 'node*' # 匹配 node1/node2/node3 data_devices: all: true # 危险:会把节点上所有裸盘都吃掉data_devices: all: true这一行务必确认机器上没有装系统盘以外的数据盘,否则系统盘被当成 OSD 格式化,后果不用多说。
3.3 OSD 纳管与 CRUSH 故障域确认
OSD 是真正存数据的一层,也是最容易出问题的一层。懒人做法是让 cephadm 把所有可用设备都吃进去:
# 把所有未被占用的裸盘都纳管为 OSD sudo ceph orch apply osd --all-available-devices # 查看纳管进度与最终拓扑 ceph orch device ls ceph osd treeceph osd tree的输出里,host那一层就是故障域,osd是具体磁盘。三节点每节点两块盘,展开应该看到 3 个 host、总共 6 个 osd,且每个 osd 权重一致。如果某个 host 下面挂着 0 个 OSD,说明那块盘上有残留的 LVM 或文件系统签名,cephadm 不敢动——这个坑在下一章的避坑里细说。
确认默认规则确实按 host 分域:
# 看 replicated_rule 的步骤里是不是 take(host) ceph osd crush rule dump replicated_rule # 看当前 CRUSH 图里的 bucket 层级 ceph osd crush tree --show-shadow这两条命令的输出能回答一个关键问题:给定一个池的 size=3,CRUSH 有没有三个 host 可选。没有就是无解,加机器是唯一出路,改min_size只是把「写不进去」推迟到「读不出来」。
3.4 验收:ceph -s、rados bench 与一次真实写入
集群起来了不等于能用。我会做三层验收:健康状态、容量分布、实际吞吐。
# 第一层:健康状态,目标是 HEALTH_OK 或只剩可以解释的 WARN ceph -s ceph health detail # 第二层:容量与分布,确认每个 OSD 使用率接近 ceph osd df tree # 第三层:建个临时池做吞吐测试 ceph osd pool create testpool 64 64 ceph osd pool set testpool size 3 --yes-i-really-mean-it rados bench -p testpool 30 write --no-cleanup rados bench -p testpool 30 seq rados bench -p testpool 30 rand rados -p testpool cleanup ceph osd pool delete testpool testpool --yes-i-really-really-mean-itrados bench后面的30是运行秒数,数字给大一点结果才稳定;--no-cleanup保留写入的对象,这样后面的seq(顺序读)和rand(随机读)才有数据可读,不加这个参数读测试会跑在空池上,数字好看但毫无意义。三个数字里,我一般重点看 write 的带宽和 rand 的 IOPS:三节点机械盘 write 跑不到 100MB/s,多半是后端网络走了管理网;rand 的 IOPS 低于 500,要怀疑某块盘已经在报错重试。
ceph osd df tree的%USE那一列要展开看,理想情况是各 OSD 使用率相差不超过 5%。差得离谱说明 PG 分布不均,这时候别急着 reweight,先确认pg_num是不是从建池起就没调过。
4. 三种接口各跑一遍:RBD、CephFS、RGW 的最小验证
4.1 RBD:建池、建镜像、映射成本地块设备
RBD 是最常用的接口,验证路径最短:建池、启用、建镜像、映射、格式化成文件系统、跑一次 fio。文档里的命令我按顺序抄一遍并补上注释:
# 建池:pg_num 与 pgp_num 一致,测试环境 64 足够 ceph osd pool create rbdpool 64 64 # 标记为 RBD 池(启用 rbd 应用),不做这步 rbd 命令会报 pool 未初始化 rbd pool init rbdpool # 建一个 10G 的镜像,显式开启 layering(快照和克隆依赖它) rbd create --size 10240 rbdpool/vol01 --image-feature layering # 查看镜像属性,注意 features 和 order rbd info rbdpool/vol01 # 映射到本机,--id 指定用哪个客户端身份 sudo rbd device map rbdpool/vol01 --id admin rbd device list # 格式化成 xfs 并挂载 sudo mkfs.xfs /dev/rbd0 sudo mkdir -p /mnt/rbd sudo mount /dev/rbd0 /mnt/rbd--image-feature这一项值得单独讲。老内核客户端不认识exclusive-lock、object-map这些特性,映射后会直接报错,所以文档里经常建议测试环境先用layering单独开。生产上用rbd create的默认特性即可,但要确认客户端内核版本够新。
挂载好之后跑一次 fio 做粗测,重点不是绝对数字,而是「有没有明显掉底」:
# 4K 随机写,iodepth 32,4 个并发,跑 30 秒 fio --name=rbd-randwrite \ --filename=/mnt/rbd/fio.dat \ --size=2G --rw=randwrite --bs=4k \ --iodepth=32 --numjobs=4 --runtime=30 --time_based \ --group_reporting--iodepth是队列深度,机械盘拉高深度收益明显,全闪存设 16~32 就够;--numjobs是并发进程数,它和--iodepth相乘才是总并发。测出来的 IOPS 如果随时间明显下滑,看ceph -s有没有在 recovery——恢复流量会抢带宽,这时候的数字不作数。
4.2 CephFS:先有 volume,再有挂载点
CephFS 比 RBD 多一层元数据服务,所以顺序是「先建 volume(自动拉起 MDS)、再授权客户端、最后挂载」。少一步都挂不上。
# 一步建好 data/metadata 池和 MDS 守护进程,placement 指定三节点 ceph fs volume create cephfs01 --placement="3 node1 node2 node3" # 查状态:至少要有一个 active MDS ceph fs status cephfs01 ceph fs ls # 建一个只读根目录的客户端身份(生产上别直接用 admin 挂) ceph auth get-or-create client.cephfs01 \ mon 'allow r' \ mds 'allow r, allow rw path=/' \ osd 'allow rw pool=cephfs01_data' \ -o /etc/ceph/ceph.client.cephfs01.keyring # 取出明文密钥,后面挂载要用 ceph auth print-key client.cephfs01挂载有两条路线,内核客户端和ceph-fuse。内核客户端性能好但受内核版本限制,ceph-fuse兼容性好、出问题好排查。测试环境我一般先跑 fuse,通了再换内核挂载:
# 内核客户端挂载,注意 mon 地址和 secretfile 两个参数 sudo mkdir -p /mnt/cephfs sudo mount -t ceph 10.0.0.11:6789:/ /mnt/cephfs \ -o name=cephfs01,secretfile=/etc/ceph/ceph.client.cephfs01.key # 换 ceph-fuse 的写法,参数几乎一样 sudo ceph-fuse -n client.cephfs01 -m 10.0.0.11:6789 /mnt/cephfsname=后面写的是客户端实体名去掉client.前缀,写成client.cephfs01会报认证失败;secretfile指向的必须是 keyring 文件而不是密钥字符串,把密钥直接塞进secret=也可以,但会在mount的输出和 shell history 里留痕。
4.3 RGW:对象网关与一次 S3 冒烟
RGW 是唯一需要额外做 realm/zonegroup/zone 三层初始化的接口。文档里这部分顺序不能乱,先建 realm 再建 zonegroup 再建 zone,最后才是orch apply rgw。
# 三层初始化,--default 表示默认域 radosgw-admin realm create --rgw-realm=myrealm --default radosgw-admin zonegroup create --rgw-zonegroup=myzg --master --default radosgw-admin zone create --rgw-zone=myzone --rgw-zonegroup=myzg --master --default # 拉起三个 RGW 实例,端口 7480 ceph orch apply rgw myrealm myzone --placement="3 node1 node2 node3" --port 7480 ceph orch ps --daemon-type rgw # 建一个 S3 用户,记下 access/secret key radosgw-admin user create --uid=tester --display-name="tester" \ --access-key=AKIAEXAMPLE --secret-key=SECRETEXAMPLE--placement="3 node1 node2 node3"表示三个节点各一个实例,前面那个3是数量,后面是候选主机。没写端口时默认 80,测试环境用 7480 更省事。
冒烟用 aws cli 最直接,把 endpoint 指到 RGW 就行:
export AWS_ACCESS_KEY_ID=AKIAEXAMPLE export AWS_SECRET_ACCESS_KEY=SECRETEXAMPLE ENDPOINT=http://10.0.0.11:7480 aws --endpoint-url $ENDPOINT s3 mb s3://demo dd if=/dev/urandom of=/tmp/test.bin bs=1M count=64 aws --endpoint-url $ENDPOINT s3 cp /tmp/test.bin s3://demo/test.bin aws --endpoint-url $ENDPOINT s3 ls s3://demo/如果s3 mb报SignatureDoesNotMatch,九成是 access key 或者 endpoint 后面多了斜杠;报NoSuchBucket但ls能看到桶,则是 zonegroup 的endpoints没配对,用radosgw-admin zonegroup get看一眼。
4.4 三种接口怎么选:一张对照表
| 维度 | RBD | CephFS | RGW |
|---|---|---|---|
| 访问方式 | 块设备,映射成本地盘 | POSIX 文件系统,可多机共享 | HTTP,S3/Swift 协议 |
| 典型场景 | 数据库、虚拟机磁盘 | 共享目录、容器持久卷、日志 | 图片、备份归档、对象存储 |
| 依赖守护进程 | OSD、MON | 额外需要 MDS | 额外需要 RGW 实例 |
| 扩容粒度 | 镜像可在线扩容 | 目录树随池容量扩展 | 桶数量无上限 |
| 常见坑 | 内核特性不兼容导致 map 失败 | MDS 单点、元数据池容量 | realm/zone 初始化顺序错 |
选型的判断标准其实只有一条:客户端能不能改造。数据库和虚机不可能改成调 S3 API,就用 RBD;多个节点要看见同一份目录,CephFS 是唯一选择;只要按 key 存取二进制,RGW 最省事,横向扩展也最平滑。
5. 避坑与排查:五条从告警里爬出来的记录
5.1 一直 HEALTH_WARN,报 mons are allowing insecure global_id reclaim
现象:集群刚装完,ceph -s显示 HEALTH_WARN,ceph health detail只有这一条,其他都正常。
原因:这是给老客户端留的兼容开关,允许版本过旧(或者时钟偏差过大)的客户端重新注册到 MON。集群里有这种客户端时,MON 会在会话层面放宽校验。新版部署默认开着,所以新集群一装就有这条告警。
解决:确认没有老客户端在跑之后直接关掉,客户端侧顺手把 chrony 校一遍:
ceph config set mon auth_allow_insecure_global_id_reclaim false ceph health detail关掉之后如果告警变成1 clients failing to authenticate,说明确实有老客户端连不上,那就得升级客户端而不是继续放宽。
5.2 OSD 起不来,ceph-volume 有记录但 up 一直是 0
现象:ceph orch device ls显示某块盘Available: False,ceph-volume lvm list能看到对应的 LV,但ceph osd tree里那个 OSD 是down。
原因:这块盘之前被别的集群或者别的用途用过,残留了 LVM 元数据或旧的文件系统签名。cephadm 的自动纳管逻辑会跳过「看起来有数据」的盘,不会硬上。
解决:先确认这块盘确实可以清空,再用 zap 把签名抹掉,让它重新变成可用设备:
# 先看清楚上面的东西,别闭着眼睛 zap sudo ceph-volume lvm list /dev/sdb lsblk -f /dev/sdb # 确认无用后清除签名与 LVM 元数据 sudo ceph-volume lvm zap /dev/sdb --destroy # 重新触发纳管 sudo ceph orch apply osd --all-available-devices--destroy会把 VG 一起删掉,不加只清签名。这一步没有后悔药,执行前务必二次确认盘符,尤其在盘符可能漂移的机器上。
5.3 PG 长期 undersized 或 stale,加盘也不恢复
现象:ceph pg dump_stuck undersized能列出一堆 PG,ceph -s显示degraded objects,但集群容量看着还很富裕,加了几块盘也没变化。
原因:池的size大于 CRUSH 在该规则下能提供的故障域数量。最常见的是两台机器各插若干盘、size设了 3,默认规则按 host 分域,永远只能凑出 2 个 host。
解决:要么加第三台机器,要么临时降 size 并把 min_size 一起降——但后者意味着单机故障就可能丢数据,测试环境可以接受,生产环境不建议:
# 看卡住的 PG 和它们的映射目标 ceph pg dump_stuck undersized ceph pg 1.0 query | grep -A5 "acting" # 临时降副本(仅限测试环境) ceph osd pool set rbdpool size 2 ceph osd pool set rbdpool min_size 1真正正确的解法是在文档里找「故障域」那一节,用ceph osd crush rule create-replicated建一条以 osd 为域的规则,接受单机多盘同时故障的风险,而不是硬把副本塞进不存在的域。
5.4 CephFS 挂载报 mount error 22 或直接卡住
现象:mount -t ceph返回mount error 22 = Invalid argument,或者命令挂住几分钟不返回,dmesg里一堆 libceph 重连日志。
原因:三个高频点。一是name=写成了client.cephfs01,正确的是去掉前缀的cephfs01;二是secret=直接写了 keyring 文件里的 base64 密钥但带了换行;三是挂载地址用了 v2 端口 3300 但内核客户端只支持 v1 的 6789。
解决:换成 secretfile 方式避开密钥格式问题,地址先用 6789 验证:
# 检查 keyring 内容,确认是 base64 串而不是文件路径 cat /etc/ceph/ceph.client.cephfs01.keyring # 用 secretfile 挂,先确认 v1 端口连通 nc -zv 10.0.0.11 6789 sudo mount -t ceph 10.0.0.11:6789:/ /mnt/cephfs \ -o name=cephfs01,secretfile=/etc/ceph/ceph.client.cephfs01.key,noatime # 还不行就换 ceph-fuse 试,绕过内核客户端 sudo ceph-fuse -n client.cephfs01 -m 10.0.0.11:6789 /mnt/cephfs -fceph-fuse加-f前台运行,报错直接打在终端上,比翻dmesg快得多。这也是我排查 CephFS 挂载问题的固定动作:先 fuse 通了,再回头查内核客户端。
5.5 写入突然变慢,先看 osd df 再怀疑网络
现象:业务侧报写延迟翻倍,ceph -s看起来还算正常,只有少数几个 PG 状态不对。
原因:单个 OSD 使用率接近nearfull阈值(默认 0.85),主副本全压在那几块盘上,backfill 又同时在抢带宽。ceph -s的汇总数字会掩盖这种局部不均。
解决:先看分布,再决定是 reweight 还是加盘:
# 按使用率排序,一眼看出哪个 OSD 超了 85% ceph osd df tree # 临时调整权重,让 CRUSH 把部分 PG 挪走(看输出里调整了哪些 osd) ceph osd reweight-by-utilization 120 # 如果确实要维护某台机器,先 noout 再动,顺序不能反 ceph osd set noout # ... 维护动作 ... ceph osd unset nooutreweight-by-utilization后面的数字是过载阈值百分比,120 表示使用率超过平均值 120% 的 OSD 会被降权。这个操作会触发数据迁移,业务高峰期慎用。至于noout,顺序反了会触发大规模重平衡——我在这上面翻过一次车,那次重平衡跑了六个小时。
6. 把文档用成运维手册:PG 数、水位与升级窗口的验证
文档读完一遍容易,难的是把它变成每次上线前要走的几张检查表。我自己固定跑三件事:PG 数是否还在合理区间、容量水位有没有踩线、升级窗口的顺序对不对。
先说 PG 数。文档里给的经验公式是「OSD 总数 × 100 ÷ 副本数,向上取到 2 的幂」,三节点 6 块盘、三副本,算下来是 200,取 256。但这个数字只在建池时定,之后靠pg_autoscale_mode自己调。验证方式是看自动伸缩有没有真的在工作:
# 看每个池建议的 PG 数与当前值 ceph osd pool autoscale-status # 单个池深挖 ceph osd pool get rbdpool pg_num ceph osd pool get rbdpool pg_autoscale_modeautoscale-status的NEW PG_NUM列如果和PG_NUM差得远,说明伸缩被限制了或者还没到触发条件。文档里提到的一点很关键:自动伸缩只在池的使用率超过阈值时才动手,空池不建议提前调大,否则一堆空 PG 反而拖慢 peering。
再说水位。Ceph 有三道线,nearfull、backfillfull、full,默认 0.85 / 0.90 / 0.95。踩到full之后整个集群拒写,这时候连删数据都可能删不动,因为它也需要写元数据。验证方法是定期看 OSD 层的实际使用率,而不是ceph df的池级汇总:
# 看每个 OSD 的真实使用率 ceph osd df tree # 查询和调整水位阈值(集群级) ceph config get osd mon_osd_nearfull_ratio ceph osd set-nearfull-ratio 0.80 ceph osd set-backfillfull-ratio 0.85set-nearfull-ratio是集群级的快捷命令,会把值写进 OSDMap,所有 OSD 立刻生效;想持久化到配置库则用ceph config set global mon_osd_nearfull_ratio 0.80。两者区别在于前者随 OSDMap 走、后者随配置走,维护窗口里改阈值我一般两条都执行,避免某次ceph config被覆盖后阈值悄悄回弹。
最后是升级窗口。文档的升级章节讲的是顺序,我把它压成一张可执行的表:
| 步骤 | 动作 | 验证点 |
|---|---|---|
| 1 | ceph orch upgrade check | 无阻断项,所有守护进程版本可识别 |
| 2 | ceph osd set noout | ceph -s出现 noout flag |
| 3 | ceph orch upgrade start --image <目标镜像> | ceph orch upgrade status有进度 |
| 4 | 观察ceph -s与ceph orch ps | 无 daemon 卡在 error |
| 5 | ceph osd unset noout | flag 消失,PG 开始回填 |
第 2 步和第 5 步是配套的,noout期间即使有 OSD 短暂离线也不会被标记为 out,避免升级过程中触发全量重平衡。这个顺序我踩过一次坑:先 upgrades 再 set noout,结果 MGR 重启的十几秒里有两个 OSD 被判 out,回填数据量顶得上小半个集群。
注意:升级窗口里不要同时做容量变更。加盘、改
pg_num、改 CRUSH 规则都会触发数据迁移,和升级叠加在一起,出问题时根本分不清是哪个动作引起的。
从那以后我每次动集群前都强制走一遍这几张表:先ceph -s和ceph health detail存档,再确认 PG 数与水位,最后才敲任何带set的命令。这套习惯比记住多少条命令都管用,因为 Ceph 出问题的时候,能救你的往往不是命令本身,而是你手上那份额外的状态快照。希望帮到你。
本文还有配套的精品资源,点击获取