csrs主节点未恢复选举导致元数据只读,需检查rs.status()确认primary状态、electionid及成员健康,清理失效节点配置,启用均衡器,并刷新mongos路由缓存。

配置服务器副本集(CSRS)主节点未恢复选举
网络中断后,CSRS 可能因多数节点失联而丢失 PRIMARY,进入只读状态。此时即使网络恢复,只要没有成功重新选举出主节点,所有分片节点就无法写入元数据——包括 chunk 拆分、迁移、新增分片等操作都会被拒绝。
检查方式:连任一配置服务器 Pod,执行 mongo --eval "rs.status()",重点看:
- members[n].stateStr 是否有值为 PRIMARY 的成员
- ok: 1 且 electionId 非空
- 所有成员 health: 1 且 stateStr 不是 STARTUP 或 RECOVERING
常见卡点:
- 剩余存活节点数
- 存活节点间时钟偏差 > 30 秒,导致 rs.stepDown() 失败或心跳超时
- 某节点 lastHeartbeatMessage 显示 Connection refused,说明它仍试图连已下线节点,需手动清理 rs.reconfig()
CSRS 元数据被标记为“只读”但未自动解除
MongoDB 在检测到 CSRS 不可用期间,会将集群元数据设为只读;但网络恢复后,这个状态不会自动回滚——它依赖主节点主动更新 config.settings 中的 balancer 和 clusterId 等字段。若主节点没真正“活”过来,这个只读锁就一直挂着。
验证方法:
- 连上当前 PRIMARY 的配置服务器,运行:mongo --eval "db.settings.findOne({ _id: 'balancer' })"
若返回中 stopped: true 或缺失 mode 字段,说明均衡器已被人工停用或未初始化
修复动作:
- 确认主节点已稳定运行至少 30 秒以上
- 手动启用均衡器:sh.startBalancer()(需通过 mongos 执行)
- 若失败,检查 mongos 日志是否报 not authorized on config to execute command —— 很可能是 mongos 使用的用户缺少 clusterAdmin 角色
分片节点仍连着旧的 CSRS 成员地址
网络恢复后,部分分片节点可能还缓存着故障前的 CSRS 成员列表(尤其当使用 DNS 名称而非 IP 直连时),而该列表里包含已下线或 IP 变更的节点。mongod 启动时会尝试连接全部成员,只要其中一个不可达,就可能卡在 STARTUP2 状态,不参与路由同步,间接导致整个集群行为异常。
排查路径:
- 查 kubectl logs <shard-pod-name></shard-pod-name>,搜 Failed to connect to config server 或 could not find host in config server replica set
- 检查该 Pod 启动参数中的 --configdb 值是否仍指向已失效的 Service 名称(如 config-svc:27019),而 Kubernetes 中该 Service 的 endpoints 已为空
关键细节:
- 不要直接改 Pod 的启动参数,应更新对应 StatefulSet 的 initContainer 或 ConfigMap 中的 CONFIGDB 字段
- 若用 TLS,确认 --sslCAFile 指向的证书文件在容器内存在,且 ls -l 显示属主为 mongod 用户(非 root)
- 重启分片 Pod 前,先确保 CSRS 的 rs.status() 输出中所有成员 stateStr 是 SECONDARY 或 PRIMARY,否则新节点一启动就又卡住
mongos 实例未刷新配置缓存
mongos 不持久化状态,但它会缓存从配置服务器拉取的路由表(config.chunks)。网络中断期间,它可能一直用着过期的 chunk 分布信息;即使 CSRS 恢复了,mongos 也不会自动重载——除非触发一次显式刷新或重启。
现象:
- 应用写入报 NotMasterNoSlaveOk 或 ShardKeyNotFound
- sh.status() 显示 chunk 数量与实际不符,或某分片显示 draining: true 但无迁移任务
解决办法:
- 对每个 mongos Pod 执行 mongo --eval "db.runCommand({ flushRouterConfig: 1 })"
- 或滚动重启 mongos StatefulSet(更彻底)
- 注意:如果 mongos 使用的用户没有 clusterManager 角色,命令会返回 not authorized,需先补权限
最常被忽略的一点:CSRS 恢复后,必须等所有分片节点都完成一次完整的元数据同步(日志里出现 Received new config version),再让应用流量进来。中间哪怕只有 1 个分片卡在 RECOVERING,某些跨分片事务就可能失败。











