多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

Rook-Ceph 数据修复实战

Rook-Ceph 数据修复实战 前言终于等来了国庆长假宅在家折腾自己的 HomeLab、 K8s、 NAS 服务器集群的感觉真爽这次长假真的是折腾了好多东西感兴趣的读者请期待后续的爆更等不及的话也可以直接看我的 repo -east4ming/homelab2的 PR 和 Commits。今天是第一篇。事情是这样的我家 HomeLab 的 Rook-Ceph 集群前阵子趁着国庆给全部节点从 Ubuntu 24.04 升级到 26.04.1。结果其中一台n100-cheshi-0升级出现问题我多次重启均无法恢复一热一急直接断电直接 GG一躺就是好几个小时。好在最后还是修复了。也是一篇文章敬请期待节点重新上线之后我本以为 Ceph 会自己缓过来毕竟盘都还在PG 也没报错。结果一看ceph -s好家伙4 个 OSD 只有 3 个在线OSD 1 躺在 down/out 里装死ceph osd df里它的 SIZE 是 0 B。说实话一开始我脑子里全是「磁盘挂了」「BlueStore 元数据损坏」「要重建 OSD 了」这些最坏的剧本。折腾了半宿才发现磁盘上那 4TB 数据一点事没有是 Rook operator 自己「不认」它了。这篇文章记录从排查到修复的完整链路。重点在排查思路用三方 FSID 比对加源码验证把一个看起来像数据损坏的问题定位成 Secret 里某个字段过期。声明本文非广告、非推广纯属踩坑记录。环境为 4 节点 K3s Rook-Ceph4 OSDhomelab 环境不是生产环境仅为读者提供思路别照抄。背景autoout 是罪魁祸首吗先说清楚 OSD 为什么会被踢出去。Ceph 有个参数mon_osd_down_out_interval默认 600 秒。OSD 失联超过这个时间monitor 就会把它标记为out同时把它的 CRUSH weight 清零这就是所谓的 autoout。节点断电好几个小时OSD 1 早就超时了于是OSD 1 被 autooutCRUSH weight 归零它的数据被迁移到其余 3 个 OSD集群恢复到HEALTH_OK81 个 PG 全部activeclean。单看这一步这是设计行为不是故障。真正的问题在后面节点回来了OSD 1 却没有自愈。判据一Deployment 消失 ≠ Pod CrashLoop我第一个动作是看 Podkubectl-nrook-ceph get deploy|greposd输出里只有rook-ceph-osd-0/2/3根本没有rook-ceph-osd-1这个 Deployment。这个信号很说明问题。Rook 管理 OSD 的姿势是这样的现象含义Deployment 存在Pod CrashLoop / Pendingoperator 认了这块盘问题出在运行时、调度或设备上Deployment 根本不存在operator 在准备阶段就没采纳这块盘Pod 从没被创建过也就是说OSD 1 不是运行时故障是 operator 主动跳过。这个区别直接把我从「磁盘坏了」拉到「operator 为什么不认它」。ceph osd df里 OSD 1 的 SIZE 显示0 B也是同一个逻辑不是盘没了是压根没被纳管。判据二osd-prepare 日志才是决定性证据Rook 纳管 OSD 的流程是rook-ceph-osd-prepare作业先扫盘、判断能不能用然后才由 operator 创建对应的 Deployment。所以真正的答案在 prepare 作业的日志里。kubectl-nrook-ceph logs job/rook-ceph-osd-prepare-n100-cheshi-0关键几行已简化osd_id: 1 type: bluestore ceph_fsid: abb2c4e2-12a3-4b93-8d90-f2eaf2290901 ... skipping osd.1 ... belonging to a different ceph cluster 0 ceph-volume raw osd devices configured on this node看到belonging to a different ceph cluster这句我当时有点懵我哪来的第二个 Ceph 集群不过日志也告诉我磁盘上的元数据是合法且完整的osd_id 1、type bluestore、ceph_fsid abb2c4e2-…。问题不在盘而在 Rook 认为「当前集群的 FSID」和盘上的 FSID 对不上。三方 FSID 比对顺着这条线我把三个来源的 FSID 摆到一起来源命令 / 位置FSID运行中集群真值ceph fsidabb2c4e2-12a3-4b93-8d90-f2eaf2290901OSD 1 磁盘 BlueStore 元数据prepare 日志ceph_fsidabb2c4e2-…一致rook-ceph-monSecret.data.fsidf568f7c3-5603-4108-99ff-3742cf008a83过期三行凑到一起答案就出来了集群真值 磁盘元数据 abb2c4e2-…✅只有rook-ceph-monSecret 里的fsid是旧的f568f7c3-…❌operator 拿着 Secret 里的过期 FSID 去跟磁盘比对自然判定「这不是我的盘」于是跳过采纳。磁盘、数据、PG全都是好的。源码级验证为什么这个字段不会自动纠正这里我多了个心眼万一只是巧合下次会不会又漂于是我翻了 Rook 上游源码pkg/operator/ceph/controller/cluster_info.go搜fsidSecretNameKey只有三处L52常量定义L154读取构造ClusterInfo时用L423写入且仅在 Secret 不存在、创建新集群时才写换句话说fsid没有任务在「发现不一致时自动纠正」。它一旦写歪就会一直歪下去。这也解释了为什么节点恢复后 OSD 1 永远无法自愈这不是等一等就能好的故障。Notes这个结论让我对整个修复方案有了信心。改掉 Secret 里的值就够了磁盘不用动。修复patch 而非 delete修复动作只有一行命令。原则是只改fsid字段保留ceph-secret、ceph-username、mon-secret不动。NEW_FSID$(ceph fsid)kubectl-nrook-ceph patch secret rook-ceph-mon--typemerge\-p{\data\:{\fsid\:\$(echo-n$NEW_FSID|base64-w0)\}}然后让 operator 重新加载ClusterInfokubectl-nrook-ceph rollout restart deploy/rook-ceph-operator注意千万别图省事把rook-ceph-monSecret 删了重建。它挂着DisasterProtectionFinalizer删掉很可能被 operator 当成「新集群 bootstrap」那才是真的灾难。验证从 0 devices 到 1 devices重启 operator 后再看 prepare 日志1 ceph-volume raw osd devices configured on this node从0变成1就是采纳成功的信号。接着kubectl-nrook-ceph get deploy rook-ceph-osd-1# 1/1 Readyceph osd tree# osd.1 up/inceph osddf# crush weight 0.86850OSD 1 自动重新注册CRUSH weight 恢复全程没有手工执行ceph osd in或ceph osd crush reweight。副作用全部 OSD 滚动重启operator 下发新 OSD 配置时触发了我全部 4 个 OSD 的滚动重启。集群短暂进入HEALTH_WARN指标数值osds down1objects degraded11648 / 44646 ≈ 26.090%pgs degraded23看到 26% degraded 那一瞬间心跳快了一下 。不过这属于正常过渡态期间所有 PG 仍满足副本要求没有出现undersized或incomplete。大约 1~2 分钟后集群自己恢复了。闭环HEALTH_OK ≠ 数据无损断电场景下最不能信的就是HEALTH_OK。PG 状态正常只代表「副本数够」不代表「数据没被写坏」。所以我对全部 81 个 PG 跑了一遍 deep-scrubceph pg deep-scrub$(ceph pgls|awkNR1{print $1})ceph health detail结果全部deep-scrub ok0 inconsistent objectsHEALTH_OK。至此才算真正收工。预防措施踩完坑总结几条供各位参考升级前ceph osd set noout升级完再unset noout避免 autoout 触发全量数据迁移给节点升级准备 UPS另外不要手贱强制关机几百块的 UPS 比几 TB 的重平衡便宜多了 另外这次就是断电的教训备份rook-ceph-monSecret出问题时才有基线可比对恢复后必须 deep-scrub别只看到HEALTH_OK就关电脑。总结回头看这次故障的「魔鬼」藏在一个从没被人注意过的字段里。磁盘完好、数据完好、PG 完好坏的是rook-ceph-monSecret 里那个永远不会自动纠正的过期 FSID。而 Rook 上游源码里的「只读不写」决定了它只能靠人工修。Deployment 消失 ≠ Pod CrashLoop这个判据帮我省了至少一晚上的瞎折腾。三方 FSID 比对加源码级验证则是把「玄学」变成「确定」的关键两步。纸上得来终觉浅绝知此事要躬行。OSD 1 其实压根没病只是被错认了户口。搞清楚这一点修复就只是一行kubectl patch- 精简优雅。以上。️ 参考文档Rook 官方文档 - Ceph OSD ManagementCeph 文档 - OSD autoout 与 mon_osd_down_out_intervalCeph 文档 - Deep ScrubbingRook 源码pkg/operator/ceph/controller/cluster_info.gofsidSecretNameKey定义与读写位置
返回列表