云原生中间件 -- MongoDB Operator 篇

近年来,在容器技术、开源和微服务等云原生相关理念的发展带动下,将应用部署到云上已经是大势所趋。而企业用户在现有应用业务逻辑不变时,进行应用系统无缝入云的过程中,中间件起到了应用赋能、支持上层应用等至关重要的作用,因此中间件也逐渐成为云的一部分。中间件上云主要特点是快速部署交付、降本增效、灵活扩展和简单管理。MongoDB 作为一个基于分布式文件存储的非关系型数据库,在高性能、高可用、大量数据存储、易部署、易操作等方面具有很大优势,在越来越多的场景中被使用。本篇以 MongoDB Operator 为入口,来介绍中间件在云原生中是如何设计、开发和使用的。

01

MongoDB 介绍

1.1 MongoDB 是什么?

MongoDB是一个基于分布式文件存储的数据库。由 C++ 语言编写,旨在简化用户开发和扩展。MongoDB 中的记录的数据结构类似一个文档,它是由字段和值对组成的。MongoDB 文档类似于 JSON 对象。字段的值可能包括其他文档、数组和文档数组。

图片来源:https://mongodb.net.cn/Upload/crud-annotated-document.bakedsvg.svg

它的主要特征如下:

  • 高性能

MongoDB提供高性能的数据持久性。针对嵌入式数据模型,支持减少了数据库系统上的 I /O 活动,及通过索引支持更快的查询,并且可以包括来自嵌入式文档和数组的键。

  • 丰富的查询语言

MongoDB 查询 API,提供丰富的查询语言,以支持读写操作,同时 MongoDB 还保留了关系型数据库即时查询的能力,保留了索引(底层是基于 Btree)的能力,相比于同类型的 NoSQL redis 并没有上述的能力。

  • 高可用性

MongoDB 自身提供了副本集,能将数据分布在多台机器上实现冗余,目的是可以提供自动故障转移、扩展读能力。

一个副本集是一组维护相同数据集的 MongoDB 服务器,提供冗余并增加数据可用性。

  • 水平可扩展性

MongoDB 提供水平可伸缩性功能,使用分片技术对数据进行扩展,MongoDB 能自动分片、自动转移分片里面的数据块,让每一个服务器里面存储的数据都是一样大小。

  • 支持多种存储引擎

MongoDB 支持多个存储引擎,如 WiredTiger 和内存中存储引擎。此外,MongoDB 提供灵活的存储引擎 API,允许第三方为 MongoDB 开发存储引擎。

1.2 MongoDB 部署模式

  • Standalone 模式:单点模式,单节点模式指运行在服务器上的一个 mongod 进程,用于读写数据。用户快速部署一个 MongoDB 单节点服务器,用于日常的开发、测试和学习等。

  • Replica Set 模式:副本集模式,一个副本集是一组 mongod 的实例集合,维护着相同的数据集,主要包含三类节点角色,如下图:

图片来源:https://mongodb.net.cn/Upload/replica-set-primary-with-two-secondaries.bakedsvg.svg

a. Primary 主节点

一个 Replica Set 可以有多个 Secondary 成员,但有且仅有一个节点是 Primary 节点,只有 Primary 节点是可读可写的,用户也可以修改配置,设置 Primary 节点只负责写入操作,而使 Secondary 节点负责读取操作,实现数据集的读写分离;

客户端在 Primary 节点上进行读写操作,然后通过 Replication 的异步同步机制,将数据同步到所有 Secondary 成员。在一定的时间之后,所有 Secondary 成员将拥有相同的数据集。

当 Primary 挂掉或不可用后,即 Replica Set 探测到 Primary 不可访问时,将启动自动故障转移进程,从其他的 Secondary 成员中,由 Secondary 或者 Arbiter (仲裁)节点投票选举出一个新成员作为 Primary,接收和处理客户端的请求,从而可以为用户继续提供服务了。

b. Secondary 副本节点

副本节点的主要功能是做数据的备份,当主节点不可用的时候,参与选主。副本节点之间相互有心跳监听,可以感知集群的整体状态,同时也可以作为数据源,为用户提供查询的功能。

c. Arbiter 仲裁节点

仲裁节点的特点主要是不存数据,不会被选为主,只进行选主投票功能。使用Arbiter 作用是可以减少数据的冗余备份,节省资源,又可以提供高可用的能力。

  • Sharding 模式:分片集群模式,分片是一种跨多台机器分发数据的方法。其实就是 MongoDB 横向扩容的一个整体架构实现,MongoDB 使用分片来支持具有非常大的数据集和高吞吐量操作的部署。解决 MongoDB 的性能和容量瓶颈等系统增长问题。

    一个 MongoDB 分片集群,由 shard、mongos 和 config servers 三个组件组成。

图片来源:https://mongodb.net.cn/manual/sharding/ 

1. mongos:mongos 充当查询路由的角色,为客户端应用程序和分片集群间的通信提供一个接口。向上对接客户端 Client,当收到写请求的时,按照特定算法,将请求下发到某一个 Shard 集群,写入数据。当收到读请求的时,通过定位找到要读的数据对象在哪个 Shard 上,把请求转发到这个 Shard 上,读取数据。

2. shard:是存储数据的地方,每个分片存储的数据是分片集群的数据集中的一个子集。从 MongoDB 3.6 版本开始,每个分片必须部署为副本集架构。理论上,副本集集群的个数是可以无限增长的。

3. config servers: Config servers(配置服务器)主要存储了分片集群的元数据和配置信息。从 MongoDB 3.4 版本开始,config servers 也必须部署为副本集架构。

通过以上介绍,我们可知分片集群模式的主要特点,就是可以将数据集分成多个数据块,存储在不同的分片节点上。当数据量大量增加的时候,用户可以通过添加分片来实现扩容功能。同时,分片集群模式支持多主多从的能力,不同的分片的主节点处理不同的请求;每个分片的主从之间可以进行数据的同步和备份,当一个分片的主节点不可用时,也可以自动的进行选主功能,且在选主过程中,其他的分片主节点亦可对用户提供服务。

02

需求分析

2.1 单点模式需求

  • 可以通过 CR 快速部署单点模式的 MongoDB 容器;

  • 可以自动维护 MongoDB 实例节点状态;

  • 可以调整 MongoDB 的配置文件;

  • 可以设置 MongoDB 资源大小;

  • 支持 MongoDB 镜像版本的设置;

  • 支持设置 MongoDB 的 root 密码;

  • 支持用户设置自定义数据库、用户和密码;

  • 可以备份,备份快照数据支持放入 S3 存储;

  • 可以设置备份计划,定时创建备份快照;

  • 支持 MongoDB 数据的持久化, 使用支持 storageClass 方式的 PVC;

  • 支持更新/删除 MongoDB 服务实例;

  • 支持查看 MongoDB 服务的慢日志查询;

  • 支持查看 MongoDB 服务事件查询;

  • 支持对外可访问;

  • 支持 Statefulset、Service、Pod 等资源对象的常见操作;

  • 支持查看 MongoDB 实例 Pod 的实时日志和离线日志;

  • 支持 Pod 的 exec 能力;

  • 支持下载 Pod 中的日志文件;

  • 支持 MongoDB 的常见能力的运维操作,如查看 mongo 的状态、配置信息、快速搜索等;

  • 可以设置监控的资源配置,监控 MongoDB 实例的运行情况。

2.2 副本集模式需求

  • 可以通过 CR 快速部署副本集模式的 MongoDB 容器;

  • 可以自动维护 MongoDB 实例节点状态;

  • 可以调整 MongoDB 的配置文件;

  • 可以设置 MongoDB 资源大小;

  • 支持 MongoDB 镜像版本的设置;

  • 支持设置 MongoDB 的 root 密码;

  • 支持用户设置自定义数据库、用户和密码;

  • 支持设置仲裁节点;

  • 支持快速扩缩容;

  • 保证部署的排它能力,避免重要的服务跑在一台机器;

  • 可以备份,备份快照数据支持放入 S3 存储;

  • 可以设置备份计划,定时创建备份快照;

  • 支持 MongoDB 数据的持久化, 使用支持 storageClass 方式的 PVC;

  • 支持更新/删除 MongoDB 服务实例;

  • 支持查看 MongoDB 服务的慢日志查询;

  • 支持查看 MongoDB 服务事件查询;

  • 支持对外可访问;

  • 支持 Statefulset、Service、Pod 等资源对象的常见操作;

  • 支持查看 MongoDB 实例 Pod 的实时日志和离线日志;

  • 支持 Pod 的 exec 能力;

  • 支持下载 Pod 中的日志文件;

  • 支持查看 Mongo 节点的拓扑图;

  • 支持手动切换 Mongo 主节点,及查看主从节点切换记录;

  • 支持 MongoDB 的常见能力的运维操作,如查看 mongo 的状态、配置信息、插入数据等;

  • 可以设置监控的资源配置,监控 MongoDB 实例的运行情况。

2.3 分片模式需求

  • 可以通过 CR 快速部署分片模式的 MongoDB 容器;

  • 可以自动维护 MongoDB 实例节点状态;

  • 可以调整 MongoDB 的配置文件;

  • 可以设置 MongoDB 资源大小;

  • 支持 MongoDB 镜像版本的设置;

  • 支持设置 MongoDB 的 root 密码;

  • 支持用户设置自定义数据库、用户和密码;

  • 支持设置仲裁节点;

  • 支持设置 mongo 路由以及配置中心的数量;

  • 保证部署的排它能力,避免重要的服务跑在一台机器;

  • 可以备份,备份快照数据支持放入 S3 存储;

  • 可以设置备份计划,定时创建备份快照;

  • 支持 MongoDB 数据的持久化, 使用支持 storageClass 方式的 PVC;

  • 支持更新/删除 MongoDB 服务实例;

  • 支持查看 MongoDB 服务的慢日志信息查询;

  • 支持查看 MongoDB 服务事件查询;

  • 支持 Statefulset、Service、Pod 等资源对象的常见操作;

  • 支持查看 MongoDB 实例 Pod 的实时日志和离线日志;

  • 支持 Pod 的 exec 能力;

  • 支持下载 Pod 中的日志文件;

  • 支持查看 Mongo 节点的拓扑图;

  • 支持手动切换 Mongo 主节点,及查看主从节点切换记录;

  • 支持 MongoDB 的常见能力的运维操作,如查看 mongo 的状态、配置信息、插入数据等;

  • 可以设置监控的资源配置,监控 MongoDB 实例的运行情况。

03

方案

以下介绍了 MongoDB 组建成高可用集群的两种模式,分别在当前 operator 中的设计方案:

  • 副本集模式方案:使用 K8s 的 service 的 NodePort 方式作为外部连接的入口。用户可以通过集群外部连接地址访问 mongo 服务,通过 mongoDB Client 客户端本身的能力来发现 master 节点。

  • 分片模式方案:在 mongo 高可用分片集群模式中,客户端访问的方式,设置一组 mongos 地址,由 mongo 客户端来连接和使用集群。mongod 存储了分片集群的数据和配置信息,保证状态一致。同时这些地址是外部可达的,也支持集群外部的服务连接访问。

04

架构

MongoDB Operator 的实现基于 Operator SDK 技术框架来完成。通过 Operator 实现 Mongo 服务实例、备份、主从切换等 CRD 的定义,及通过 Operator Controller 中的 Reconcile,对 Mongo CR 实例运行状态进行监听,从而不断的调整和修复 Mongo CR,直到达到期望的状态,同时它还包含了对 Mongo 服务以及 Operator 的监控功能。

以下主要从 Opertaor 部署、功能开发、持续优化三个阶段,介绍 MongoDB Operator 开发设计思想:

  • Operator 部署阶段:作为开发者,确定了 mongo 相关的需求之后,首先要熟悉 mongo 的使用方式和基本知识,掌握 Kubernetes、Operator CRD/Controller Kubebuiler/operator-sdk 等技术,才能创建 mongo operator 项目;

  • Opertaor 功能开发阶段:mongo operator 功能主要包含 mongo 实例、备份、备份计划、主从切换等 CRD 设计定义、同时包含相应的监控的指标和告警规则的设计,实现对 Mongo 服务以及 Operator 的监控告警功能;

  • Opertaor 持续优化阶段:为实现 mongo CRD 相应的资源管理,通过 mongo operator 的 Reconclie 机制,实现对 CR 实例的监听和自动维护,使 CR 达到用户的期望的状态。

根据如上思想,MongoDB Operator 架构图如下:

其中 Reconcile 的核心思路如下:

05

案例

5.1 模型样例

  • 单点模型

// MongoDBSpec defines the desired state of MongoDB// Type 类型为 Standalonetype MongoDBSpec struct {
   
     Image               string                       `json:"image,omitempty"`  // +kubebuilder:validation:Enum=Standalone;ReplicaSet;ShardedCluster  Type                string                       `json:"type,omitempty"`  Service             string                       `json:"service,omitempty"`  RootPassword        string                       `json:"rootPassword,omitempty"`  DBUserSpec          DBUserSpec                   `json:"dbUserSpec,omitempty"`  NotPersistent       bool                         `json:"notPersistent,omitempty"`  CustomConfig        string                       `json:"customConfig,omitempty"`  ExportConnect       bool                         `json:"exportConnect,omitempty"`  Resources           *corev1.ResourceRequirements `json:"resources,omitempty"`  Storage             string                       `json:"storage,omitempty"`  BackUpStorage       string                       `json:"backUpStorage,omitempty"`  StorageClassName    string                       `json:"storageClassName,omitempty"`  MetricsExporterSpec MetricsExporterSpec          `json:"metricsExporterSpec,omitempty"`  PodSpec             PodSpec                      `json:"podSpec,omitempty"`}
  • 副本集模型

// MongoDBSpec defines the desired state of MongoDB// Type 类型为 ReplicaSettype MongoDBSpec struct {
   
     Image               string                       `json:"image,omitempty"`  // +kubebuilder:validation:Enum=Standalone;ReplicaSet;ShardedCluster  Type                string                       `json:"type,omitempty"`  Members             int                          `json:"members,omitempty"`  Service             string                       `json:"service,omitempty"`  RootPassword        string                       `json:"rootPassword,omitempty"`  DBUserSpec          DBUserSpec                   `json:"dbUserSpec,omitempty"`  Arbiter             bool                         `json:"arbiter,omitempty"`  NotPersistent       bool                         `json:"notPersistent,omitempty"`  CustomConfig        string                       `json:"customConfig,omitempty"`  ExportConnect       bool                         `json:"exportConnect,omitempty"`  Resources           *corev1.ResourceRequirements `json:"resources,omitempty"`  Storage             string                       `json:"storage,omitempty"`  BackUpStorage       string                       `json:"backUpStorage,omitempty"`  StorageClassName    string                       `json:"storageClassName,omitempty"`  MetricsExporterSpec MetricsExporterSpec          `json:"metricsExporterSpec,omitempty"`  PodSpec             PodSpec                      `json:"podSpec,omitempty"`}
  • 分片集群模型

// MongoDBSpec defines the desired state of MongoDB// Type 类型为 ShardedClustertype MongoDBSpec struct {
   
     Image                string                       `json:"image,omitempty"`  // +kubebuilder:validation:Enum=Standalone;ReplicaSet;ShardedCluster  Type                 string                       `json:"type,omitempty"`  ShardCount           int                          `json:"shardCount,omitempty"`  MongodsPerShardCount int                          `json:"mongodsPerShardCount,omitempty"`  MongosCount          int                          `json:"mongosCount,omitempty"`  ConfigServerCount    int                          `json:"configServerCount,omitempty"`  Service              string                       `json:"service,omitempty"`  RootPassword         string                       `json:"rootPassword,omitempty"`  DBUserSpec           DBUserSpec                   `json:"dbUserSpec,omitempty"`  Arbiter              bool                         `json:"arbiter,omitempty"`  NotPersistent        bool                         `json:"notPersistent,omitempty"`  CustomConfig         string                       `json:"customConfig,omitempty"`  Resources            *corev1.ResourceRequirements `json:"resources,omitempty"`  Storage              string                       `json:"storage,omitempty"`  BackUpStorage        string                       `json:"backUpStorage,omitempty"`  StorageClassName     string                       `json:"storageClassName,omitempty"`  MetricsExporterSpec  MetricsExporterSpec          `json:"metricsExporterSpec,omitempty"`  PodSpec              PodSpec                      `json:"podSpec,omitempty"`}
  • 备份模型

// MongoBackUpSpec defines the desired state of MongoBackUptype MongoBackUpSpec struct {
   
     Instance       string `json:"instance"`  Restart        bool   `json:"restart,omitempty"`  ChangeMasterTo string `json:"changeMasterTo,omitempty"`}
  • 主从节点切换模型

type MongoChannelSpec struct {
   
     Instance string `json:"instance"`  Restart        bool   `json:"restart,omitempty"`  ChangeMasterTo string `json:"changeMasterTo,omitempty"` }

5.2 使用样例

  • 单点部署/备份

apiVersion: mongo.daocloud.io/v1alpha1kind: MongoDBmetadata:  name: mongodb-testspec:  type: Standalone  image: daocloud.io/atsctoo/mongo:3.6  service: mongodb-001-svc  rootPassword: "654321"  dbUserSpec:    enable: true    name: mongo001    user: user001    password: "123456"  notPersistent: true  customConfig: mongo-operator-mongo-default-config  resources:    limits:      cpu: "1"      memory: 512Mi    requests:      cpu: "1"      memory: 512Mi  storage: 1Gi  backUpStorage: 1Gi  storageClassName: "nfs"  metricsExporterSpec:    enable: true    resources:      limits:        cpu: "0.1"        memory: 128Mi      requests:        cpu: "0.1"        memory: 128Mi---apiVersion: mongo.daocloud.io/v1alpha1kind: MongoBackUpmetadata:  name: mongobackup-samplespec:  backUpInstance: mongodb-test  backUpNode: mongodb-test-standalone-0-0  storages: mongo-operator-s3
  • 副本集部署/备份/主从切换

apiVersion: mongo.daocloud.io/v1alpha1kind: MongoDBmetadata:  name: mongodb-testspec:  image: daocloud.io/atsctoo/mongo:3.6  type: ReplicaSet  members: 3  service: mongodb-test-svc  rootPassword: "123456"  dbUserSpec:    enable: true    name: mongo001    user: user001    password: "123456"  arbiter: false  notPersistent: false  customConfig: mongo-operator-mongo-default-config  exportConnect: true  resources:    limits:      cpu: "1"      memory: 512Mi    requests:      cpu: "1"      memory: 512Mi  storage: 1Gi  backUpStorage: 1Gi  storageClassName: ""   # 存储类型 为空时,表示使用默认  metricsExporterSpec:    enable: true    resources:      limits:        cpu: "0.1"        memory: 128Mi      requests:        cpu: "0.1"        memory: 128Mi---apiVersion: mongo.daocloud.io/v1alpha1kind: MongoBackUpmetadata:  name: mongobackup-samplespec:  backUpInstance: mongodb-test  backUpNode: mongodb-test-replset-0-0  storages: mongo-operator-s3---apiVersion: mongo.daocloud.io/v1alpha1kind: MongoChannelmetadata:  name: mongochannel-samplespec:  changeMasterTo: 'mongdb-test-replset-0-2.dce.dsp.ats.io:35966'  instance: mongodb-test
  • 分片部署/备份

apiVersion: mongo.daocloud.io/v1alpha1kind: MongoDBmetadata:  name: mongodb-testspec:  image: daocloud.io/atsctoo/mongo:3.6  type: ShardedCluster  service: mongodb-test-svc  shardCount: 2  mongodsPerShardCount: 3  configServerCount: 3  mongosCount: 2  rootPassword: "123456"  dbUserSpec:    enable: true    name: mongo001    user: user001    password: "123456"  arbiter: true  notPersistent: true  customConfig: mongo-operator-mongo-default-config  resources:    limits:      cpu: "1"      memory: 512Mi    requests:      cpu: "1"      memory: 512Mi  storage: 1Gi  backUpStorage: 1Gi  storageClassName: ""   # 存储类型 为空时,表示使用默认  metricsExporterSpec:    enable: true    resources:      limits:        cpu: "0.1"        memory: 128Mi      requests:        cpu: "0.1"        memory: 128Mi---apiVersion: mongo.daocloud.io/v1alpha1kind: MongoBackUpmetadata:  name: mongobackup-samplespec:  backUpInstance: mongodb-test  backUpNode: mongodb-test-replset-0-0  storages: mongo-operator-s3

5.3 监控图表

06

总结

以上介绍了基于 K8s Operator 模式之上的 MongoDB Operator,MongoDB Operator 简化了 MongoDB 的部署、监控以及运维操作,它提供了在云上根据自主需求创建/更新/配置 MongoDB 服务、备份等功能,提升了用户对中间件 MongoDB 的管理能力。


 本文作者 

宋文杰

「DaoCloud 道客」Python研发工程师


猜你喜欢

转载自blog.csdn.net/DaoCloud_daoke/article/details/127675550