ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Ceph MON命令实战:从状态查看到仲裁恢复的运维指南

Ceph MON命令实战:从状态查看到仲裁恢复的运维指南 去年冬天处理过一次 MON 节点全挂的事故从无从下手到一步步把集群拉回来让我意识到一个问题很多 Ceph 相关文档都在讲存储池、RBD、CRUSH但专门把 MON 命令系统梳理一遍的几乎没有。而 MON 恰恰是集群的命门仲裁一丢整个分布式存储就变成了只读的摆设。这篇东西不是手册的翻译是我自己在这套命令上实际摸爬滚打后的总结覆盖状态查看、节点管理、认证修复、monmap 重建等高频场景适合刚接手 Ceph 集群的运维也适合被 MON 故障折腾过、想系统补课的人。1. 先摸清家底用 ceph mon dump 读懂集群地图与 MON 演进接手一个陌生集群第一步不是急着敲各种命令而是先搞清楚 MON 的底细。ceph mon dump是我每次排查问题第一个执行的操作没有之一。这条命令输出的实际上是 MON 的持久化状态也就是 monmap它记录了集群里所有 MON 节点、它们的地址、以及这个 map 的版本号。ceph mon dump输出内容看起来不多但信息密度很高逐段拆开讲。最上面一般是epoch、fsid、last_changed、min_mon_release之类的元信息。epoch表示当前 monmap 的版本号每次增删 MON、修改地址epoch 就会加一。排查问题时要习惯性地记下这个数字后面用ceph mon dump对比新旧版本时epoch 就是最直接的参照物。fsid是集群的唯一标识备份和恢复 monmap 时需要精确匹配。如果 fsid 对不上别想把 dump 文件恢复到另一个集群。min_mon_release是当前 MON map 支持的最低版本比如quincy或reef混合版本集群中要特别注意这个字段老版本 MON 和新版本共存时可能触发协议不兼容。中间部分是一系列 MON 节点的定义每条记录大致长这样0: [v2:10.0.0.11:3300/0,v1:10.0.0.11:6789/0] mon.node10是 MON 在该 map 中的编号v2地址是 Ceph 较新版本默认监听的协议端口3300v1地址是传统协议端口6789。老版本只会有v1如果在扩容时混用 v1 和 v2会看到一条 MON 同时输出两种协议栈。这里有个坑我后面会专门讲。还要留意输出末尾的dump汇总它会告诉你dumped monmap to /tmp/monmap之类的路径——这是ceph mon dump附带的行为它会自动把 monmap 以二进制形式导出到本地文件。这个文件非常重要monmaptool修改、恢复操作都依赖它建议养成每次 dump 后顺手复制一份留档的习惯。ceph mon dump /tmp/monmap_dump_$(date %F).txt这条命令虽然叫 dump但它导出的是纯文本。如果想导出二进制 monmap 文件用ceph mon getmapceph mon getmap -o /tmp/monmap.binceph mon dump更偏向于“看”ceph mon getmap则偏向于“拿”——拿到文件后可以做校验、恢复、离线重建。两条命令配合使用MON 维度的问题基本都能摸到底。2. 状态透视ceph quorum_status 到仲裁信息的深入解读ceph quorum_status这条命令很多人用过但未必读懂了输出。它告诉你当前集群 MON 仲裁是否健康以及谁在仲裁里、谁不在。ceph quorum_status输出是 JSON 格式关键字段包括quorum、monmap、quorum_leader_name。quorum是一个数组里面是当前参与仲裁的 MON 编号。比如quorum: [0, 1, 2]表示三节点 MON 都健康如果出现quorum: [0, 1]而 MON 总数是 3说明第三个 MON 掉线或者网络隔离了。这里有一个经常被误解的点ceph -s里的mon: 3 daemons, quorum 0,1,2才是仲裁状态的简化视图而ceph quorum_status是详细 JSON。两者不是替代关系而是同一个状态的不同展示粒度。排查问题时我习惯先看ceph -s快速确认仲裁再看quorum_status拿细节。关于仲裁还有一个容易忽略的理论基础MON 使用的是 Paxos 协议的简化版这决定了必须超过半数 MON 在线才能形成仲裁。3 节点 MON 允许挂 1 个5 节点允许挂 2 个如果是 2 节点 MON 这种非标准部署挂 1 个就等于仲裁丢了。所以部署规划时就该明白2 节点 MON 不是高可用是自欺欺人。ceph quorum_status里quorum_leader_name字段标识当前谁是仲裁中的 leader。集群写入元数据时leader 负责协调各 MON 的 Paxos 提案。如果 leader 频繁变化往往不是好事——可能是网络抖动导致选举震荡这种时候要去查 MON 节点之间的网络质量而不是急着重启服务。实际使用中ceph quorum_status常被写进监控脚本判断仲裁状态。一个简单的健康检查建议配合ceph mon stat它输出更紧凑ceph mon statceph mon stat会直接给出类似e3: 3 mons at {0...}的信息e3就是当前 epoch。如果脚本里同时跑ceph quorum_status和ceph mon stat一个拿详细状态一个拿快速摘要排查效率会高很多。还有一个方向容易被忽略ceph quorum_status也能用于验证故障域配置。比如你把 MON 分布在 3 个不同机架某次机架断电后quorum_status里缺失的节点编号会告诉你哪个机架的 MON 挂了。这比直接 ping IP 更准确因为即便进程活着Paxos 通信断开也可能导致节点被踢出仲裁。3. 扩容与收缩MON 节点的添加删除操作与注意事项MON 节点会在什么时候需要增删最常见的两种情况是硬件换代迁移以及初期只部署了单 MON 需要扩大冗余。操作本身不复杂但顺序错了容易出大事尤其是删除 MON。3.1 添加一个 MON 节点的完整过程假设新节点的 IP 是10.0.0.14hostname 是node4需要先在这台机器上安装 ceph-mon。如果是容器化或使用 cephadm过程会有差异本文讲的是传统手动部署流程因为它更能体现原理。第一步在新节点上生成 MON 的密钥环ceph auth get-or-create mon.node4 mon allow * -o /etc/ceph/ceph.mon.keyring这条命令会从集群拉取或新建 MON 认证密钥。注意目录权限建议chown ceph:ceph后放到标准位置否则后续服务启动会因读不到密钥而失败。第二步在新节点上初始化 MON 数据目录ceph-mon -i node4 --mkfs --mon-data /var/lib/ceph/mon/ceph-node4这一步的关键是--mon-data路径必须和配置文件里一致。--mkfs会从集群获取当前 monmap 和密钥环生成本地数据。如果网络不通或认证失败这一步就会卡住或报错。第三步把新 MON 加入现有集群ceph mon add node4 10.0.0.14:6789ceph mon add是控制命令它会修改 monmap 并把新 MON 的信息广播出去。执行完后用ceph quorum_status查看新节点应该出现在列表里。但此时新 MON 的数据目录还是“空”的需要启动服务逐步同步systemctl start ceph-monnode4启动后 MON 会从现有仲裁节点获取完整的历史数据。有时候启动完成后ceph -s看到的 MON 数增加了但新节点没有马上参与仲裁这通常是数据同步还没完成稍等片刻即可。3.2 删除一个 MON 的最低伤害操作删除 MON 是高风险操作最怕的是把还在线的节点误删。一个稳妥的顺位是ceph mon remove node2执行该命令前务必确认被删节点的心跳已经停止。如果误删了一个还在运行的 MON该节点会持续尝试加入仲裁并产生状态冲突。最坏情况下它会带着旧的 monmap 版本反复提示仲裁变化影响集群稳定性。删除后还有一步容易遗漏清理该节点的本地数据目录和认证信息。ceph auth del mon.node2 systemctl stop ceph-monnode2 rm -rf /var/lib/ceph/mon/ceph-node2如果不执行ceph auth del这个节点的认证信息会一直留在集群的 auth 数据库中虽然短期不会造成故障但会形成安全面和运维噪音。特别是当集群里 MON、MDS、MGR 角色混在一起时残留的认证可能会导致后续审计混乱。3.3 地址变更时必须遵守的操作顺序MON 的 IP 变了不能直接改配置文件重启那样新旧地址会同时在集群中存在干扰仲裁。正确的做法是ceph mon set-addrs node3 [v2:10.0.0.13:3300,v1:10.0.0.13:6789]先把 monmap 里的地址改掉然后再去节点上改配置文件、重启服务。顺序反了轻则这个 MON 无法加回仲裁重则集群内暂时出现两个同名 MON 的冲突。我在一次迁移中就因为先重启服务再改 map导致该 MON 连续几次被踢出仲裁最后花了十几分钟才稳定。对于大规模版本升级特别注意混合地址问题Ceph 新版本默认启用 v2 协议旧节点只有 v1。新老共存时ceph mon dump会同时显示 v2 和 v1 地址。ceph mon add新节点时如果只写 v1 地址可能会出现新节点无法被部分旧节点访问的诡异问题。最简单的方式是升级完所有节点后统一使用 v2 地址并确保mon_host里包含全部可用地址。4. 容灾恢复单 MON 数据修复与 monmap 重建的完整流程MON 的数据目录损坏、monmap 丢失这些故障听起来吓人但整套恢复逻辑是成体系的。下面这套流程我用过不止一次是真正能落地的方案。4.1 数据目录层面看懂 critical 文件并做预防每个 MON 的数据目录/var/lib/ceph/mon/ceph-name下有一组 key 文件比如store.db、current.epoch等。store.db是 LevelDB 格式的元数据库保存了 MON 自己管理的状态。如果这个库损坏ceph-mon进程可能启动到一半就崩溃。排查方法先看日志。journalctl -u ceph-monnode1 -n 100日志里如果出现Corruption或IO error相关字样基本可以断定 store.db 有问题。这种情况下最有效的手段是从另一个健康 MON 拷贝一份数据或者从备份恢复。写这篇的时候我看到不少同行会定期 cron 一条命令来备份 MON 数据这是很值得推荐的预防性操作ceph-mon -i node1 --inject-monmap /tmp/backup_monmap严格说这条命令适合把已有的 monmap 注入到当前数据目录而不是直接另存。如果想做数据层面的备份通常用快照或 LevelDB 的在线备份工具。更常见的实操是定期把 monmap dump 出来保存因为它体积小、恢复成本低而完整数据目录的备份往往太重。MON 最重要的数据其实是 monmap auth key保护好这两个大部分故障都能兜底。4.2 monmap 重建当集群全部 MON 失联时的手动流程有时整个 MON 层挂了各 MON 数据目录可能已经不一致。这时需要用ceph-mon --extract-monmap从某个 MON 数据目录里把现有的 monmap 抽出来再手工重建、修复。假设所有 MON 都不在线只剩 node1 的数据目录可用ceph-mon -i node1 --extract-monmap /tmp/monmap.bin这个命令会读取 node1 本地数据目录里的 monmap 文件并导出。如果提取失败说明该目录可能已不完整可以尝试其他节点的目录。拿到 bin 文件后用monmaptool查看并重建monmaptool --print /tmp/monmap.bin输出会列出当前 MON 列表及地址。如果发现某个节点地址变了或某个节点需要移除直接改monmaptool --rm node2 /tmp/monmap.bin monmaptool --add node1 10.0.0.11:6789 /tmp/monmap.bin这些都改完后重新注入到各 MON 数据目录ceph-mon -i node1 --inject-monmap /tmp/monmap.bin ceph-mon -i node2 --inject-monmap /tmp/monmap.bin注意注入 monmap 时需要指定--inject-monmap参数它会让 MON 在启动阶段直接使用你提供的 monmap 而不是本地存储的旧版本。原理是在store.db未初始化的状态下monmap 充当了启动的种子。启动验证这一步最容易翻车。先手动启动第一个 MONceph-mon -i node1 --foreground观察输出是否进入election状态。如果没有其他 MON 在线它会一直等仲裁。这时再启动第二个 MON两个节点应该能形成2/3或3/3仲裁。如果启动时同时带入旧的 monmap 和新的地址可能出现different fsid报错——这说明你拿到的 bin 文件不属于当前集群八成是混用了其他集群的备份。关于 fsid 问题和整体恢复有一个常见误区要提醒--inject-monmap修改的是本地数据目录里的 map 文件不等于修改了集群整体的状态。集群只有在新 MON 启动并形成仲裁后才会通过 Paxos 把新 monmap 广播出去。所以注入后尽量第一时间启动所有 MON不要长时间只有一个节点处于已注入状态否则一旦这个节点再崩溃没有其他节点能同步这个新 map恢复工作就得重来。5. 认证体系与 MON 强相关的 auth 命令及故障关联很多运维把ceph auth单纯当作密钥管理工具但认证和 MON 的关系远比表面深。MON 认证出问题轻则客户端连不上重则 MON 本身互相认为对方非法导致仲裁分裂。5.1 认证命令是排查性能故障的方向之一ceph auth list能列出所有实体及权限排查某个客户端为何被拒绝时它是第一步ceph auth list输出中你会看到client.admin、client.rbd、osd.0等。重点看caps部分比如client.rbd caps: [mon] allow r caps: [osd] allow rwx如果某个客户端权限缺失用ceph auth caps修复ceph auth caps client.rbd mon allow r osd allow rwx注意caps修改是整体覆盖不是增量追加。我踩过不少次坑比如想给某个用户加一条mgr权限结果把原来的osd权限覆盖掉导致服务端告警。所以执行前建议先把原有 caps 复制留存再构造新命令。5.2 get-or-create 与 get-or-create-key 的正确姿势在创建客户端用户时两条命令经常被混用ceph auth get-or-create client.rbd mon allow r osd allow rwx -o /etc/ceph/ceph.client.rbd.keyring这条命令如果用户已存在它会直接返回现有密钥如果不存在则创建。-o参数把 keyring 写进文件避免在终端显示密钥。另一条ceph auth get-or-create-key只输出密钥本身适合在脚本里直接赋值变量但不建议在生产环境把密钥打印到日志中。两者本质是同一个功能的不同输出形态。5.3 认证失败导致 MON 反复脱离仲裁的修复遇到过这样一个故障集群有 3 个 MON其中一个节点 OSD 正常但ceph -s里它的 ID 不在 quorum 里。日志报auth: unable to verify...或monmap mismatch。这类问题多半不是 MON 之间网络不通而是它们持有不同的ceph.mon.keyring或认证状态不一致。修复方案是重新同步所有 MON 的 keyringceph auth get mon.node2 -o /tmp/ceph.mon.keyring scp /tmp/ceph.mon.keyring node2:/etc/ceph/ceph.mon.keyring systemctl restart ceph-monnode2注意ceph auth get需要在仲裁健康时执行否则它读不到正确的数据库。如果集群已经因为 MON 认证问题处于震荡状态先尝试只修复一个 MON 并让它加入仲裁再逐个修复其他节点避免一把抓。还有一种情况是client.admin的 keyring 过期或丢失了此时即使 MON 正常也无法用ceph命令连接。修复方法是先用一台还有本地 keyring 的节点直接指定 MON 地址和密钥进入ceph -n client.admin --keyring /etc/ceph/ceph.client.admin.keyring -m 10.0.0.11:6789 status这条命令能绕过默认配置的可达性问题让它直连某个 MON。如果仍然失败考虑用ceph-authtool重建一个 admin keyring 再配合caps授权。这是最后手段务必确保操作者权限足够否则可能把整个集群的认证账本弄乱。6. 隐藏命令与监控技巧注入参数、日志级别调整与 MON 心跳定位MON 相关命令不只有ceph mon那一簇很多隐藏能力潜藏在ceph tell和日志参数中。生产环境遇到 MON 相关问题这些命令往往比常规命令更高效。6.1 ceph tell mon 注入运行参数遇到 MON 行为异常比如 OSD 上报超时导致误判可以通过ceph tell在运行状态下临时调整参数ceph tell mon.* injectargs --mon_osd_report_timeout 600mon_osd_report_timeout控制 MON 等待 OSD 上报的时限。默认值较低时网络稍有波动就可能把健康 OSD 标记为 down进而触发数据重均衡。如果只是临时的网络抖动先用这条命令拉长超时比直接修改整个集群的配置文件要安全。还可以用它动态调整 MON 日志级别故障定位时很有用ceph tell mon.* injectargs --debug_mon 20 --debug_paxos 20 --debug_auth 20日志级别从 0 到 20默认通常只有 0-5。临时调高后MON 日志会输出大量 Paxos、认证相关细节。定位完毕记得调回来否则日志量会暴涨对磁盘造成压力。ceph tell mon.* injectargs --debug_mon 0 --debug_paxos 0 --debug_auth 0注意injectargs的修改不写配置文件服务重启后失效。如果需要长期生效还是要到ceph.conf里持久化设置。6.2 通过 mon_status 快速判断心跳和网络隔离ceph tell mon.0 mon_status或直接在 MON 节点查看ceph daemon mon.node1 mon_statusceph daemon命令是针对具体守护进程的接口mon_status会输出包括rank、state、election_epoch在内的详细信息。state字段可能显示leader、peon、probing等状态。probing说明当前 MON 还在尝试联系其他节点如果长时间停留在probing大概率是该节点与其他 MON 的网络隔离或地址配置错误。这个命令在排查 MON 到达不了仲裁时非常有用。它比ceph quorum_status更底层因为它读的是单个守护进程的本地状态而不是通过控制命令汇总。你会发现有时候ceph quorum_status返回的仲裁是全局视图而某个 MON 本地认为自己是probing两者不一致时就该怀疑该节点的本地视图已经不健康了。6.3 日志文件路径变化与排查线索MON 日志在哪因部署方式不同差别很大。传统手动部署日志通常在/var/log/ceph/ceph-mon.node1.log如果使用 systemdjournal 是另一个来源journalctl -u ceph-monnode1实际排查时我习惯先看 journal因为 systemd 会捕获标准输出和错误日志时序更完整。文件日志则适合长期归档分析。无论看哪个建议把debug_mon、debug_paxos调高后再复现问题。Paxos 相关的告警往往是 MON 间选举不稳的信号比如lease timeout、not enough paxos members之类看到后第一反应不是重启而是检查网络丢包和时钟同步。时钟同步对 MON 来说真的很重要。MON 的 Paxos 协议严重依赖时间戳NTP 服务一旦失效即使网络畅通各节点感知的“当前时间”不同会导致租约不连续、选举频繁重置。处理这种问题查看时间源比操作 Ceph 命令更快chronyc tracking如果发现System time偏差持续几十毫秒到几百毫秒先处理时钟同步再观察 MON 仲裁是否自然恢复。这条经验救过我很多次比盲目调参有效得多。在实际项目中我对 MON 命令的使用心得是所有命令都要有对应“副作用”的意识。ceph mon dump会落盘一份二进制 monmapceph mon add会改 monmap 并触发广播ceph auth caps会整体覆盖权限。理解了这些副作用你就不会在操作后一脸懵地看到集群状态发生跳变。MON 命令本身并不复杂复杂的是命令背后那套选举、认证和 map 同步机制。多花一点时间去验证每次命令的后续影响你对集群的掌控力会有质的变化。
返回列表