OceanBase开源之夏——收获颇丰的开源实践

笔者目前就读于武汉大学研二,参与了2024年ob社区的开源之夏中适用于ob-operator的命令行工具的研发,笔者的Github账号是@lizzy-0323,欢迎各位一起交流!

前言

今年的七月份,我在常听的播客《开源面对面》中了解到了开源之夏这项活动,了解到活动的持续时间是7-10月,并且可以完整,深入地参与一个社区,这使我非常兴奋。和在实习工作的同学和学长聊天后,他们一致认为,这样的一次经历完全相当于一次高质量的实习,因此我决定了要参与的决心。

当然,非常幸运的是我入选了OceanBase社区的项目,这里也感谢ob-cloud-naive sig的导师和各位成员的帮助,让我能够顺利的参与到这次活动中来。

项目基本信息

项目名称: ob-operator 命令行工具

项目导师: 与义

项目描述: 目前用户管理 ob-operator 中 CRD 的主要方式是直接管理 YAML 配置文件,虽然用户可以使用 Dashboard 进行直观的、图形化的管理,但有些用户为了更高的灵活性倾向于使用命令行进行运维。ob-operator 的用户通常对 Kubernetes 的运维工作有一定的了解,如果能够开发 ob-operator 配套的命令行工具为他们提供必要组件的安装升级,核心 CRD 的编辑和管理以及 OceanBase 集群的简单诊断等功能,将带来较大的便利。

项目链接:  https://summer-ospp.ac.cn/org/prodetail/24f5f0064?list=org&navpage=org

项目实现思路

目前来说ob-operator用户去使用该工具搭建ob集群,主要有两种方式,采用Dashboard部署和采用yaml文件部署。而我要实现的是一个命令行工具,用户可以通过命令行工具来搭建ob集群,这样用户可以更加方便的搭建ob集群。

命令行工具主要的特点是简便,用户可以通过简单的命令来完成复杂的操作,因此大部分配置将会采用默认值的形式写好,用户往往只需要更改极个别的配置即可完成搭建。

通过查看Dashboard部分对集群资源进行管理的代码,可以看到非常清晰的资源创建逻辑:

  1. 前端通过api请求后端,设置表单数据
  2. 后端接收到请求,并调用k8s的client-go中的api进行资源的创建
  3. k8s接收到请求,根据请求的数据创建资源
  4. 前端接收到后端的返回信息,展示给用户

采用命令行工具创建时,实际上我们只需要2和3两个步骤,思路上主要是采用`Cobra`框架去实现,在经过几轮讨论后,我们主要提供以下几种命令:

  • 集群管理: cluster
  • 租户管理: tenant
  • 备份策略管理: backup-policy
  • 组件的安装和升级: install, upgrade
  • 交互式创建单节点集群和多节点集群: demo

这些命令也是用户使用该工具时的主要需求,整体实现上不难,我认为难点主要在于设计上如何让每一个命令的设计都尽量清晰明了,整体的流程遵循一套范式,这样也便于后续的扩展,同时也需要考虑到用户输入的几种不同情况带来的影响(尤其是租户管理部分,可能出现较多的配置情况)。

因此,基于cobra,我定义了这一套命令行处理范式,如下图所示:

1730776810`Parse`主要负责Cobra框架中的PreRunE部分,负责解析用户输入的命令,并解析为相应的结构体,`Complete`主要负责根据用户的输入,补全其他不提供输入的默认值,`Validate`主要负责对资源进行校验,在资源创建请求不合规后,应当立即返回错误给前台,而无需将请求发送到k8s中。最后是`Run`部分,目前还没有完全把所有命令的主要功能都移到这部分,后续会进行重构修改,主要是负责每一个命令的运行操作,最后,请求都会发送给k8s的client-go中的api进行资源的管理。

在开发中的挑战

在开发过程中我也遇到了一些小问题,但好在有老师的沟通和社区的帮助下,我都得以解决。总的来说问题都处于对于ob-operator运行机制和k8s运行机制的不熟悉,作为开发者,除了技术层面,还需要对于整个系统的运行机制和业务逻辑有一个清晰的认识,这样才能更好的进行开发。举一个例子,比如创建租户时,除了要明确租户的概念,还需要明确大概有几种可能存在的场景,例如:

  1. 创建主租户
  2. 创建空备租户(对应from flag)
  3. 创建主租户或备租户用于恢复(对应restore flag)
    这几种实际上是不同的场景,因此需要提供不同的flag来鉴别租户的role,并加以一系列校验逻辑。

由于我的机器配置较低,在配置环境和部署集群时,也遇到了一些小问题,比如在创建集群时把内存大小设置为10Gi,租户的`unitconfig`中的memory设置为5Gi,理论上这里是可以创建的,但实际上仍旧是无法创建,这是由于OB在没有创建任何租户的情况下也会占用不少的内存(系统租户等),因此,最终剩余的空间其实是不足5Gi需要在集群定义时加入 system_memory__min_full_resource_pool_memory这两个参数配置传递进去,在对于小型机器创建集群时是非常必要的,这个问题也是我在查找OB官方文档,尝试解决无果之后,和老师讨论得到的结果。 因此遇事不决先多看文档,然后学会提问是非常重要的 : )对于k8s的运行机制可以查看这篇文章 what-happens-when-k8s ps:此处感谢与义老师。

为什么选择OceanBase

在开发的过程中,我遇到了一些OB中常见的概念,这过程中我去官网中查阅文档和博客,大致的了解了这款数据库,同时思考其中的设计理念,OceanBase是一个非常庞大的数据库,在这里我只谈一谈我对于一些概念的浅薄理解,写的不好的地方还请多多指正。

对一个分布式系统了解并不多的人而言,我们简单的去想如何实现分布式数据库,大概就是一个采用分片策略,将一个大表的数据分散存储到多个数据库服务器上的设计(这里的分片通常是水平分片),同时采用一致性哈希算法等来管理数据的分布和路由,等等。

然而,真正的分布式数据库系统远不止如此,它需要考虑数据复制、事务管理、故障恢复、数据一致性保证等多个方面。一个分布式数据库系统的目标之一是提供一个统一的接口给用户,使得用户可以像操作单一数据库一样操作分布在多个节点上的数据,并且必须保证 高可用性,当部分节点失败时,应该能够保证系统的正常运行。

不同于其他分布式数据库的设计,OceanBase采用 Share-Nothing的架构,没有任何共享存储结构。这意味着每个节点都是完全对等的,各自拥有 SQL 引擎和存储引擎,采用负载均衡策略将数据分片到多个observer上,每一个observer就是一个节点,节点间通过网络通信。

另外,OceanBase还采用 多租户隔离的结构,租户是逻辑概念,也是OceanBase数据库中的核心,从用户的角度而言,相当于一个数据库实例,租户之间的资源是完全隔离的,这就做到了可以在同一套物理资源上部署和管理多个独立的数据库实例,同时这种设计也使得它天然支持 云数据库架构。总的来说,可以理解为每一个节点有一个observer进程,为租户完成资源分配,租户是逻辑概念,而集群是部署层面的物理概念,是zone和节点的租户,zone是逻辑概念,代表着一批相似硬件可用性的节点,针对不同使用场景有不同的意义。不得不说实现一个分布式数据库要考虑的问题很多,但OB将设计抽象为租户、zone、observer等概念,使得用户可以更加方便的管理和使用数据库,无论是对于企业开发还是学生阶段的学习了解来说,都是非常有意义的。此外,OB的社区也是非常活跃的,有很多的博客和文档,我在完成实验室的一些工作时也使用到了OB,在社区中提ISSUE和PR,回复都非常及时,大大的提升了我的参与感,因此我非常建议大家在学习和工作中尝试使用OB。

为什么选择ob-operator

关于这部分我有很大感悟,这是因为,在完成实验室的科研任务时,我曾经部署过单节点和三节点的OB,虽说文档已经非常详细,但还是需要消耗一些时间,如果是更大规模的部署,可能对运维人员的要求会更高。因此更加觉得目前ob-operator的开发是非常有意义的。

ob-operator采用Kubernetes Operator框架搭建,部署集群实际上只需要在集群中部署ob-operator后,采用yaml文件,dashboard,cli(in the future)三种方式就可以即为简便的部署ob集群,并以最快速度投入生产中。ob-operator的架构也非常清晰巧妙,和kubebuilder的架构类似,主要采用controller来对特定的资源进行响应,依据实现好的逻辑将资源的实际状态(Status)和期望状态(Spec)对齐;并采用Webhook实现了设定默认值和进行资源规约校验两部分功能。

由于OB相关的工作流涉及到一系列长调度操作,因此k8s的 Operator 模式(单一解调worker机制)往往是不适合的,因此ob-operator非常巧妙的采用了任务流和全局任务管理器,任务流包含了当前执行的任务索引和任务状态,可以通过查看 obcluster_flow.go等文件了解到每一个资源的所创建的任务流对应的任务列表,通过 obcluster_task.go了解每个任务具体的操作流程,其他资源同理。同时,全局任务管理器中也包含了工作集映射和结果缓存映射,可以查看 task_manager.go来了解。

总的来说,通过k8s提供的极强的抽象能力,使得资源的管理对用户的透明度更高,也更为简便,因此非常希望大家如果有兴趣可以尝试使用一下ob-operator,也可以参与到ob-operator的开发中来!!

收获与感悟

在本次开发中,最大的提升就是对于k8s的理解,如k8s的资源管理和控制器的设计有了更深入的了解,同时,自己对于资源的检查等命令也变得更加熟练,在遇到问题时往往很快能通过查看资源对应的状态和pod对应的日志来很快的解决问题。另外,在项目的开发中,我也学到了很多工程上的知识,比如对于git尤其是git rebase等命令使用更加规范,以及CI/CD自动化部署,版本号注入等流程等。

在每一次提交PR后,老师们都会对代码的可读性和架构的规范性提出建议,这也使得我在代码的规范上有了更高要求。在日常的科研过程里,我也用到了OB,这段经历加深了我对OB的理解,也使得我在ob-operator的开发中更加有动力。

另外,在全文的最后,还是想 感谢一下与义老师,由于我在实验室的工作,很多时候都要利用周末的时间,和工作日晚上的时间进行开发,很多次都是一直做到深夜,但与义几乎都会很快给予我回复,并且在我遇到问题时给予我很多的帮助,除此以外,还对整个计算机技术的学习,职业发展等都给予了很多指导,这是我回想起来都非常难得的一段经历( 下图为一次讨论后的赛博合影一张)

1730776506最后,希望大家也积极的参与到开源中来!多多关注 OB社区 !


请使用浏览器的分享功能分享到微信等