keyfile是共享密钥认证,轻量但风险高;x.509基于证书链,支持细粒度角色绑定和最小权限,是生产唯一推荐方式,二者不可混用。

分片集群中 keyFile 和 x.509 认证的区别在哪?
成员间通信认证不是选“开启”或“关闭”的问题,而是选“用什么机制”。keyFile 是共享密钥方式,轻量但密钥泄露即全集群沦陷;x.509 基于证书链,支持细粒度角色绑定(比如只允许某证书作为 shard 成员,不能当 config server),更符合生产环境最小权限原则。
实际部署中容易踩的坑:keyFile 必须严格 600 权限且所有节点内容完全一致,稍有空格或换行就会报 Failed to load key file: Invalid key file format;而 x.509 要求所有节点系统时间误差 ≤ 30 秒,否则 TLS 握手直接失败,错误日志里只显示模糊的 SSL handshake failed,不提示时间偏移。
-
keyFile适合快速验证或封闭内网测试环境 -
x.509是生产唯一推荐方式,尤其当 config server、mongos、shard 部署在不同安全域时 - 别混用:一个集群不能部分节点用
keyFile、部分用证书
如何让 mongos 和 mongod 同时启用 TLS 并验证对方身份?
光配 --sslMode requireSSL 不够,必须明确指定双向验证开关。关键参数是 --sslAllowInvalidCertificates 和 --sslAllowInvalidHostnames——这两个必须设为 false,否则等于没开验证。
典型配置片段(以 shard 节点为例):
--sslMode requireSSL \ --sslPEMKeyFile /etc/mongo/tls/shard1.pem \ --sslCAFile /etc/mongo/tls/ca.crt \ --sslClusterFile /etc/mongo/tls/shard1.pem \ --sslClusterPassword '' \ --sslAllowInvalidCertificates false \ --sslAllowInvalidHostnames false
注意:--sslClusterFile 必须和 --sslPEMKeyFile 指向同一证书文件,且该证书的 subjectAltName 必须包含当前节点所有可访问的 DNS 名或 IP(例如 DNS:shard1.prod,IP:10.10.20.5),否则 mongos 连接时会报 unable to verify the first certificate。
开启成员授权后,为什么 rs.status() 返回 stateStr: "STARTUP2" 卡住?
这是最常被忽略的启动顺序问题:分片集群的 config server、shard、mongos 必须全部配置好 TLS 和 keyfile/x.509 后,再统一启动。如果先启了一个没配证书的 shard,它会尝试用明文连接 config server,而 config server 已启用 TLS,拒绝连接,导致该 shard 一直卡在 STARTUP2 等待初始化响应。
排查方法很简单:
- 查 config server 日志,搜索
connection refused或SSL handshake failed - 在未启动的 shard 上手动执行:
openssl s_client -connect config01:27019 -CAfile ca.crt,看是否能完成握手 - 确认所有节点的
replSet名称完全一致(大小写敏感),且 config server 的replSet名必须是configReplSet(硬编码,不能改)
用户权限和内部成员授权是两套独立体系,别指望开了 TLS 就自动有读写权
TLS 和 keyFile 只管“你是谁”,不管“你能干啥”。即使所有节点通信加密了,新连接上来的 mongos 或应用仍默认无任何数据库权限。必须显式创建用户并赋予角色:
db.createUser({
user: "appUser",
pwd: "strongPass123",
roles: [
{ role: "readWrite", db: "myapp" },
{ role: "clusterMonitor", db: "admin" }
]
})
特别注意:sh.addShard() 命令本身需要 clusterAdmin 角色,这个角色只能在 admin 库下创建;而普通业务用户必须在对应业务库中创建,跨库授权不会生效。
最容易被忽略的是:开启 authorization: enabled 后,localhost exception 失效——你不能再靠本地直连去救急建用户,必须提前在配置文件里写好 security.authorization: enabled 并配好初始管理员用户。











