Ceph+K8s 中间件实战 | 第 17 天:K8s 部署 MongoDB 三主三从集群(Ceph RBD + 架构设计 + 运维命令)

第 17/28 天

引言

在前面的篇章中,我们已经在第 8 天用 Bitnami Helm Chart 部署过 MongoDB 副本集集群,并在第 15 天搭建了 Prometheus + Grafana 全景监控。今天我们把 MongoDB 的部署规格再上一个台阶:三主三从的分片集群(Sharded Cluster)。当业务数据量突破单机副本集的写入瓶颈(比如超过 TB 级、写入 QPS 持续走高)时,单靠”一主多从”已经无法线性扩展——从节点再多,写入也只能落在唯一的主节点上。分片集群通过将数据按分片键(Shard Key)水平拆散到多个分片,让每个分片都拥有自己的主节点与从节点,实现”三个主节点同时承担写入、三个从节点各自冗余备份”的分布式格局,这正是本篇”三主三从”的由来。

本篇依然遵循系列部署原则:存储全部落在 Ceph RBD 块设备上(复用第 2 天创建的 ceph-rbd StorageClass),部署使用开源 Bitnami Helm Chart,并给出完整的登录验证与日常巡检命令。

设计架构

组件拓扑

MongoDB 分片集群由三类角色组成,Bitnami Chart 会以多个 StatefulSet + Deployment 的形式把它们全部拉起:

组件 数量 职责 K8s 工作负载形态
mongos 路由 2 个实例 无状态查询路由器,接收客户端请求并按分片键分发到对应分片 Deployment
configsvr 副本集 3 个节点 保存集群元数据(分片列表、集合分片规则、chunk 分布) StatefulSet
shard0 / shard1 / shard2 每个分片 2 个数据节点(1 主 + 1 从) 真正存储数据的分片,各自独立副本集 StatefulSet × 3

整体拓扑一句话概括:客户端 → mongos(×2)→ 按分片键路由 → shard0/shard1/shard2 各自的 Primary → oplog 异步复制到各自 Secondary,而 configsvr 在后台为 mongos 提供路由元数据。三个分片各自拥有 1 个 Primary,合计”三主”;每个分片 1 个 Secondary,合计”三从”,即”三主三从”。

数据流向

  1. 应用通过 MongoDB 驱动连接 mongos(通常走 Service VIP,两个 mongos 实例负载均衡);
  2. mongos 向 configsvr 查询目标集合的 chunk 分布(路由表会缓存在内存中);
  3. 根据文档的分片键值计算哈希/范围,把读写请求转发到对应分片的 Primary;
  4. Primary 写入 WiredTiger 引擎与 oplog 后返回应答,Secondary 异步拉取 oplog 回放,保持数据一致;
  5. 当某个 chunk 数据量超过阈值(默认 64MB)时,mongos 触发 chunk 分裂与迁移,在分片之间搬移数据以保持均衡。

K8s Logo

高可用机制

  • 分片内副本集选举:每个分片内部是标准副本集,Primary 宕机后剩余节点通过 Raft 类协议选举出新主(默认选举超时 10s)。注意:每个分片只有 2 个数据节点时无法构成投票多数,演示环境可接受,生产环境建议 shardsPods: 3 或额外部署仲裁节点(详见 FAQ)。
  • mongos 无状态多实例:mongos 只缓存路由元数据,随时可销毁重建,配合 Headless Service 由客户端驱动做故障转移,两个实例互为备份。
  • configsvr 三副本:元数据副本集为 3 节点,任意 1 台故障不影响集群路由;configsvr 的数据同样落在 Ceph RBD 上,节点重建后数据自动恢复。
  • 存储层冗余:所有 mongod 的 PVC 都绑定 Ceph RBD 块设备,由 Ceph 自身的多副本(默认 size=3)提供底层数据冗余,K8s 节点宕机后 Pod 漂移到新节点,PVC 通过 RBD 重新挂载,数据零丢失。

存储规划

每个数据节点一个独立 PVC(RBD 块设备天然适合数据库随机读写,注意 RBD 是单写者语义,与副本集”一主写入”模型完美契合):

组件 PVC 数量 单 PVC 容量 StorageClass
mongos 0(无状态) – –
configsvr 3 10Gi ceph-rbd
每个分片 2 20Gi ceph-rbd

部署实战

第一步:添加 Bitnami Helm 仓库

💻 代码示例

helm repo add bitnami https://charts.bitnami.com/bitnami

helm repo update

helm search repo bitnami/mongodb –versions | head -5

第二步:编写 values.yaml

💻 代码示例

# /tmp/mongodb-sharded-values.yaml

architecture: sharded # 关键:分片集群模式

 

auth:

rootUser: root

rootPassword: "CephK8s@Mongo2026"

 

# 三主三从:3 个分片,每个分片 2 个数据节点(1 Primary + 1 Secondary)

shards: 3

shardsPods: 2

 

# config server 副本集 3 节点(元数据高可用)

configsvr:

replicaCount: 3

persistence:

enabled: true

storageClass: "ceph-rbd"

size: 10Gi

 

# mongos 路由 2 实例(无状态负载均衡)

mongos:

replicaCount: 2

 

# 所有分片数据节点统一持久化到 Ceph RBD

persistence:

enabled: true

storageClass: "ceph-rbd"

size: 20Gi

 

# 资源限制示例

resources:

requests:

cpu: 500m

memory: 1Gi

limits:

cpu: "1"

memory: 2Gi

说明:architecture: sharded 是分片模式的总开关;shards 决定分片数量;shardsPods 决定每个分片副本集内的数据节点数(2 即一主一从);configsvr 与 mongos 的副本数分别由各自段落控制。所有 storageClass 统一指向第 2 天配置的 Ceph RBD StorageClass,PVC 由 StatefulSet 的 volumeClaimTemplates 自动创建。

第三步:helm install 部署

💻 代码示例

helm install mongodb-sharded bitnami/mongodb

-n middleware –create-namespace

-f /tmp/mongodb-sharded-values.yaml

–timeout 20m

 

# 等待所有 Pod 就绪

kubectl rollout status statefulset -n middleware -l app.kubernetes.io/instance=mongodb-sharded –timeout=600s

第四步:验证 Pod / Service / PVC

💻 代码示例

# Pod:3 个分片 StatefulSet + configsvr + mongos

kubectl get pods -n middleware -l app.kubernetes.io/instance=mongodb-sharded

 

# 预期输出形如:

# mongodb-sharded-configsvr-0/1/2 Running

# mongodb-sharded-mongos-0/1 Running

# mongodb-sharded-shard0-data-0/1 Running

# mongodb-sharded-shard1-data-0/1 Running

# mongodb-sharded-shard2-data-0/1 Running

 

# PVC:全部绑定到 ceph-rbd StorageClass

kubectl get pvc -n middleware -l app.kubernetes.io/instance=mongodb-sharded

 

# Service:mongos 对外入口 + 各组件 Headless Service

kubectl get svc -n middleware -l app.kubernetes.io/instance=mongodb-sharded

登录验证

通过 mongos 入口连接集群(推荐从集群内任意 Pod 或使用 kubectl port-forward 转发):

💻 代码示例

kubectl exec -it mongodb-sharded-mongos-0 -n middleware —

mongosh –host 127.0.0.1 –port 27017

-u root -p 'CephK8s@Mongo2026' –authenticationDatabase admin

进入 mongosh 后执行分片集群状态检查:

💻 代码示例

// 1. 查看分片集群整体状态:分片列表、chunk 分布、均衡器

sh.status()

 

// 2. 列出所有分片

db.adminCommand({ listShards: 1 })

 

// 3. 验证三主三从:每个分片应有 1 个 PRIMARY + 1 个 SECONDARY

db.adminCommand({ replSetGetStatus: 1 })

验证数据真正分散到三个分片(分片键使用 hashed 类型保证均匀分布):

💻 代码示例

// 对业务库启用分片

sh.enableSharding("appdb")

 

// 创建哈希分片集合

sh.shardCollection("appdb.orders", { "_id": "hashed" })

 

// 插入测试数据后再次查看 chunk 分布(应散布在 shard0/1/2 上)

for (let i = 0; i < 10000; i++) {

db.getSiblingDB("appdb").orders.insertOne({ _id: i, uid: i % 1000, amount: i * 1.5 });

}

sh.status()

K8s Logo

日常巡检

1. 集群级健康检查

💻 代码示例

# 所有 Pod 与端点健康

kubectl get pods,svc,endpoints -n middleware -l app.kubernetes.io/instance=mongodb-sharded

 

# 各分片副本集角色与选举状态(逐个分片执行)

kubectl exec -it mongodb-sharded-shard0-data-0 -n middleware —

mongosh –port 27017 -u root -p 'CephK8s@Mongo2026' –authenticationDatabase admin

–eval "JSON.stringify(rs.status().members.map(m => ({name: m.name, stateStr: m.stateStr})))"

2. 日志与事件

💻 代码示例

# 跟踪 mongos 路由日志(慢查询、分片迁移事件都会在这里出现)

kubectl logs -f -n middleware mongodb-sharded-mongos-0

 

# 查看近期异常事件

kubectl get events -n middleware –sort-by=.lastTimestamp | tail -20

3. 性能与容量

💻 代码示例

# 节点资源水位

kubectl top pod -n middleware -l app.kubernetes.io/instance=mongodb-sharded

 

# PVC 使用率(Ceph RBD 卷)

kubectl get pvc -n middleware -l app.kubernetes.io/instance=mongodb-sharded

 

# 慢查询与连接数(mongosh 中执行)

kubectl exec -it mongodb-sharded-mongos-0 -n middleware —

mongosh –host 127.0.0.1 –port 27017 -u root -p 'CephK8s@Mongo2026' –authenticationDatabase admin

–eval "db.currentOp({secs_running: {$gt: 5}}); db.serverStatus().connections"

4. 容量巡检脚本(写入 crontab 每日执行)

💻 代码示例

cat > /usr/local/bin/mongo-inspect.sh << 'EOF'

#!/bin/bash

kubectl exec -it mongodb-sharded-mongos-0 -n middleware —

mongosh –host 127.0.0.1 –port 27017 -u root -p 'CephK8s@Mongo2026'

–authenticationDatabase admin –quiet –eval

"sh.status().shards.forEach(s => print(s._id, JSON.stringify(s))); db.adminCommand({listDatabases:1}).databases.forEach(d => print(d.name, d.sizeOnDisk))"

EOF

chmod +x /usr/local/bin/mongo-inspect.sh

# 0 2 * * * /usr/local/bin/mongo-inspect.sh >> /var/log/mongo-inspect.log 2>&1

常见问题

Q1:为什么建好集合后数据还是只往一个分片写?
A:开启分片必须三步走:sh.enableSharding("库名") → sh.shardCollection("库.集合", {分片键: "hashed"}) → 之后插入的数据才会按分片键路由。如果先插入了大量数据再分片,存量数据要等均衡器(Balancer)慢慢迁移。另外分片键要选基数高、访问均匀的字段,否则会出现”热点分片”。

Q2:每个分片只有 2 个数据节点,Primary 宕机后能自动切换吗?
A:MongoDB 副本集选举要求投票过半数,2 个节点中挂掉 1 个就无法选出新主,集群会进入只读/不可写状态。演示”三主三从”布局时这是可接受的;生产环境请把 shardsPods 改为 3(一主两从),或为每个分片额外部署仲裁节点(Arbiter),保证任何单点故障都能自动故障转移。

Q3:Ceph RBD 的 PVC 空间不够了怎么办?
A:分两层处理:K8s 层面直接扩容 PVC(kubectl edit pvc <名称> 调大 spec.resources.requests.storage,RBD 支持在线扩容,扩容后需要重启对应 mongod Pod 让文件系统感知新大小);同时 MongoDB 层面用 db.stats() / sh.status() 观察各分片容量,必要时增加新分片(再 helm upgrade 把 shards 调大)实现水平扩展,无需迁移旧数据。

总结

本篇完成了 MongoDB 分片集群在 K8s 上的全流程落地:通过 Bitnami Helm Chart 一键拉起 3 个分片(每分片一主一从,合计三主三从)+ 3 节点 configsvr + 2 实例 mongos;所有数据节点 PVC 均绑定 Ceph RBD StorageClass,底层由 Ceph 多副本兜底;登录验证与日常巡检命令覆盖了集群状态、副本集角色、慢查询、容量与日志。相比第 8 天的单副本集,分片集群把写入能力从”1 个主节点”扩展到了”3 个主节点并行”,是支撑 TB 级业务的正确姿势。需要提醒的是:分片集群的运维复杂度明显更高,业务初期数据量不大时,单副本集 + 良好索引往往更划算。

K8s Logo

下期预告

第 18 天:K8s 部署 RabbitMQ 集群(Ceph RBD + 高可用架构 + 登录巡检)。RabbitMQ 是消息队列领域的事实标准之一,我们将用 Bitnami RabbitMQ Chart 部署三节点镜像队列集群,讲解队列镜像同步、Quorum Queue 与持久化消息在 Ceph RBD 上的落地,并给出生产环境的登录验证与巡检命令。敬请期待!

系列目录

  • [Day 1] Ceph 分布式存储回顾与 K8s 存储体系概述 — 3307.html
  • [Day 2] K8s 接入 Ceph RBD 块存储 — 3311.html
  • [Day 3] K8s 接入 CephFS 共享文件存储 — 3317.html
  • [Day 4] K8s 部署 MySQL 高可用集群 — 3320.html
  • [Day 5] K8s 部署 Redis Cluster 集群 — 3324.html
  • [Day 6] K8s 部署 Redis Sentinel 哨兵模式 — 3325.html
  • [Day 7] K8s 部署 MinIO 对象存储集群 — 3329.html
  • [Day 8] K8s 部署 MongoDB 副本集集群 — 3333.html
  • [Day 9] K8s 部署 Nacos 注册配置中心 — 3337.html
  • [Day 10] K8s 部署 Zookeeper 集群 — 3341.html
  • [Day 11] K8s 部署 Elasticsearch 集群 — 3345.html
  • [Day 12] K8s 部署 Kafka 集群 — 3349.html
  • [Day 13] K8s 部署 GitLab 代码托管平台 — 3355.html
  • [Day 14] K8s 部署 ClickHouse 列式数据库集群 — 3359.html
  • [Day 15] K8s 中间件统一监控与运维巡检总结 — 3363.html
  • [Day 16] K8s 部署 PostgreSQL 高可用集群 — 3391.html
  • 🟢 Day 17 今日 K8s 部署 MongoDB 三主三从集群
  • [Day 18] K8s 部署 RabbitMQ 集群
  • [Day 19] K8s 部署 Apache Pulsar 集群
  • [Day 20] K8s 部署 OpenSearch 集群
  • [Day 21] K8s 部署 ELK Stack 日志平台
  • [Day 22] K8s 部署 Loki + Grafana 日志监控
  • [Day 23] K8s 部署 Jenkins CI/CD 平台
  • [Day 24] K8s 部署 Harbor 镜像仓库
  • [Day 25] K8s 部署 Consul 服务网格
  • [Day 26] 场景串联①:基础生产栈
  • [Day 27] 场景串联②:微服务全栈
  • [Day 28] 场景串联③:大数据/日志密集栈
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像 - 恒星
欢迎您留下宝贵的见解!
提交
头像 - 恒星

昵称

取消
昵称表情代码图片快捷回复

    暂无评论内容