云原生中间件 -- MongoDB Operator 篇

133 阅读14分钟

图片

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


01

MongoDB 介绍

1.1 MongoDB 是什么?

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

  • 高性能

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 的实例集合,维护着相同的数据集,主要包含三类节点角色,如下图:

图片

图片来源:mongodb.net.cn/Upload/repl…

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 三个组件组成。

图片图片来源:mongodb.net.cn/manual/shar… 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研发工程师