必须重启节点才能更新密钥,但可零业务中断:依赖YAML多密钥共存与分层滚动重启;仅MongoDB 4.2+支持YAML格式多密钥,旧版或单密钥无法平滑升级;需严格按config server→shard→mongos顺序滚动重启并验证状态,最后清理旧密钥并再次滚动重启。

不能在不重启任何节点的前提下更新密钥——MongoDB的密钥认证机制要求每个节点加载新密钥时必须重启进程。但可以做到「零业务中断」,关键在于利用YAML格式多密钥共存 + 严格分层滚动重启。
为什么必须用YAML格式密钥文件
MongoDB 4.2+ 才支持在keyFile中写入多个密钥(YAML序列),这是滚动升级的前提。旧版本或单密钥文件无法实现平滑过渡。
错误做法包括:
• 用echo "newkey" > keyfile覆盖——直接丢失旧密钥,节点立即失联
• 手动拼接两个base64字符串但没加换行和YAML语法——mongod启动报错:key file does not have permissions restricted或解析失败
• 密钥间用空格而非换行分隔——YAML解析器忽略空格,只认第一个密钥
如何生成合法的多密钥YAML密钥文件
每个密钥必须是6–1024字节、base64安全、无换行符的字符串,多个密钥用YAML列表格式组织:
- YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoK<br>- c29tZW5ld2tleXN0cmluZw==
生成时注意:
• 用openssl rand -base64 756生成单密钥(长度合规)
• 多密钥拼接后必须用chmod 600且属主为mongod:mongod
• 不同节点的密钥文件内容必须**逐字节一致**(含缩进、换行、空格),否则出现部分节点连通、部分UNREACHABLE
滚动重启必须严格按角色顺序执行
顺序错乱会导致配置元数据分裂或路由表错乱:
• 先改config server副本集(CSRS):secondary → secondary → 原primary(先rs.stepDown()再关机)
• 再逐个处理每个shard副本集:**禁止跨shard并行**,任一shard未完成前不得动下一个
• 最后轮换所有mongos:每次只停一个,确保至少2个在线,避免客户端连接全断
每步重启后必须验证:
• sh.status()无ERROR,无“waiting for config server”卡顿
• rs.status().members[n].stateStr全为PRIMARY或SECONDARY
• rs.status().members[n].lastHeartbeat时间戳持续更新(非null或陈旧值)
第二阶段清理旧密钥不能跳过验证
所有节点都已接受新密钥 ≠ 可以立刻删旧密钥。必须确认:
• 所有mongos日志中不再出现auth: keyfile authentication failed(旧密钥尝试失败记录)
• 连续30分钟内sh.status()和rs.status()稳定无抖动
• 然后再统一将密钥文件改为仅含新密钥的单条YAML项,并对所有节点**再次滚动重启**——这步容易被跳过,但不执行会导致后续密钥轮换无法复用同一套流程











