可以无停机轮换,但必须严格按「双密钥共存 → 逐节点重启 → 清理旧密钥」三步走,跳过任意一环都会导致节点失联或认证失败;因mongod启动时只读取一次keyFile且不重载,双向认证要求双方至少一个密钥共存,否则握手失败。

可以无停机轮换,但必须严格按「双密钥共存 → 逐节点重启 → 清理旧密钥」三步走,跳过任意一环都会导致节点失联或认证失败。
为什么不能直接替换密钥文件?
mongod 启动时只读取一次 keyFile,运行中不重新加载;且 keyFile 身份验证是双向的——新密钥写入后,若对端还没更新,握手就会失败。错误现象通常是:no valid authentication method found 或 Unable to authenticate using SCRAM-SHA-256(实际是 keyFile 验证失败被掩盖)。
关键点在于:密钥文件支持多密钥并存,只要至少一个密钥在双方都存在,认证就能通过。这是滚动升级的唯一可行基础。
- 密钥文件内容必须是 base64 编码的纯文本,每行一个密钥,不能有空行或注释
- 生成新密钥必须用
openssl rand -base64 756(MongoDB 要求长度 ≥ 756 字节) - 旧密钥和新密钥必须同时存在于所有节点的同一文件中,顺序无关
如何安全重启每个节点?
重启顺序和方式直接影响集群可用性。不能简单 kill -9 或 systemctl restart,否则可能触发选举异常或写入中断。
对副本集成员(包括分片副本集和配置服务器 CSRS):
- 从节点:连上
mongosh,执行use admin→db.shutdownServer(),再手动启动 - 主节点:先
rs.stepDown()让其退位,等新主上任、状态稳定(rs.status().myState === 2),再db.shutdownServer() - mongos 实例:可直接
db.shutdownServer(),它不参与投票,重启不影响数据分片逻辑
注意:db.shutdownServer() 是优雅关闭,会等待当前操作完成;而 kill -2(SIGINT)效果相同,但不如命令可控。
清理旧密钥时最容易踩的坑
第二轮重启前若遗漏任一节点的密钥文件清理,该节点会继续接受旧密钥——看似正常,实则埋下安全隐患;更危险的是,如果某个节点漏掉第二轮重启,它将只认新密钥,而其他节点还在双密钥阶段,导致该节点被踢出集群。
- 务必确认所有节点的 keyFile 内容已**仅剩新密钥一行**(用
wc -l核对) - 检查
mongod.conf中security.keyFile路径是否指向正确文件(常见错误:软链接未更新、路径拼写错误) - 重启后立即验证:
rs.status().members[n].stateStr应全为PRIMARY/SECONDARY,无REMOVED或UNKNOWN
真正容易被忽略的是:密钥轮换后,所有客户端连接池(比如 pymongo 的 maxPoolSize)不会自动感知变更,但 keyFile 不影响客户端直连——它只用于 mongod/mongos 间通信。这点和 TLS 证书轮换完全不同,不必重连应用。

















