运维,数据库··约 8 分钟读完

MongoDB 副本集搭建遇到的 10 个坑及解决方法

MongoDB副本集搭建避坑指南 本文总结了Docker+物理机混合部署MongoDB副本集时常见的10个问题及解决方案。核心问题集中在: Keyfile配置:权限需设为400且属主为mongodb用户(UID 999),主从库必须使用相同文件(占问题70%) 网络与端口:容器初始化需用内部端口(27017),避免--network host与-p参数冲突 数据残留:从库若曾独立初始化需清除/data目录重建 版本一致性:主从版本差异可能导致同步异常,建议主库版本≤从库 认证流程:应先关闭--auth创建首
数据库mongodb

MongoDB 副本集搭建遇到的 10 个坑及解决方法

本文记录了在 Docker + 物理机混合部署 MongoDB 副本集过程中踩过的所有坑,附完整解决方案。


坑 1:rs.initiate() 初始化失败

报错

No host described in new configuration 1 for replica set rs0 maps to this node

原因:Docker 容器内 docker exec 执行时,MongoDB 监听的是容器内部端口(默认 27017),但 host 字段填了宿主机映射端口(如 8017)。

解决

# ❌ 错误(写了宿主机端口) docker exec mongo_node1 mongo --eval 'rs.initiate({members:[{_id:0, host:"127.0.0.1:8017"}]})' # ✅ 正确(写容器内部端口) docker exec mongo_node1 mongo --eval 'rs.initiate({members:[{_id:0, host:"127.0.0.1:27017"}]})'

坑 2:添加从库时 Authentication failed

报错

39.105.184.238:8017 failed with Authentication failed

原因:主库用了 --keyFile 启动(节点间认证),但从库没配 keyfile。

解决:主从必须使用相同的 keyfile,从库启动时加 --keyFile 参数:

docker run -d --name mongo_node1 \ -v /data/mongodb.key:/data/mongodb.key:ro \ mongo:3.6.23 \ mongod --replSet rs0 --keyFile /data/mongodb.key

坑 3:Keyfile 文件路径错误

报错

Error reading file /data/mongodb.key: No such file or directory

原因-v 挂载时宿主机路径指向了不存在的文件。

解决

# 确认宿主机文件存在 ls -la /data/mongodb.key # 确认挂载参数正确 -v /data/mongodb.key:/data/mongodb.key:ro # ↑ 宿主机路径 ↑ 容器内路径

坑 4:Keyfile Permission denied

报错

error opening file: /data/mongodb.key: Permission denied

原因:keyfile 权限是 400,但属主是 root。容器内 MongoDB 使用 mongodb 用户(uid 999),读不了 root 的文件。

解决

chown 999:999 /data/mongodb.key

坑 5:Keyfile permissions are too open

报错

permissions on /data/mongodb.key are too open

原因:MongoDB 要求 keyfile 权限 ≤ 400。

解决

chmod 400 /data/mongodb.key

坑 6:Received heartbeat from member with the same member ID

报错

Received heartbeat from member with the same member ID as ourself: 0

原因:从库之前执行过 rs.initiate(),导致 _id: 0 和主库冲突。MongoDB 的 local.system.replset 中残留了旧配置。

解决:彻底清除从库数据:

docker stop mongo_node1 && docker rm mongo_node1 rm -rf /data/mongo/sec/* # 重新启动容器后,在主库重新 rs.add()

坑 7:--network host 和 -p 冲突

报错:无报错,但端口映射不生效。

原因

# ❌ 这两个参数互斥 docker run --network host -p 8017:27017 ...

二选一

# 方案 A:host 网络(端口自动暴露) docker run --network host ... # 方案 B:bridge 网络 + 端口映射 docker run -p 8017:27017 ...

坑 8:主从 MongoDB 版本不一致

现象

WARNING: shell and server versions do not match MongoDB server version: 2.6.10

原因:主库是 2.6,从库是 3.6,差三个大版本。

风险

  • oplog 格式可能不兼容
  • 同步可能出现意外行为
  • 部分命令行为不同

建议:尽量统一版本,主库版本 ≤ 从库版本。


坑 9:--auth 模式下无法创建第一个用户

报错

Error: couldn't add user: there are no users authenticated

原因--auth 开启后需要先有用户才能操作,但还没创建第一个用户,死循环了。

解决:暂时关掉 --auth 创建用户后再开启:

# 1. 不带 --auth 启动 mongod -f mongod.conf # 先注释 security.authorization # 2. 创建用户 mongo admin --eval 'db.createUser({user:"admin", pwd:"123456", roles:[{role:"root", db:"admin"}]})' # 3. 开启 --auth 重启 mongod -f mongod.conf # 恢复 security.authorization

坑 10:rs.add() 长时间卡住 / 超时

现象:执行 rs.add() 后没有返回,或 SSH 超时。

排查步骤

# 1. 检查网络 ping 从库IP telnet 从库IP 8017 # 2. 检查从库日志 docker logs mongo_node1 --tail 20 # 3. 检查从库能否连上主库 docker exec mongo_node1 mongo 主库IP:8017 --eval 'rs.status()' # 4. 确认 keyfile 一致 md5sum /data/mongodb.key # 对比主从两边是否一样

总结

10 个坑中,70% 是 keyfile 相关(路径、权限、内容不一致),20% 是端口和网络配置10% 是数据残留

如果从头搭建一次,建议按这个顺序:

  1. 主库启动并初始化(不开 auth)
  2. 配好 keyfile(chmod 400 + chown 999:999)
  3. 从库启动并加入副本集
  4. 验证同步状态
  5. 创建用户并开启 auth
  6. 应用连接测试