1.实战中的配置
查看mongo集群的pod
1 | kubectl get pod -n mongo |
在 MongoDB 分片架构中:
- mongos (mongo-mongodb-sharded-mongos-0): 只是路由节点,负责转发请求,不存储任何数据。所以你在它的 describe 结果里只看到了 localtime 和 kube-api-access,看不到数据卷。
- configsvr (mongo-mongodb-sharded-configsvr-0): 存储集群的元数据(配置信息)。
- shard data (mongo-mongodb-sharded-shard0-data-0): 这才是真正存储数据库业务数据的地方。
想要知道数据实际存储在哪里
第一步:查看数据节点 Pod 的 PVC 名称
1 | kubectl describe pod mongo-mongodb-sharded-shard0-data-0 -n mongo |
找到Volumes部分,其中ClaimName就是PVC名字。
1 | Volumes: |
第二步:查看 PVC 对应的 PV 名称
1 | kubectl get pvc datadir-mongo-mongodb-sharded-shard0-data-0 -n mongo |
输出结果中VOLUME 那一列就是 PV 的名字。
1 | kubectl get pvc datadir-mongo-mongodb-sharded-shard0-data-0 -n mongo |
第三步:查看 PV 的物理路径
1 | kubectl get pv pvc-82de37fd-b2c7-4b90-8b83-553da08114f0 -o yaml |
spec 部分,查看路径信息。hostPath的path,就是物理地址了。来到这个路径,可以看到里面有.wt文件,这就是mongo存储数据的文件了。
从抽象需求(Pod/PVC)到具体实现(PV/物理路径)的逐层剥离:
- Pod 层 (mongo-shard0-data-0):
- 视角: “我是数据库程序,我只知道把数据写到容器内的 /bitnami/mongodb/data 目录。这个目录挂载了一个叫 datadir 的卷。”
- 线索: ClaimName: datadir-mongo-0 (我有这张提货券)。
- PVC 层 (datadir-mongo-0):
- 视角: “我是提货券,我要求 10GB 的空间。K8s 告诉我,我已经绑定到了 pvc-abcd-1234 这个资源上。”
- 线索: Volume: pvc-abcd-1234。
- PV 层 (pvc-abcd-1234):
- 视角: “我是真正的存储资源对象。我有详细的连接信息。我的类型是 HostPath。”
- 线索: Path: /data/k8s-volumes/mongo/shard0。
- 物理层 (Linux Server):
- 视角: “我是硬盘上的一个文件夹。我就在 /data/k8s-volumes/mongo/shard0。”
为什么pod不能直接写死路径:
- 不可移植: 如果你的 Pod 迁移到了另一台服务器,或者换了一个集群,而新环境里没有 192.168.1.5 这台机器,Pod 就直接报错跑不起来了。
- 开发与运维分离: 开发人员(写 Pod 的人)通常不知道、也不应该关心服务器的 IP 和硬盘路径。运维人员(管 PV 的人)才需要关心。
分片架构为什么要这样设计
核心理念只有四个字:**分而治之 (Divide and Conquer)**。
它的目的是为了解决单机性能瓶颈(磁盘不够大、CPU 跑满、内存不足)。为了实现无限的水平扩展(Horizontal Scaling),MongoDB 将功能拆解成了这三个独立的组件。
可以用一个“大型物流中心”的例子来完美类比这个架构:
- Mongos:前台接待/调度员 (Router)
- 对应你的 Pod: mongo-mongodb-sharded-mongos-0
- 角色特点: 无状态、不存货、只动嘴。
- 为什么这么设计?
- 它是应用程序(App)的唯一入口。你的代码只需要连接 mongos,就像你寄快递只找前台一样。
- 不存数据:因为它是负责计算路由逻辑的。它需要消耗 CPU 来解析你的查询命令,计算出数据在哪个分片上。
- 作用: 如果没有它,你的 App 就得自己去记“张三的数据在服务器 A,李四的数据在服务器 B”,这太痛苦了。Mongos 屏蔽了底层的复杂性。
- Config Server:仓库账本/目录管理员 (Metadata)
- 对应你的 Pod: mongo-mongodb-sharded-configsvr-0
- 角色特点: 存目录、数据量小、极度重要。
- 为什么这么设计?
- 它存储的是**“元数据” (Metadata)**。也就是一张巨大的“地图”。
- 它记录了:“数据被切成了几块?如果在服务器 A 找不到,应该去服务器 B 找吗?哪个分片负责哪个范围的数据?”
- 关系: mongos 接到请求后,必须先问 Config Server:“嘿,用户要查 ID=100 的数据,他在哪个仓库?”然后 mongos 才知道去哪里拿数据。
- 注意: 虽然它也存数据,但存的是配置信息,不是业务数据,所以它通常不需要很大的磁盘,但要求极高的数据一致性。
- Shard (Data Node):真正的仓库/搬运工 (Data Storage)
- 对应你的 Pod: mongo-mongodb-sharded-shard0-data-0
- 角色特点: 存真货、干苦力、可无限增加。
- 为什么这么设计?
- 这里存储了你真正的业务数据(比如用户表、订单表)。
- 分片 (Sharding) 的意思就是:假设你有 100TB 数据,不可能塞进一台机器。于是我们把数据切碎:
- Shard-0 存“A开头~H开头”的用户。
- Shard-1 存“I开头~Z开头”的用户。
- 作用: 这就是为什么你要找数据必须看这个 Pod 的原因。所有的磁盘 I/O 读写压力都在这里。
总结:一次查询的生命周期
为了串联它们,假设你的 K8s 集群里来了一个请求:“帮我查找用户 ID = 5000 的资料”。
- 第一步(Mongos): 请求到达 mongos-0。Mongos 只是个接待员,它手里没有数据。
- 第二步(Config): Mongos 悄悄看了一眼缓存里的“账本”(这个账本是从 configsvr-0 同步过来的)。账本上写着:“ID 0~10000 的数据在 Shard-0 仓库里”。
- 第三步(Shard): Mongos 转头把请求转发给 shard0-data-0。
- 第四步(返回): shard0-data-0 在自己的硬盘里找到数据,返回给 Mongos,Mongos 再返回给用户。
为什么要拆得这么细?(设计优势)
- 无限扩展能力(Horizontal Scaling):
- 如果数据把 shard0 塞满了怎么办?很简单,加一组 shard1 服务器。Mongos 会自动把一部分数据搬过去。你的 App 甚至感觉不到变化,不需要停机。
- 性能隔离:
- CPU 密集型任务(如路由计算、排序聚合)由 mongos 承担。
- IO 密集型任务(读写磁盘)由 shard 承担。
- 如果查询太慢,可以单独给 mongos 加 CPU;如果磁盘不够,可以单独给 shard 加硬盘。
- 高可用(High Availability):
- 在这个架构中,每一个组件(Shard, Config, Mongos)通常都是多副本的。
- Shard 坏了一个节点?有备份节点顶上。
- Mongos 坏了一个?K8s Service 会自动把流量切到另一个 Mongos 上。
这就是为什么你在 K8s 里看到这么多不同名字的 Pod,它们各司其职,共同支撑起了一个海量数据存储系统。