ansible部署mongodb分片集群时,hosts变量必须严格按角色隔离:同一ip若承担shard1、config_server、mongos多个角色,须配置唯一端口(如27001/27019/27017)和独立based_dir(/data/shard1、/data/configs、/data/mongos),仲裁节点需在mongod.conf中显式设arbiteronly: true,否则复制集初始化静默失败。

Ansible部署分片集群时,hosts变量怎么组织才不翻车
Ansible不是靠“写对playbook”就能跑通分片集群的,关键在hosts文件里角色和端口的映射逻辑是否闭环。常见错误是把shard1、config_server、mongos混在同一台机器上却没隔离端口或数据目录,导致启动冲突或配置覆盖。
必须明确三点:
-
shardX_port、config_port、mongos_port要全局唯一,比如shard1_port=27001、config_port=27019、mongos_port=27017 - 同一IP上若同时承担多个角色(如某节点既是
shard1主又是config_server),必须用不同based_dir子路径区分数据:/data/shard1、/data/configs、/data/mongos - 仲裁节点(
arbiter)不能参与数据读写,但ansible模板里仍需为其生成mongod.conf,且replSet配置中必须显式标注arbiterOnly: true
漏掉任意一条,service mongod start会静默失败,日志里只报Failed to start mongod.service,实际卡在复制集初始化阶段。
Kubernetes Operator扩容分片,为什么改spec.members没反应
Operator对topology: sharding和topology: replicaset的处理逻辑完全不同:spec.members只在后者生效;前者扩容必须操作spec.shards数组。
直接编辑CR把replicas: 3改成4完全无效——Operator压根不解析这个字段。它只认spec.shards长度,每个数组元素代表一个独立副本集。
正确做法是:
- 向
spec.shards追加新对象,例如新增- name: shard4 members: 3 - 确保新shard的
storageClassName、resources、nodeAffinity与现有shard一致,否则Pod卡在Pending - Operator拉起Pod后,会调用
sh.addShard("shard4/..."),但这一步依赖Ops Manager集成;纯Operator(无OM/CM)不会自动注册分片,得手动连mongos执行
不检查Operator日志里的Adding shard或sh.addShard failed提示,很容易以为扩容成功,其实数据根本没路由过去。
缩容分片前,Operator不会帮你做sh.removeShard()
Operator从不主动触发sh.removeShard(),这是人为强干预操作。直接删掉CR里的shard条目,Operator会立刻重建它——因为它发现“声明状态”和“实际集群状态”不一致,试图修复。
缩容必须按顺序人工完成:
- 先用
mongos连接,运行sh.stopBalancer()停掉均衡器 - 反复执行
sh.status(),确认目标shard的chunks字段为0(说明所有chunk已迁出) - 手动执行
sh.removeShard("shardX"),等返回"msg" : "removeshard completed successfully" - 最后才删除CR中对应shard,再
kubectl apply
跳过chunk迁移检查就删CR,Operator会不断重试拉起已注销的shard,Pod反复创建又崩溃,日志刷屏failed to join replica set。
备份与监控脚本嵌入Ansible时,权限和路径容易被忽略
Ansible默认以root执行,但mongodump若连带认证参数(如--username)一起写进shell模块,密码明文暴露在ps aux里;而crontab任务若用普通用户运行,又常因/home/mongodb/.bashrc未加载导致mongodump命令找不到。
稳妥方案是:
- 用
copy模块下发.mongorc.js或client.pem到/etc/mongod/,让mongodump通过--sslPEMKeyFile或--authenticationDatabase隐式认证 -
crontab条目统一用root用户,且PATH显式设为/usr/bin:/bin:/usr/local/bin,避免依赖shell环境变量 - 监控脚本(如
mongostat采集)必须加timeout 30,否则网络抖动时service模块会卡死整个playbook
最隐蔽的问题是:Ansible的shell模块默认不继承~/.bashrc,哪怕你user: mongodb,which mongodump也可能返回空——得用executable: /bin/bash显式指定解释器。











