最有效手段是用ceph tell osd.* injectargs动态调参并配合setnorecover临时关停;关键参数为--osd-max-backfills、--osd-recovery-max-active、--osd-recovery-max-single-start和--osd-recovery-sleep,其中后者最柔和有效。

直接结论:用 ceph tell osd.* injectargs 动态调整 recovery 相关参数,配合 ceph osd setnorecover 临时关停,是最有效、最常用、且无需重启的手段。
哪些参数真正控制 recovery IO 带宽
recovery 流量不是靠单个“带宽限速”参数控制的,而是由一组并发数 + 睡眠时间共同压制。关键参数有四个:
-
--osd-max-backfills:单个 OSD 最大并发 backfill 数(全量回填),默认是 10;设为 1 可大幅降低磁盘争抢 -
--osd-recovery-max-active:单个 OSD 允许的最大活跃 recovery 请求数(含 log-based 和 backfill),默认是 3;设为 1 后基本只允许串行恢复 -
--osd-recovery-max-single-start:每秒最多新启动几个 recovery 请求,默认是 1;调小可防突发请求洪峰 -
--osd-recovery-sleep:每次 recovery 操作后强制休眠毫秒数,默认是 0;设为100就相当于每操作一次停 100ms,IO 占比直接压到 1% 以下
注意:--osd-recovery-sleep 是最“软”也最有效的调节阀——它不阻塞请求队列,只是拉长单次操作间隔,对 client IO 几乎无感知,但 recovery 总吞吐会线性下降。
业务高峰期一键暂停 recovery 的命令组合
当监控发现 client 延迟飙升、osd_op_w_latency 超过 200ms,或 ceph -s 显示 recovery 进度卡在某个 PG 时,立刻执行:
ceph osd set norebalance ceph osd set norecover ceph osd set nobackfill
这三条命令是原子生效的,立刻冻结所有 PG 迁移、数据恢复、全量回填行为。它们不会影响 client 读写,也不会让 OSD offline,只是把 recovery 队列挂起。
恢复时不要只敲 unset ——必须按顺序反向执行:
ceph osd unset nobackfill ceph osd unset norecover ceph osd unset norebalance
顺序错可能导致部分 recovery 仍被抑制。
为什么不能只改 ceph.conf 然后 reload?
因为 recovery 参数属于 OSD 运行时状态参数,systemctl reload ceph-osd@N 不会重载这些值;只有 injectargs 或重启进程才生效。而重启 OSD 会导致短暂 PG incomplete、client IO 报 Input/output error,生产环境不可接受。
OpenClaw 基础设施心跳监控与自动恢复:部署/卸载心跳守护进程,配置主机监控(Gateway、磁盘、内存、CPU、进程),设置飞书告警,自动重启故障Gateway。适用关键词:心跳监控、heartbeat daemon、服务器告警、自动重启、健康检查、auto recovery。
所以正确做法是:
- 先用
ceph tell osd.* injectargs '--osd-recovery-sleep 100'快速压低流量 - 观察 2 分钟,如果延迟回落,再逐步调高(比如改回 50)
- 确认稳定后,再把配置补进所有节点的
/etc/ceph/ceph.conf的[osd]段,并加注释说明用途
长期配置要加这两行:
[osd] osd_recovery_sleep = 0.1 osd_max_backfills = 1
注意单位:osd_recovery_sleep 在配置文件里单位是秒(0.1 表示 100ms),而 injectargs 里传的是毫秒(--osd-recovery-sleep 100),别混用。
容易被忽略的副作用和边界情况
backfill 和 recovery 是两种不同路径:backfill 发生在新 OSD 上线、PG 分配变更后,走的是全量拷贝;recovery 是日常同步,走日志回放。但它们共用 osd_max_backfills 和 osd_recovery_max_active,所以调低这两个值会同时压制两者。
另一个坑是:如果用了 ceph osd set norecover,但没关 nobackfill,那么当有新 OSD 加入时,backfill 仍会悄悄启动——它不受 norecover 控制。所以三者必须一起开关。
最后提醒:所有 injectargs 操作在 OSD 进程重启后失效,别以为设了一次就一劳永逸。










