不能靠 db.rotatecertificates() 单独完成无停机轮换,它仅重载证书文件,不生成分发证书、不重建客户端连接池,且要求证书文件原子替换、权限严格为600、路径完全匹配,滚动顺序须 secondary→primary→secondary,并强制客户端重建连接池。

不能靠 db.rotateCertificates() 单独完成无停机轮换。它只 reload 文件,不生成、不分发、不解决客户端连接复用问题——直接调用必然导致部分连接中断或认证失败。
证书文件必须原子替换,且权限严格匹配
mongod 进程对 certificateKeyFile、clusterFile、CAFile 等路径下的文件有强校验:文件存在、可读、权限为 600(UNIX)、内容格式合法。任何一项不满足,db.rotateCertificates() 会静默失败或报错 Failed to load TLS certificate。
- 推荐用
mv new.pem old.pem && mv tmp.pem new.pem方式原子覆盖,避免中间态文件缺失 - 替换后必须
chown mongod:mongod+chmod 600,尤其注意容器内 UID 可能不是 0 - 若用 Vault Agent 渲染,
destination路径需与 mongod 配置中路径完全一致(含大小写、末尾斜杠)
滚动顺序必须是 secondary → primary → secondary
副本集节点身份和心跳依赖 TLS 握手;主节点轮换过早,会导致从节点无法建立加密心跳连接,触发 replSetHeartbeat failed 和选举震荡。
- 先对所有 secondary 执行文件替换 +
db.rotateCertificates() - 再对 primary 执行:先
rs.stepDown(),等新 primary 选出并稳定,再在其上操作 - 原 primary 降级为 secondary 后,最后对其轮换
- 每步之间建议 wait 30s,确认
rs.status().members[n].stateStr === "SECONDARY"或"PRIMARY"
客户端连接池重建不可跳过
即使服务端证书已更新、mongod 已 reload,pymongo/node-mongodb-native 等驱动仍会复用旧 TLS 会话(session resumption),导致后续请求握手失败,错误常为 ssl.SSLError: [SSL: TLSV1_ALERT_UNKNOWN_CA] 或 connection closed by peer。
- 必须在服务端轮换完成后,主动触发客户端重建连接池:pymongo 中调用
client.close()后新建 client;Node.js 中销毁旧MongoClient实例 - 无状态服务(如 API 网关)可滚动重启;有状态服务(如长连接 WebSocket 后端)需实现连接优雅关闭逻辑
- Kubernetes 下建议配合 readiness probe 检查
db.runCommand({ping:1})成功后再开放流量
extensionValue 和 SAN 必须与配置严格一致
当启用 net.tls.clusterAuthX509.extensionValue 时,mongod 会校验证书中指定 OID 扩展值是否完全匹配——哪怕多一个空格或换行,都会拒绝连接,日志显示 Invalid cluster certificate extension。
- OpenSSL 生成时必须显式加
-addext "subjectAltName = DNS:rs0.example.com,IP:10.0.1.5",否则 TLS 握手失败 - 若使用 Vault PKI,签发时需设
ext_key_usage = ["server auth", "client auth"]和use_csr_sans = true -
extensionValue值区分大小写,且必须与clusterFile中证书的subjectKeyIdentifier或自定义 OID 扩展值一字不差
最易被忽略的是客户端连接池重建——它不在 mongod 控制范围内,却直接决定轮换是否真正“无停机”。只要还有长连接复用旧会话,服务就处于半失效状态,监控可能不报警,但部分请求已开始失败。











