MongoDB Operator 不支持分片集群自动伸缩,需外部控制器驱动CR更新;shard/configsvr/mongos必须用StatefulSet管理;configsvr须奇数节点且显式命名;存储、资源、亲和性、readinessProbe等配置均有严格要求;扩容需手动splitAt+CR更新。

用 MongoDB Operator 部署分片集群前,先确认它真能自动伸缩
不能。MongoDB Community Edition 的 mongodbcommunity CRD(由 Percona 或 MongoDB 官方 Operator 提供)本身不支持运行时动态增减 mongos 或 shard 节点的自动伸缩——它只负责声明式部署与基础健康巡检。所谓“自动伸缩”,实际得靠外部控制器(如 KEDA + 自定义指标)驱动 CR 更新,再由 Operator 执行滚动变更。
常见错误现象:shard Pod 数量卡在 3 不变,即使你调高了 shardsvr.spec.replicas;或 mongos 副本数改了但 Service endpoints 没刷新,新流量进不去。
- Operator 版本必须 ≥ 1.25(旧版对分片拓扑的
updateStrategy支持不全) - 所有
shard、configsvr、mongos必须用 StatefulSet 管理,不能用 Deployment —— 否则主机名、PV 绑定、副本序号全乱 - Config Server 必须是奇数节点(3 或 5),且必须用
replicaSet.name: "csReplSet"显式指定,否则mongos初始化时连不上
配置分片拓扑时,shard 和 configsvr 的 storageClassName 别混用
K8s 中不同可用区的 PV 可能绑定不同 storageClassName,而 MongoDB 分片要求每个 shard 内部副本间网络延迟低、IO 性能一致。如果把 shard 和 configsvr 共用一个慢盘类(比如 standard),configsvr 会成为整个集群元数据操作瓶颈,导致 sh.addShard() 卡住或超时。
使用场景:跨 AZ 部署三副本分片时,shard 应用 ssd-highiops 类存储,configsvr 可用 ssd-balanced,但绝不能降级到 hdd。
-
configsvr的resources.requests.memory至少 2Gi,低于此值容易触发OutOfMemoryKilled导致 config server 全挂 - 每个
shard的volumeClaimTemplates必须带唯一name(如data-volume-shard0),否则多个 shard 共享 PVC 会导致数据覆盖 - 别在
shard的podAntiAffinity里只设topologyKey: topology.kubernetes.io/zone—— 这样同 zone 内多个副本可能挤在同一 Node,应叠加topologyKey: kubernetes.io/hostname
让 mongos 实现“伪自动伸缩”,关键在 Service 和 readinessProbe
mongos 本身无状态,但它的连接池和路由缓存依赖稳定的 endpoint 列表。直接扩 mongos 副本数没用,除非 Service 能立刻发现新 Pod 并透传流量,且新 Pod 已完成对 config server 的初始化同步。
常见错误现象:新增 mongos Pod 处于 Running 但 NotReady,kubectl get endpoints 里看不到对应 IP;或者流量持续打到旧实例,新实例零请求。
-
readinessProbe必须调用mongosh --eval "db.runCommand({ping:1})",不能只检查端口通 ——mongos进程起来但未连上 config server 时,端口已监听但无法路由 -
Service的sessionAffinity: None必须显式设置,否则默认 sticky session 会让客户端长期绑定某台mongos,失去伸缩意义 - 若用 Istio,需禁用
sidecar.istio.io/inject: "false"—— Envoy 代理会干扰mongos的内部心跳包,导致 config server 认为它失联
真正要伸缩分片容量,只能手动触发 sh.splitAt() + Operator CR 更新
Operator 不感知业务数据分布,也不会自动拆分 chunk。当某个 shard 的 chunk 数超过 200k 或单 shard 存储 > 200GB,就得人工干预:先用 sh.status() 查热点 shard,再用 sh.splitAt() 或 sh.splitFind() 拆分,最后通过 patch CR 更新该 shard 的 spec.replicas 并等待滚动完成。
性能影响:一次 splitAt 操作会阻塞该 chunk 上的写入约 1–3 秒;批量拆分建议错开业务高峰,并监控 shardingStatistics 中的 chunkMigrationInProgress 指标。
- 拆分前确保
balancer开启:sh.setBalancerState(true),否则 chunk 不会自动迁移 - Operator 更新
shard副本数后,新 Pod 加入 replica set 需要时间同步数据 —— 此期间rs.status().members[n].stateStr会是STARTUP2,别急着切流 - 永远别在
configsvr扩容中执行sh.addShard(),否则 config server 会返回NotMaster错误,新 shard 注册失败
最易被忽略的是 config server 的 mongod 日志级别:默认 verbosity: 0,一旦发生选举或迁移失败,根本看不到 replSet 相关细节。上线前务必把 logLevel: 1 加进 configsvr 的 additionalMongodConfig。










