知道,而且这是 Ceph 运维里非常关键的一对概念。
1) down:表示"当前不可达/不在工作"
-
含义 :MON/OSD 心跳认为该 OSD 当前不在线(进程挂了、机器宕机、网络断了、严重卡顿导致心跳超时等)。
-
谁设置 :通常由 MON 根据心跳自动判断(也可能管理员手工干预,但常见是自动)。
-
直接影响
-
该 OSD 上的 PG 对外服务会立刻受影响:
- 副本数不足 (degraded),可能出现 peering 、undersized 、stale 等状态。
-
但 CRUSH 仍然认为它是"in"(如果它还没 out),所以它仍在 CRUSH 计算的"候选集合"里,只是因为不可达而无法实际提供 I/O。
-
-
典型场景:短暂网络抖动、重启 OSD、主机维护等。你通常希望它能很快回来,而不是立刻触发大规模数据迁移。
2) out:表示"被从数据放置集合中移除"
-
含义 :CRUSH/OSDMap 认为该 OSD 不再参与数据放置与承载(即使它物理上在线也不应该再接收/保存副本)。
-
谁设置
- 可以手工:
ceph osd out <id> - 也可以自动:OSD 长时间
down后,MON 依据mon_osd_down_out_interval把它 自动标记 out(你配置里该值是 2000 秒,约 33 分钟)。
- 可以手工:
-
直接影响
- 集群会开始把原本放在该 OSD 上的数据副本 迁移/重建到其他 OSD(recovery/backfill),以恢复副本数(size)。
- 这会带来明显的后台 I/O、网络流量和恢复压力,也可能影响前台性能。
-
典型场景:磁盘坏了、主机长期下线、你确认短期不会回来,或者你要永久下架该盘/该节点。
3) 二者关系与组合状态
-
down与out可以同时存在,也可以单独出现:- down + in:OSD 挂了,但集群暂时认为它仍是成员,通常会等待其恢复(直到 down 太久可能自动 out)。
- up + out:OSD 进程在线,但被剔除出 CRUSH(常见于你手工 out 做维护/下架;此时它在线也不会被用于放置数据)。
- down + out:既不可达,又被剔除;集群会把数据往别处迁移(或已经迁移中/迁移完)。
4) 运维上最重要的判断原则
- 你只要把 OSD 标记 out,基本等价于告诉集群:"不要等它了,开始搬数据"。
- 如果只是短时间维护或你不确定是否会很快恢复,通常先处理 down 的根因(网络/进程/主机),避免过早 out 引发大规模 backfill。
如果你愿意描述一下你的具体现象(例如:是单个 OSD down 还是整机多 OSD down、持续多久、是否已经触发 degraded/backfill、有没有设置 noout 标志),我可以按"最小扰动"原则给你一个处理顺序。
是的,你的理解是正确的。
在 down + in 的状态下,不会立刻触发数据迁移(recovery / backfill)。下面我用"机制层面 + 运维层面"把这点说清楚,避免常见误解。
一、为什么 down + in 不会立刻迁移数据(核心原因)
1️⃣ CRUSH 视角:OSD 仍然是"合法成员"
-
in的含义是:该 OSD 仍然参与 CRUSH 数据放置计算
-
所以从 OSDMap/CRUSH 的角度看:
- PG 的 目标副本集合(acting set / up set)没有改变
- 只是其中某个 OSD 暂时不可达
👉 CRUSH 没变,就没有"重新放置"的理由
👉 没有重新放置,就不会启动 backfill
2️⃣ Ceph 的设计目标:避免"短抖动=大迁移"
Ceph 明确区分:
- 可恢复的短期故障(down)
- 结构性成员变化(out)
如果 down 就立刻迁移:
- 网络抖动、OSD 重启都会引发 TB 级 backfill
- OSD 回来后还要 再迁移回来一次
- 集群性能会被严重拖垮
所以:
只有当 OSD 被判定为"不再回来"时(out),才启动数据迁移。
二、down + in 状态下,集群实际会发生什么
✔ 会发生的事情
-
PG 可能进入:
degradedundersizedpeering
-
读写行为:
- 有足够副本仍然在线 → 读写继续
- 写入会受限(取决于 pool 的
size / min_size)
-
MON 持续等待该 OSD 恢复
-
不会产生大规模 backfill
❌ 不会发生的事情
- ❌ 不会把该 OSD 上的数据副本迁移到其他 OSD
- ❌ 不会改变 PG 的 CRUSH 归属
- ❌ 不会马上恢复副本数
三、什么时候才会开始迁移?(关键触发点)
情况 1:OSD 被标记为 out
-
手工:
bashceph osd out <id> -
自动:
inimon_osd_down_out_interval = 2000 # 你这里是约 33 分钟OSD
down超过该时间 → MON 自动out
👉 一旦变成 out,立刻开始 backfill / recovery
情况 2:你主动干预
-
设置:
bashceph osd set noout即使 OSD down 很久,也不会自动 out(常用于维护窗口)
四、一个典型时间线(非常重要)
假设:
- pool:
size=3 - OSD.12 异常
⏱ 时间轴
T0 OSD.12 心跳丢失 → down + in
T0~T+33min PG degraded,但不迁移
T+10min OSD.12 恢复 → up + in(一切正常)
👉 没有任何 backfill,影响最小
如果 OSD 没回来:
T0 down + in
T+33min MON 自动 osd out 12
T+33min+ 开始 recovery/backfill
五、运维中的一句"黄金原则"
Down 是"状态判断",Out 是"结构决策"
down:"我现在联系不上它"out:"我决定不再指望它了"
六、你这套配置下的特别说明(结合你前面给的参数)
你配置里:
ini
mon_osd_down_out_interval = 2000
osd_recovery_max_active = 1
osd_recovery_sleep = 0.4
这意味着:
- down 33 分钟内:不会迁移
- 一旦 out:迁移会非常温和、慢,但对前台影响小
👉 这是一个非常保守、以业务稳定优先的策略组合。
如果你愿意,我可以:
- 给你一个 OSD 维护的"标准操作流程(SOP)"
- 或帮你判断:当前某个 down OSD 要不要立刻 out(基于 pool size / min_size / 当前 PG 状态)
你可以直接贴一段 ceph -s 或 ceph osd tree 的输出,我可以帮你判断风险。
mon_osd_min_up_ratio 是 MON 侧的"安全阈值参数" ,用于在 OSD 大面积异常时,阻止集群进入破坏性状态 。它的作用经常被误解,下面我从定义 → 触发条件 → 实际影响 → 与相近参数对比四个层面把它讲清楚。
一、mon_osd_min_up_ratio 是做什么的(一句话版)
当处于
up状态的 OSD 占比低于该阈值时,MON 会进入"保护模式",拒绝或限制一系列会导致集群雪崩的状态变更操作。
它的核心目标只有一个:
防止"半个集群挂了,还继续重平衡/选主/写入",从而把好好的数据弄坏。
二、什么叫 up ratio(非常关键)
先明确几个概念:
-
up:OSD 进程在线、能心跳、能通信 -
in:OSD 参与 CRUSH 数据放置 -
up ratio:textup_ratio = up_osds / total_osds
例如:
- 总 OSD = 100
- 当前 up = 35
→up_ratio = 0.35
三、mon_osd_min_up_ratio 的触发条件
假设配置:
ini
mon_osd_min_up_ratio = 0.3
当:
text
up_osds / total_osds < 0.3
即:
只有不到 30% 的 OSD 处于 up 状态
MON 就会认为:
"集群已经严重失常,不能再做任何可能造成不可逆破坏的动作"
四、触发后,MON 会"禁止"哪些行为(重点)
当低于 mon_osd_min_up_ratio 时,MON 会 拒绝或冻结 以下行为:
1️⃣ 禁止自动将 OSD 标记为 out
- 即使 OSD 已经
down很久 - 即使超过
mon_osd_down_out_interval
👉 避免在大面积故障时触发海量 backfill
2️⃣ 禁止 PG 自动重映射(rebalancing / recovery)
-
不再进行:
- backfill
- recovery
- remap
-
PG 状态会停留在 degraded / undersized
👉 宁可服务降级,也不破坏数据结构
3️⃣ 禁止危险的 pool/OSDMap 变更
-
比如:
- 某些 CRUSH 相关更新
- 可能导致 PG 大规模变动的操作
4️⃣ 写入可能被进一步限制(间接影响)
-
如果:
- pool 的
min_size无法满足 - 副本数不足
- pool 的
-
写入会失败(这是 OSD/PG 层决定的,但该参数会让状态长期停留)
五、这个参数"不做什么"(常见误区)
❌ 它不会:
- 不会自动把 OSD 标记为
down - 不会直接停止集群
- 不会主动杀进程
- 不会修复任何 OSD
它只是一个 "MON 决策刹车阀"。
六、和几个容易混淆的参数对比(非常重要)
| 参数 | 控制维度 | 含义 |
|---|---|---|
mon_osd_min_up_ratio |
up | 至少多少比例 OSD 在线 |
mon_osd_min_in_ratio |
in | 至少多少比例 OSD 仍在 CRUSH |
mon_osd_down_out_interval |
时间 | down 多久后自动 out |
noout flag |
人工 | 人为禁止 OSD out |
一句话区分:
-
min_up_ratio:"在线的 OSD 太少了,先别动结构"
-
min_in_ratio:"参与数据放置的 OSD 太少了,别继续搞"
七、结合你前面给的配置(很重要)
你之前贴的配置里有:
ini
mon_osd_min_in_ratio = 0.3
如果你同时有:
ini
mon_osd_min_up_ratio = 0.3
那意味着:
-
只要有 ≥30% 的 OSD 仍然 up 且 in
- 集群允许继续恢复、out、backfill(但你又用 recovery 限流参数控制了速度)
-
低于 30%
- 集群进入"冻结保护状态"
- 不再自动 out
- 不再 rebalancing
👉 这是一个 典型的"容灾型保守配置",适合:
- 硬件规模较大
- 对误操作/雪崩极度敏感
- 宁可短期不可写,也不愿冒数据结构风险的场景
八、一个非常现实的运维判断公式(送你)
是否应该让 MON 继续自动 out OSD?
看三个值:
text
up_ratio
in_ratio
min_size / size
-
如果:
up_ratio < mon_osd_min_up_ratio- 或
in_ratio < mon_osd_min_in_ratio
-
那么:
任何"out"操作都应该非常谨慎,甚至暂停
九、总结一句话(可当速记)
mon_osd_min_up_ratio是 MON 的"紧急刹车",
当在线 OSD 太少时,禁止一切可能导致 PG 大规模迁移或结构变化的自动决策。
如果你愿意,我可以:
- 帮你判断 这个值在你当前 OSD 数量下是否合理
- 或结合你某次真实故障(比如"掉了一半节点")推演 Ceph 实际会怎么反应
你可以直接告诉我:
总 OSD 数、当前 up/down 情况、主要跑 RBD 还是 CephFS。
下面按"机制---路径---参数---典型现象---调优要点"的顺序,把 Ceph 的心跳(liveness)机制讲清楚,重点覆盖你关心的两条链路:
- OSD ↔ OSD(数据面故障检测的主力)
- OSD ↔ MON(控制面汇总判定与发布 OSDMap)
并结合你前面贴过的参数(我会直接引用你配置里出现的那些项)。
0. 先把概念摆正:Ceph 里"谁在判定谁死了"
-
OSD ↔ OSD 心跳 :用于 OSD 彼此判断对端是否可达(快速、分布式、贴近数据路径)。
-
MON 的 down 判定:MON 最终对外宣布"OSD 是 up 还是 down",依据来自:
- OSD 的 心跳/报告(beacon、osdmap report)
- 其他 OSD 对某 OSD 的 down 报告(failure report)
- 自身维护的超时逻辑
一句话:
OSD 之间先"发现",MON 再"裁决并广播"(通过 OSDMap)。
1) OSD ↔ OSD 的心跳机制(核心)
1.1 心跳做什么
每个 OSD 会对同一 PG/邻近 CRUSH 关系中的一些 OSD 建立心跳会话,周期性发送"我还活着"的探测包。探测成功则维持对端为"可达";探测超时则触发"怀疑 down",进一步向 MON 报告。
1.2 心跳走哪条网络
Ceph 通常会在 front/public 和 back/cluster 两张网卡(或同一张网)上进行通讯;心跳消息属于 messenger 层消息,走 OSD 的网络通道(和数据复制同体系)。
你配置里:
public_network = 172.16.111.0/24cluster_network = 172.16.111.0/24
意味着:你没有把 public 与 cluster 分离,心跳与复制/客户端 I/O 共享同一网段,拥塞时更容易出现"误判 down"的风险。
1.3 关键参数(你配置里有的)
osd_heartbeat_interval = 6
- 含义:OSD 发送心跳探测的周期(秒)。
- 影响:越小,故障发现更快;但网络与 CPU 开销更大。
osd_heartbeat_grace = 20
- 含义:允许连续心跳失败/收不到响应的最大宽限时间(秒)。超过则认为对端异常,进入 failure 流程。
- 直觉:大致相当于"允许丢多少秒的心跳"。
粗略理解:对端在 20 秒内一直不可达,就会被怀疑 down(实际还叠加消息重试、队列拥塞等因素)。
与之强相关(你配置里也出现了 messenger 线程/节流)
ms_async_op_threads = 16:messenger 处理线程,过小会让心跳消息在队列里排队,造成"假超时"。ms_dispatch_throttle_bytes = 419430400:分发节流,拥塞时会延迟处理消息,同样可能放大心跳延迟。ms_max_backoff = 2:退避上限,影响拥塞/失败时的重试节奏。
典型现象:
- 网络瞬时拥塞、OSD 负载打满、messenger 队列积压 → 心跳消息延迟 → 可能出现短暂 down 抖动。
2) OSD ↔ MON 的"心跳/汇报"机制(控制面)
OSD 与 MON 之间不是简单"互 ping",而是一组更完整的"定期汇报 + 超时判定"机制。它的目标是:让 MON 持续掌握 OSD 的存活与状态变化,并形成一致的 OSDMap。
2.1 OSD 向 MON 的定期动作
(A) Beacon("我还在"的固定节奏)
你配置里:
osd_beacon_report_interval = 6
含义:OSD 以该间隔向 MON 发送 beacon/状态心跳类消息(实现细节会随版本略变,但作用一致:维持 OSD 的存活存在感)。
(B) OSDMap/PG 统计报告(状态同步)
你配置里:
osd_mon_heartbeat_interval = 3osd_mon_report_interval_max = 20osd_pg_stat_report_interval_max = 20
含义(按功能分组理解):
osd_mon_heartbeat_interval:OSD 与 MON 的联络/保活节奏更密(3 秒),用于更快故障感知或会话维护。osd_mon_report_interval_max:OSD 向 MON 上报自身状态(容量、标志、心跳、一些运行统计等)的最大间隔。osd_pg_stat_report_interval_max:PG 统计上报的最大间隔(PG 状态变化、degraded 等)。
2.2 MON 侧如何判定 OSD "可能不正常"
你配置里:
mon_osd_report_timeout = 25
含义:如果 MON 在该时间窗口内 收不到某 OSD 的报告/心跳类信息,会认为该 OSD 状态可疑,结合其他 OSD 的 failure report 来最终判定 down。
再配合:
mon_tick_interval = 2:MON 做超时检查的主循环粒度。
直觉化:
OSD 如果 25 秒都没"跟 MON 打招呼",MON 会开始认为它不对劲(但是否立刻 down,要看 failure 报告/裁决逻辑)。
3) "OSD 判定 OSD down"如何变成"MON 宣布 OSD down"
这一步是很多人真正困惑的地方:为什么我看见某个 OSD 在某些节点上"看起来 down",但 MON 过一会儿才宣布?
3.1 failure report(OSD → MON 报告"我觉得它死了")
当某 OSD 多次探测不到对端,达到 osd_heartbeat_grace 等阈值后,会向 MON 发送 failure report。
MON 不会立刻只听一个人的。
3.2 MON 的"仲裁阈值"(防止误判)
你配置里:
mon_osd_min_down_reporters = 2mon_osd_reporter_subtree_level = rack
含义:
mon_osd_min_down_reporters = 2:至少需要 2 个独立报告者都说"它 down 了",MON 才更倾向接受该结论。mon_osd_reporter_subtree_level = rack:报告者的拓扑层级要求/约束(希望报告来自不同故障域/符合某种 CRUSH 子树逻辑),降低"同机架交换机抖一下导致机架内互相误报"的概率。
结果:
你会看到:OSD 之间先怀疑并上报,MON 收集到足够"可信、多源"的报告后,才更新 OSDMap,把该 OSD 标成
down。
4) down、out 与心跳的联动(你之前问过的那条链路)
心跳只负责"活不活"。当 OSD 被 MON 宣布 down 后,是否进一步变成 out 触发迁移,取决于另一组参数(你配置里也有):
mon_osd_down_out_interval = 2000(约 33 分钟):down 持续多久自动 outmon_osd_auto_mark_in = True:回来后是否自动 in
因此典型时间线是:
- OSD ↔ OSD 心跳失败 → failure report
- MON 收集足够报告 → OSDMap 标记
down - 只要仍然
in:不会立刻迁移 - down 超过
mon_osd_down_out_interval:MON 可能标记out→ 开始 backfill/recovery
5) 最常见的"心跳误判"根因与如何用参数定位
5.1 网络共享导致拥塞(你这类配置更容易踩)
public 与 cluster 同网段时:
- 客户端突发 I/O、恢复流量、scrub、backfill 都在同一网络竞争
- 心跳包延迟上升,可能触发
osd_heartbeat_grace误判
定位建议(不改参数也能先验证)
- 看是否在高吞吐/恢复期出现 down 抖动
- 看 OSD 日志是否有 "heartbeat no reply / slow ops" 同时出现
- 看是否出现大面积同机架/同交换机下的 OSD 同时抖动(对应
reporter_subtree_level的价值)
5.2 OSD 线程/队列被打满(messenger 处理不过来)
ms_async_op_threads太小或 CPU 打满ms_dispatch_throttle_bytes节流导致处理延迟
会造成"消息收到了但处理太晚",效果和丢包类似。
5.3 grace 与 interval 配比不合理
经验上:
interval太大 +grace太小:容易误判interval太小 +grace太大:开销高、故障发现慢
你的配比(6s/20s)属于相对常见的"稳健型"区间,但在网络不隔离+负载峰值大的场景仍可能抖动。
6) 你这套参数在一起如何"读"
把你配置里与心跳最相关的几项合在一起看:
-
OSD↔OSD:
osd_heartbeat_interval=6osd_heartbeat_grace=20
-
OSD→MON:
osd_mon_heartbeat_interval=3osd_beacon_report_interval=6osd_mon_report_interval_max=20
-
MON 判定:
mon_osd_report_timeout=25mon_osd_min_down_reporters=2mon_osd_reporter_subtree_level=rack
-
迁移触发:
mon_osd_down_out_interval=2000
综合含义是:
- OSD 层面较快发现问题(20s 级)
- MON 不会轻易宣布 down(至少 2 个报告者 + 拓扑约束 + 25s 超时)
- 即便 down,也会等较久才 out(33 分钟),减少误判导致的迁移风暴
这是典型"稳定优先"的配置思路。
如果你希望我把这套机制讲得更"落地到排障",你可以贴任意一段(无需全量):
ceph -sceph health detail- 某个 OSD 的日志里与 heartbeat 相关的几行
我可以据此把"是网络拥塞、CPU 排队、还是单盘 I/O 卡死导致心跳超时"这种路径给你一条条对上,并指出应该先看哪些指标、哪些参数不建议轻易动。
这是一个非常关键、而且经常被"半懂"的问题。结论我先给你一句绝对不模糊的话,然后再把机制拆开解释。
一、先给结论(非常重要)
一个 OSD 仅仅变成
down(仍然是in)时,
Ceph 不会进行真正意义上的数据迁移(backfill)。
但要注意两点容易混淆的地方:
- 可能会看到
recovery字样(但它不等于 backfill) - 只有 OSD 被标记为
out,才一定会触发 backfill
下面我们把这几个词严格区分开。
二、为什么 down + in 不会迁移数据(机制层)
1️⃣ CRUSH 没变 → 放置没变
-
in表示:这个 OSD 仍然参与 CRUSH 计算
-
PG 的 目标副本集合(acting set)仍然包含这个 OSD
因此:
- Ceph 没有理由去"换地方放数据"
- 不会产生大规模数据拷贝
三、那为什么有时候会看到 recovery?
这是最容易混淆的点。
先给你一个严格定义表(重点)
| 名词 | 本质含义 | 是否拷贝大量对象 |
|---|---|---|
| recovery | 恢复副本一致性(补缺、追日志) | ❌ 不一定 |
| backfill | 重新放置副本(OSD 变化导致) | ✅ 一定 |
| scrub | 校验一致性 | ❌ |
四、逐个讲清楚 recovery / backfill 到底是什么
4.1 recovery 是什么(很多人误会)
Recovery = "把副本追到一致状态"
常见触发场景:
-
OSD 短暂 down 后 又回来了
-
在 down 期间:
- 其他副本继续接收了写入
-
回来的 OSD:
- 数据是"旧的"
这时 Ceph 会:
- 对比 PG 日志(pg log)
- 把 缺失的对象或对象片段 同步回来
- 目标是:让副本再次一致
👉 这是"修复",不是"迁移"
特征:
- 数据量通常 远小于全量 PG
- 不涉及 CRUSH 重算
- 不改变副本位置
- 发生在 OSD 回来之后(up)
4.2 backfill 是什么(真正的数据迁移)
Backfill = "你不在了,我换地方放"
触发前提(任意一个):
- OSD 被标记为
out - CRUSH map 变化(加/删 OSD、权重变化)
- pool 的 size / CRUSH rule 改变
Ceph 会:
- 重新计算 PG 的目标 OSD 集合
- 把 完整对象 从旧位置复制到新 OSD
- 直到满足副本数
👉 这才是你直觉里理解的"数据迁移"
特征:
- 数据量大
- 网络/磁盘 I/O 明显
- 对前台影响明显
- 持续时间长
五、时间线对比(非常关键)
情况 A:OSD down 10 分钟,又回来了
T0 OSD down + in
T0~T10 PG degraded(不迁移)
T10 OSD up + in
T10~ recovery(追写入期间的差异)
✔ 无 backfill
✔ 只有 recovery
✔ 影响小
情况 B:OSD down 很久 → out
T0 OSD down + in
T0~T33m PG degraded(不迁移)
T33m MON osd out
T33m+ backfill / recovery
✔ 有 backfill
✔ 有 recovery
✔ 影响明显
六、PG 状态字样如何对应(实战非常重要)
你在 ceph -s / ceph pg dump 里看到的状态:
| PG 状态 | 含义 |
|---|---|
degraded |
副本数不足(常见于 down + in) |
undersized |
副本 < min_size |
recovering |
正在做 recovery |
backfilling |
正在做 backfill |
active+clean |
完全正常 |
重点:
recovering≠ 一定在迁移数据
backfilling= 确实在搬数据
七、结合你之前的配置(你这套很"稳")
你有:
ini
mon_osd_down_out_interval = 2000
osd_recovery_max_active = 1
osd_recovery_sleep = 0.4
这意味着:
- down 33 分钟内:不会 backfill
- 回来的话:只做 recovery,而且非常温和
- 真的 out 了:backfill 也会被严格限速
👉 这是典型的:
"宁可短时间 degraded,也不轻易搬数据" 策略
八、一句"工程级"总结(你可以记这个)
Down ≠ 搬数据
Out = 开始搬数据
Recovery = 补差
Backfill = 换地方
如果你愿意,我可以:
- 用一个 3 副本、3 OSD 的具体例子,一步步画出 PG 在 down / up / out 各阶段到底拷了什么数据
- 或直接根据你真实集群的
ceph -s输出,告诉你:现在看到的 recovery 是"安全的",还是已经进入"搬数据阶段"
你可以随便选一个。