闲谈KubeBlocks For MongoDB设计实现

作者:小猿姐日期:2025/10/20

闲谈KubeBlocks For MongoDB设计实现

引言

MongoDB 是目前最受欢迎的 NoSQL 数据库之一,这跟它的多种特性有关,如面向文档、高性能、易使用等等,业务使用较为友好。不过由于它本身的复杂性,如节点多状态、多拓扑结构等,使得 MongoDB 的运维管理较为困难。在 K8S 环境下,由于资源的灵活编排,网络的隔离限制,进一步增加了 MongoDB 云原生化的难度,本文将从以下几点阐述 KubeBlocks For MongoDB 在设计实现过程中遇到的难点及解决方案,让大家有一个基本了解及能更好的使用KB。

多拓扑结构的灵活定义

MongoDB 支持单节点、副本集、分片集群等部署形态,以满足不同的业务需求。不同的拓扑形态部署方式差异较大,比如副本集支持多节点部署,每个节点除了状态不一样,数据是完全一致的(仲裁节点不包含数据)。分片包含多个不同组件 mongos、configServer、Shard,不同组件的管理方式不一样,而且组件管理有顺序依赖。为了能够定义和实现不同引擎的不同拓扑形态(KubeBlocks是多引擎的通用管理平台),KubeBlocks 在 ClusterDefinition 中支持了 topology 的自定义功能,MongoDB 实现如下:

1apiVersion: apps.kubeblocks.io/v1
2kind: ClusterDefinition
3metadata:
4  name: mongodb
5spec:
6  topologies:
7  - components:
8    - compDef: mongodb-
9      name: mongodb
10    default: true
11    name: replicaset
12  - components:
13    - compDef: mongo-mongos-
14      name: mongos
15    - compDef: mongo-config-server-
16      name: config-server
17    name: sharding
18    orders:
19      update:
20      - mongos
21      - config-server
22      - shard
23    shardings:
24    - name: shard
25      shardingDef: mongo-shard-
26

这里定义了两种拓扑形态:replicaset 和 sharding。顾名思义 replicaset 用于副本集实现,sharding 用定义分片集群。而单节点则认为是副本数为1的 replicaset。其中分片集群中不同组件的依赖关系通过 orders 定义,确保分片集群在运维操作时按照指定顺序执行。不同组件的具体实现可以参考 compDef 指定的 componentDefinition,代码在kubeblocks-addons 仓库中。

创建 Cluster 时,通过 topology 指定所需的拓扑形态:

1apiVersion: apps.kubeblocks.io/v1
2kind: Cluster
3spec:
4  terminationPolicy: {{ .Values.extra.terminationPolicy }}
5  clusterDef: mongodb
6  {{- if or (eq .Values.mode "replicaset") (eq .Values.mode "standalone") }}
7  topology: replicaset
8  {{- else if eq .Values.mode "sharding" }}
9  topology: sharding
10  {{- end }}
11...
12

无法避免的数据倾斜

MongoDB 分片集群模式下,数据倾斜是最常见的问题之一。可能有多种原因导致,如分片键的选择、业务的数据属性等等,总之数据倾斜基本无法避免。KubeBlocks For MongoDB 支持单个或多个 shard 的独立变更,当数据出现倾斜时,可通过 shardTemplates 对指定的 shard 执行按需变配:

1apiVersion: apps.kubeblocks.io/v1
2kind: Cluster
3spec:
4  clusterDef: mongodb
5  topology: sharding
6  shardTemplates:
7  - shardIDs:
8    - shard-xxx  #指定变配的shard ID
9    resources:
10      limits:
11        cpu: "1"
12        memory: 2Gi
13      requests:
14        cpu: 100m
15        memory: 204Mi
16    volumeClaimTemplates:
17    - name: data
18      spec:
19        accessModes:
20        - ReadWriteOnce
21        resources:
22          requests:
23            storage: 20Gi
24

如何提供K8S外部访问

在默认情况下,MongoDB 副本集使用 Pod 的 headless service 对外提供访问,副本之间也是通过 headless service进行通信,这主要应用于业务在同一 K8S 集群内部的场景。当业务在 K8S 集群之外时,headless service 无法访问,由于 MongoDB 的集群发现协议,简单的对 headless service 进行路由转发,只能提供 MongoDB 的直接访问,无法实现 MongoDB 副本集的高可用链接。因此 KubeBlocks For MongoDB 支持了主机网络模式,用于提供 K8S 集群外部业务访问 MongoDB 的能力。

创建 Cluster 时,可通过 annotation 指定实例为主机网络模式:

1apiVersion: apps.kubeblocks.io/v1
2kind: Cluster
3metadata:
4  annotations:
5    {{- if ne .Values.mode "sharding" }}
6    kubeblocks.io/host-network: mongodb
7    {{- end }}
8...
9

实现逻辑是:当 Cluster 指定为主机网络模式时,每个副本运行的 Pod都 采用主机网络模式,副本集初始化所使用的 Host 也采用 Node IP,确保对外和副本之间都使用主机网络。

使用主机网络后带来一个问题是:当 Pod 发生漂移后,它的 Node IP也发生变化,导致副本集中节点无法重新加入集群,出现异常状态。为了解决 Pod 漂移问题,KubeBlocks For MongoDB 实现了一个动态适配逻辑,当 Pod 的 Node IP 发生变化时,它会自动修正副本集中的节点配置,确保节点状态和集群状态正常。

缺点:

  • 只能用于业务可联通主机网络的场景;
  • 在同一时刻,只能存在少数节点不可用。

建议,如果需要K8S集群外部访问,尽量使用 MongoDB 分片集群形态,mongos 的链接地址可以进行路由转发。

是否需要高可用服务

MongoDB 副本集和分片集群一般采用三副本架构,当一个副本出现时,它会自动进行 Failover,以正常服务。乍一看,MongoDB 已经具备了高可用能力,加上Pod的自动重启机制,就无需额外的高可用服务了。所以现有的 MongoDB Operator 基本只提供了 MongoDB 多副本形态,没有高可用服务。但这真的高可用,可以上生产吗?

其实这是不够的,三副本场景下,一个副本异常,虽然可以继续服务,但实例已处于亚健康状态了。如果再出现副本异常,实例就不可服务。所以三副本提供了一定的高可用冗余能力,但并不能保证一定不出问题。

Pod自动重启机制加上livenessProbe,可以在异常场景下,实现服务自动重启。这个在stateless场景下很好用,但在数据库这种重状态的场景下使用,会一种灾难,它会导致一些不可预期的问题,比如不间断重启、进程非预期强杀等等。

KubeBlocks For MongoDB 提供了额外的高可用服务,在 Failover 时,会探测到异常情况,发生告警事件,对于部分异常状态会尝试进行自动修复,不能自动修复的场景,交由人工处理,确保服务正常。

社区版缺少的企业级备份恢复

社区版 MongoDB 只支持逻辑备份,物理备份需要文件系统支持快照能力时才能通过快照实现,而目前基本只有云盘才支持,其它大部分环境是不支持的。导致 MongoDB 的备份非常受限,在数据量大、负载高的情况下甚至无法实现有效备份(没有热备能力,逻辑备份无法保证数据的一致性)。如果需要完全的备份能力需要购买 MongoDB 企业版或者 Atlas 实例才行。

显然这对于数据安全要求较高的 DB 服务来说是难以接受的,因此 KubeBlocks For MongoDB 引进了 Percona 的扩展能力,实现了包括物理备份在内的多种备份能力,以满足企业级服务要求。

逻辑备份

适用于数量小,负载低的实例,优点是灵活,可以指定 db 或 collection 进行备份或恢复。缺点是速度较慢,在负载高时,可能会备份失败

物理备份

物理备份时采用了 Wiredtiger 支持的 backupCursor 能力,确保备份过程中,业务读写不受影响。适用数量大、负载高的实例,优点是速度快,它的备份速度至少是逻辑备份的 5 倍以上。缺点是不够灵活,只能实现整体备份和恢复

PITR

支持副本集和分片集群的日志备份,及按时间点恢复的能力。确保实例数据可以快速精准恢复。

必不可少的审计日志

审计是企业级服务中必不可少的能力,这个在 MongoDB 社区版中也是没有,需要购买。KubeBlocks For MongoDB 引入了 Percona 扩展能力,支持 JSON 格式,方便审计排查:

1{ "atype" : "clientMetadata", "ts" : { "$date" : "2025-10-14T09:26:26.261+00:00" }, "local" : { "ip" : "10.13.33.216", "port" : 27017 }, "remote" : { "ip" : "10.13.34.28", "port" : 45592 }, "users" : [], "roles" : [], "param" : {}, "result" : 0 }
2{ "atype" : "clientMetadata", "ts" : { "$date" : "2025-10-14T09:26:26.267+00:00" }, "local" : { "ip" : "10.13.33.216", "port" : 27017 }, "remote" : { "ip" : "10.13.34.28", "port" : 45620 }, "users" : [], "roles" : [], "param" : {}, "result" : 0 }
3{ "atype" : "clientMetadata", "ts" : { "$date" : "2025-10-14T09:26:26.267+00:00" }, "local" : { "ip" : "10.13.33.216", "port" : 27017 }, "remote" : { "ip" : "10.13.34.28", "port" : 45608 }, "users" : [], "roles" : [], "param" : {}, "result" : 0 }
4

结束语

这不是一篇整体性介绍 KubeBlocks For MongoDB 实现的文章,只是想分享一下在实现过程中遇到的几个问题。顺便感慨一下:随着 MongoDB 商业化的成功,用户越来越多,其开源社区的运营却每况愈下。官网好多技术博客都下架了, MongoDB 中文社区也基本没有更新了。对于后来者而言,难度越来越高了。

KubeBlocks For MongoDB 将继续专注 MongoDB 在云原生方向的发展,提供方便、易用、敏捷的 MongoDB 服务,欢迎大家使用、交流、贡献。


闲谈KubeBlocks For MongoDB设计实现》 是转载文章,点击查看原文


相关推荐


复杂结构数据挖掘(二)关联规则挖掘 Association rule mining
nju_spy2025/10/19

你是否曾好奇,为什么超市总把啤酒和尿布摆在一起?这看似随意的陈列背后,藏着数据挖掘领域的经典智慧 —— 关联规则挖掘。在大数据时代,海量交易记录如同未开垦的金矿,而关联规则正是撬开这座金矿的关键工具。想象一下,当你在电商平台浏览商品时,系统推荐的 "买了这个的人还买了...",或是超市根据消费数据优化的货架布局,这些场景背后都离不开关联规则算法的神奇魔力。         从本质上讲,关联规则挖掘要解决的核心问题,是在庞大的交易数据中找出 "X→Y" 这样的隐含关系 —— 例如 "买了面包的人


程序员必备!5 款免费又好用的数据库管理工具推荐
追逐时光者2025/10/18

前言 在数据驱动的时代,数据库管理工具对于程序员而言如同瑞士军刀般不可或缺。它们不仅能够帮助我们高效地管理数据库,还能提升数据处理的准确性和速度。今天大姚给大家分享 5 款免费且实用的数据库管理工具(排名不分先后,欢迎文末留下你常用的数据库管理工具),希望可以帮助到有需要的同学。 DataGrip DataGrip 是 JetBrains 推出的一款跨平台(在 Windows、macOS 和 Linux 上提供一致的体验)数据库 IDE,专为 SQL 开发与数据库管理而打造。它集智能代码补全、A


kotlin中MutableStateFlow和MutableSharedFlow的区别是什么?
AsiaLYF2025/10/16

在 Kotlin 的协程库(kotlinx.coroutines.flow)中,MutableStateFlow 和 MutableSharedFlow 都是用于构建响应式数据流的可变(Mutable)热流(Hot Flow),但它们的设计目标和行为特性有显著区别。以下是它们的核心对比: 1. 核心区别总结 特性MutableStateFlowMutableSharedFlow数据保留始终保存最新一个值(必须有初始值)不保留值(默认),但可配置缓冲区保留历史值订阅时机新订阅者立即收到当前最新


组合为什么优于继承:从工程实践到数学本质
canonical_entropy2025/10/15

在面向对象设计的殿堂里,"组合优于继承"(Composition over Inheritance)是一条近乎金科玉律的原则。每一位有经验的开发者都会告诫新手:优先使用组合,谨慎使用继承。但这背后的原因究竟是什么?仅仅是因为组合更加灵活吗?答案远不止于此。这种设计偏好的背后,实际上隐藏着深刻的数学原理,它关乎系统结构的稳定性、可预测性和长期可维护性。 第一部分:工程实践的智慧结晶 在日常编程实践中,我们对"组合优于继承"有着直观而实用的理解。 继承的"白盒"困境 继承建立了一种"is-a"(是一


这份超全JavaScript函数指南让你从小白变大神
良山有风来2025/10/14

你是不是曾经看着JavaScript里各种函数写法一头雾水?是不是经常被作用域搞得晕头转向?别担心,今天这篇文章就是要帮你彻底搞懂JavaScript函数! 读完本文,你将收获: 函数的各种写法和使用场景 参数传递的底层逻辑 作用域和闭包的彻底理解 箭头函数的正确使用姿势 准备好了吗?让我们开始这场函数探险之旅! 函数基础:从“Hello World”开始 先来看最基础的函数声明方式: // 最传统的函数声明 function sayHello(name) { return "Hello


武装你的Python“工具箱”:盘点10个你必须熟练掌握的核心方法
烛阴2025/10/12

一、字符串方法 字符串处理是我们日常编程中最高频的操作之一。 .strip() - 去除首尾空白 示例: user_input = " admin \n" cleaned_input = user_input.strip() print(f"清理前: '{user_input}', 清理后: '{cleaned_input}'") # 输出: #清理前: ' admin #', 清理后: 'admin' .split() - 字符串切割 示例: csv_line =


我用亲身经历告诉你,为什么程序员千万别不把英语当回事
oioihoii2025/10/10

年轻人,如果你现在觉得写代码只需要认识 if/else 和 for 循环里的那几个英文单词就够了,那你简直像极了十年前的我。而今天的我,多想回到过去,给那个骄傲自满的自己一记响亮的耳光。 我不是以成功者的姿态来教导你,而是以一个踩过坑、吃过亏、肠子都悔青了的过来人身份,跟你聊聊我最后悔的一件事——没有早点学好英语。 一、工作里吃的哑巴亏,都是我当年脑子进的水 1. “啃”二手资料的酸楚 还记得那次,团队要引入一个热门的新框架。我兴冲冲地找了几篇中文博客,照猫画虎地搞了起来。结果,掉进了一个坑里,


Seata分布式事务框架详解与项目实战
IT橘子皮2025/10/9

一、Seata核心架构与原理 Seata(Simple Extensible Autonomous Transaction Architecture)是阿里巴巴开源的分布式事务解决方案,旨在为微服务架构提供高性能、易用性的分布式事务支持。其核心设计理念是"化繁为简",通过封装传统分布式事务模式的复杂性,降低分布式一致性问题的解决门槛。 ​核心组件​: ​TC(Transaction Coordinator)​​:事务协调者,维护全局事务和分支事务的状态,负责协调全局事务提交或回滚 ​TM(


【鸿蒙生态共建】一文说清复杂类型数据的非预期输入转换与兜底-《精通HarmonyOS NEXT :鸿蒙App开发入门与项目化实战》读者福利
俩毛豆2025/10/7

在客户端开发中,你是否曾遇到过这样的困扰:一次看似寻常的网络数据解析,却导致了出人意料的崩溃;一个本该正常的文件读取操作,却返回了难以理解的数据错误。这些问题的根源,往往指向同一环节——数据类型转换。当应用面对网络传输、文件I/O等不可控的数据源时,如何稳健、准确地进行数据解析与转换,就成为保障应用稳定性的第一道防线。 本篇内容是《精通HarmonyOS NEXT :鸿蒙App开发入门与项目化实战》这本书第四章内容的延续,是咱这本书读者的福利,在本篇内容中以模拟多种数据输入,向复杂类型(类、数


Spring Cloud之负载均衡之LoadBalance
新绿MEHO2025/10/6

目录 负载均衡 问题 步骤 现象  什么是负载均衡? 负载均衡的一些实现 服务端负载均衡 客户端负载均衡 使用Spring Cloud LoadBalance实现负载均衡 负载均衡策略 ​编辑 ​编辑LoadBalancer原理 服务部署 准备环境和数据 服务构建打包 启动服务 上传Jar包到云服务器 启动服务 远程调用访问  负载均衡 问题 上面是我们之前的代码,是根据应用名称获取了服务实例列表,并从列表中选择了一个服务实例。 那如果

首页编辑器站点地图

Copyright © 2025 聚合阅读

License: CC BY-SA 4.0