1.实战中的配置

查看mongo集群的pod

1
2
3
4
5
6
7
8
9
10
kubectl get pod -n mongo
NAME READY STATUS RESTARTS AGE
mongo-mongodb-sharded-configsvr-0 1/1 Running 0 16d
mongo-mongodb-sharded-configsvr-1 1/1 Running 1 (16d ago) 16d
mongo-mongodb-sharded-configsvr-2 1/1 Running 1 (16d ago) 16d
mongo-mongodb-sharded-mongos-0 1/1 Running 0 16d
mongo-mongodb-sharded-mongos-1 1/1 Running 0 16d
mongo-mongodb-sharded-shard0-data-0 1/1 Running 0 16d
mongo-mongodb-sharded-shard0-data-1 1/1 Running 0 16d
mongodb-exporter-976c9b7b-8dt25 1/1 Running 0 16d

在 MongoDB 分片架构中:

  1. mongos (mongo-mongodb-sharded-mongos-0): 只是路由节点,负责转发请求,不存储任何数据。所以你在它的 describe 结果里只看到了 localtime 和 kube-api-access,看不到数据卷。
  2. configsvr (mongo-mongodb-sharded-configsvr-0): 存储集群的元数据(配置信息)。
  3. 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
2
3
4
5
Volumes:
datadir:
Type: PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
ClaimName: datadir-mongo-mongodb-sharded-shard0-data-0
ReadOnly: false

第二步:查看 PVC 对应的 PV 名称

1
kubectl get pvc datadir-mongo-mongodb-sharded-shard0-data-0 -n mongo

输出结果中VOLUME 那一列就是 PV 的名字。

1
2
3
kubectl get pvc datadir-mongo-mongodb-sharded-shard0-data-0 -n mongo
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
datadir-mongo-mongodb-sharded-shard0-data-0 Bound pvc-82de37fd-b2c7-4b90-8b83-553da08114f0 100Gi RWO local-storage 16d

第三步:查看 PV 的物理路径

1
kubectl get pv pvc-82de37fd-b2c7-4b90-8b83-553da08114f0 -o yaml

spec 部分,查看路径信息。hostPath的path,就是物理地址了。来到这个路径,可以看到里面有.wt文件,这就是mongo存储数据的文件了。

抽象需求(Pod/PVC)到具体实现(PV/物理路径)的逐层剥离:

  1. Pod 层 (mongo-shard0-data-0):
    • 视角: “我是数据库程序,我只知道把数据写到容器内的 /bitnami/mongodb/data 目录。这个目录挂载了一个叫 datadir 的卷。”
    • 线索: ClaimName: datadir-mongo-0 (我有这张提货券)。
  2. PVC 层 (datadir-mongo-0):
    • 视角: “我是提货券,我要求 10GB 的空间。K8s 告诉我,我已经绑定到了 pvc-abcd-1234 这个资源上。”
    • 线索: Volume: pvc-abcd-1234。
  3. PV 层 (pvc-abcd-1234):
    • 视角: “我是真正的存储资源对象。我有详细的连接信息。我的类型是 HostPath。”
    • 线索: Path: /data/k8s-volumes/mongo/shard0。
  4. 物理层 (Linux Server):
    • 视角: “我是硬盘上的一个文件夹。我就在 /data/k8s-volumes/mongo/shard0。”

为什么pod不能直接写死路径:

  1. 不可移植: 如果你的 Pod 迁移到了另一台服务器,或者换了一个集群,而新环境里没有 192.168.1.5 这台机器,Pod 就直接报错跑不起来了。
  2. 开发与运维分离: 开发人员(写 Pod 的人)通常不知道、也不应该关心服务器的 IP 和硬盘路径。运维人员(管 PV 的人)才需要关心。

分片架构为什么要这样设计

核心理念只有四个字:**分而治之 (Divide and Conquer)**。

它的目的是为了解决单机性能瓶颈(磁盘不够大、CPU 跑满、内存不足)。为了实现无限的水平扩展(Horizontal Scaling),MongoDB 将功能拆解成了这三个独立的组件。

可以用一个“大型物流中心”的例子来完美类比这个架构:

  1. Mongos:前台接待/调度员 (Router)
  • 对应你的 Pod: mongo-mongodb-sharded-mongos-0
  • 角色特点: 无状态、不存货、只动嘴。
  • 为什么这么设计?
    • 它是应用程序(App)的唯一入口。你的代码只需要连接 mongos,就像你寄快递只找前台一样。
    • 不存数据:因为它是负责计算路由逻辑的。它需要消耗 CPU 来解析你的查询命令,计算出数据在哪个分片上。
    • 作用: 如果没有它,你的 App 就得自己去记“张三的数据在服务器 A,李四的数据在服务器 B”,这太痛苦了。Mongos 屏蔽了底层的复杂性。
  1. Config Server:仓库账本/目录管理员 (Metadata)
  • 对应你的 Pod: mongo-mongodb-sharded-configsvr-0
  • 角色特点: 存目录、数据量小、极度重要。
  • 为什么这么设计?
    • 它存储的是**“元数据” (Metadata)**。也就是一张巨大的“地图”。
    • 它记录了:“数据被切成了几块?如果在服务器 A 找不到,应该去服务器 B 找吗?哪个分片负责哪个范围的数据?”
    • 关系: mongos 接到请求后,必须先问 Config Server:“嘿,用户要查 ID=100 的数据,他在哪个仓库?”然后 mongos 才知道去哪里拿数据。
    • 注意: 虽然它也存数据,但存的是配置信息,不是业务数据,所以它通常不需要很大的磁盘,但要求极高的数据一致性。
  1. 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 的资料”

  1. 第一步(Mongos): 请求到达 mongos-0。Mongos 只是个接待员,它手里没有数据。
  2. 第二步(Config): Mongos 悄悄看了一眼缓存里的“账本”(这个账本是从 configsvr-0 同步过来的)。账本上写着:“ID 0~10000 的数据在 Shard-0 仓库里”
  3. 第三步(Shard): Mongos 转头把请求转发给 shard0-data-0。
  4. 第四步(返回): shard0-data-0 在自己的硬盘里找到数据,返回给 Mongos,Mongos 再返回给用户。

为什么要拆得这么细?(设计优势)

  1. 无限扩展能力(Horizontal Scaling):
    • 如果数据把 shard0 塞满了怎么办?很简单,加一组 shard1 服务器。Mongos 会自动把一部分数据搬过去。你的 App 甚至感觉不到变化,不需要停机。
  2. 性能隔离:
    • CPU 密集型任务(如路由计算、排序聚合)由 mongos 承担。
    • IO 密集型任务(读写磁盘)由 shard 承担。
    • 如果查询太慢,可以单独给 mongos 加 CPU;如果磁盘不够,可以单独给 shard 加硬盘。
  3. 高可用(High Availability):
    • 在这个架构中,每一个组件(Shard, Config, Mongos)通常都是多副本的。
    • Shard 坏了一个节点?有备份节点顶上。
    • Mongos 坏了一个?K8s Service 会自动把流量切到另一个 Mongos 上。

这就是为什么你在 K8s 里看到这么多不同名字的 Pod,它们各司其职,共同支撑起了一个海量数据存储系统。