随着云计算和数据库技术的快速发展,高效且低成本地管理数据库集群变得愈发重要。在本次分享中,我们希望能够为大家提供一些有价值的见解和实用的解决方案,帮助大家更好地应对这一挑战。
我是来自 KubeBlocks 的珊珊,ApeCloud 是开发 KubeBlocks 的创业公司。在加入 ApeCloud 之前,我在阿里云的数据库事业部工作多年,专注于 SQL 优化和执行开发。我的搭档丁顺是移动云的系统架构师,同时他也是 KubeBlocks 的贡献者。他在今年年初给 KubeBlocks 贡献了代码,随后,他将移动云某自研数据库以 addon 的形式集成到 KubeBlocks。
今天,我将介绍 KubeBlocks 及其设计理念,丁顺将分享移动云为何选择 KubeBlocks,KubeBlocks 如何帮助他们减少工作量,以及未来的合作规划。本次分享不会涉及 API 细节或具体的数据库技术。
KubeBlocks 的诞生及设计
如何在 K8s 上管理多种数据库?
我们发起 KubeBlocks 项目的初衷很简单:如何更高效地管理多种数据库。我们团队成员有很强的数据库和 K8s 技术背景,有数据库开发者、DBA、SRE 等。我们每天都会处理上百个云数据库问题,从数据库崩溃(crash)、慢查询、高可用到数据迁移、资源调度等等。
我们团队最特别之处是:我们各自专攻不同的数据库,比如 MySQL、PostgreSQL、Redis、MongoDB 等等广泛使用的开源数据库。我们经常会讨论如何管理某个数据库,在这样的讨论中,我们发现这些数据库有许多共同点。如果我们能够优化其中一种数据库的管理,那么其他数据库是否也可以从中获益呢?此外,数据库进入了快速增长的时代,新的数据库产品层出不穷。而这些新的数据库在一定程度上也继承了共同特征。
所以,我们面对的挑战是,是否有可能设计一个统一的平台,这个平台能够支持管理不止一个,而是一系列数据库,甚至支持管理新兴的数据库?如果有这样一个平台,我们还希望该平台能够支持部署在不同的基础设施上。
因此,Kubernetes 成为我们的选择。Kubernetes 已经成为容器编排的事实标准,它可以将该统一平台带到任何有 Kubernetes 的地方,不论是公有云、私有云,还是边缘云。
对于“在 Kubernetes 上管理数据库”的问题,答案很简单,那就是开发一个 Operator。那么如何在 K8s 上管理“各种数据库”呢?
我们先来聊聊“管理”究竟指的是什么。当我们谈论“管理数据库”时,通常是指以下几项内容:
创建、伸缩(水平伸缩或者垂直伸缩)、备份和恢复、配置(尤其是参数配置)、版本升级、卷扩容以及监控。
要开发一个涵盖所有这些功能的专用 Operator,需要一个由数据库专家和云原生专家组成的团队,投入数月时间,更重要的是,还需要大量用户验证。用户越多,Operator 就越成熟。这是一个具有挑战性的任务,并不是每个数据库团队都能负担得起。所以我们可以看到,Operator 成熟度水平各异。
与 Kubernetes 相比,在我看来,数据库是一个相对小众的领域。我们能否找到一种方法,快速将数据库专家的知识转化为生产力,也就是说将其转化为代码,让越来越多的数据库能够轻松地运行在 Kubernetes 上?
我们以备份恢复为例来说明一下。备份恢复对灾难恢复至关重要,先来回顾一下经典的备份恢复流程:
- 备份方法:通常有一种或多种备份方法,可用于全量备份和持续的归档日志。为了进行全量备份,可以使用数据库专用备份工具,或者简单地执行卷快照。
- 备份调度:需要配置备份调度器,定期触发备份操作,比如每小时、每天、每周或在用户指定的时间进行备份。
- 备份存储库:用于存储备份数据,并保留一定的时间。备份存储库可以是本地的 PV(持久卷),也可以是对象存储,比如 S3、OSS,或者在测试环境中使用的 MinIO。
- 恢复:当需要从备份中恢复数据库集群时,必须设置恢复数据的流程,并决定是在 Pod 运行之前还是之后恢复数据。
在整个流程中,我们发现数据库专家的工作实际上是相当专注但有限的,包含了:
- 如何使用数据库专用的备份工具;
- 如何设置归档日志;
- 以及如何配置恢复命令(如果需要的话)。
而上面列出的其他任务可以交给云原生专家来处理。云原生专家负责开发框架来支持整个流程,不同类型数据库的专家可以复用该框架,或者适配同一数据库的不同版本。
KubeBlocks 的抽象与架构设计
带着这些想法,KubeBlocks 应运而生。KubeBlocks 是一个开源且云中立的项目。它于去年六月开源,截至目前已有约 2000 颗 star。KubeBlocks 是一个与数据库类型无关的 Operator,它具有可扩展性、灵活性和可插拔性。
KubeBlocks 的可扩展性来源于其统一的 API。KubeBlocks 提供了 addon 机制,用于集成数据库引擎。这正是中国移动云能够在两个月内将其自研和开源的数据库集成到 KubeBlocks 中的关键所在。目前,我们已有大约 35 个 addon,其中大部分是由社区用户根据其自身需求贡献的。
KubeBlocks 的灵活性体现在其灵活的集群拓扑结构上。用户可以自定义集群拓扑,每个组件都来自 addon 市场。
KubeBlocks 具有可插拔性,其模块化设计使得备份恢复、监控、配置等模块都可插拔。用户可以根据具体需求选择使用哪些模块。
如果您对 KubeBlocks 感兴趣,可以到我们的 GitHub 仓库,获取更多技术细节和文档,以及我们已有的完整数据库 addon 列表。
所有这些特性都得益于我们对数据库进行了精确而简洁的建模,这一点从数据库的视角来看尤为重要。主要有以下三步。
第一步,分层模型。
我们首先将每个独立的数据库系统或服务建模为一个组件(component),比如一个 MySQL 组件,用于提供 MySQL 服务,以及一个 orchestrator,用于管理 MySQL 的高可用性和数据复制管理。这种建模方式非常直观。
而数据库集群本质上是组件集合,这些组件共同协作,处理特定的数据库任务。例如,一个包含 MySQL 组件和 orchestrator 组件的集群,就可以构建一个高可用的 MySQL 主备集群。此外,您还可以根据自己的喜好,添加任何您偏好的代理组件来自定义集群,比如 HAProxy 或 ProxySQL。
这两层结构非常容易理解。但数据库的特别之处在哪里呢?它不仅是有状态的,更重要的是:它有角色。
我们提供了一种专门为数据库设计的工作负载,称为 InstanceSet,来实现角色感知的数据库管理。
InstanceSet 是对 StatefulSet 的改进,能够按照特定的角色顺序管理数据库,以增强可用性,而不是简单地按数字升序或降序进行管理。InstanceSet 支持具有不同资源和配置的异构副本,并支持指定某个数据库实例下线。指定实例下线常用于主动运维场景,例如当某个副本出错,或者某个节点需要升级时。
第二步,集群模版 API 和集群 API 的分离。
我们注意到,对于只想创建一个集群的数据库用户来说,这仍然过于复杂。
除了四层建模之外,我们还进一步将每一层分解为两个部分:一部分供数据库专家使用,另一部分供数据库用户使用。数据库专家负责处理集群定义(定义拓扑结构)、组件定义(描述引擎特定行为),以及组件版本(描述引擎镜像和兼容性)。而数据库用户只需要了解他们需要的集群和组件,对于每个组件,他们只需关注资源配置,例如 CPU、内存、卷容量和副本数。
第三步,提出了 Database Interface。
随着越来越多的数据库集成到 KubeBlocks 中,我们发现仅仅依靠设置脚本来描述引擎特定行为已经远远不够。
因此,我们提出了一套数据库接口(Database Interface)来管理副本或组件的生命周期,或者在 KubeBlocks 中称为生命周期操作(Lifecycle Actions)。如果没有这些操作,将无法有效地管理数据库。每种操作的具体细节因数据库而异。
我将这些操作分为三类:
- 角色探测(roleProbe)和切换(switchover),用于角色管理;
- 成员加入(memberJoin)和离开组织(memberLeave)、数据转储(dataDump)和加载(dataLoad),用于水平扩展和收缩;
- 组件级管理中的 post-provision 和 pre-termintion 操作;
目前最广泛使用的操作是角色探测(roleProbe)。它会定期触发,检查每个副本的角色,并通过事件或 API 调用将结果报告给 Pod。这样,数据库服务就可以按照预期路由到正确的副本。
随着更多的 addon 加入我们的社区,我们将不断优化和丰富这些操作。
总结一下,KubeBlocks 是一个与数据库类型无关的 Operator。它提供了统一的 API,数据库专家可以通过我们的 addon 机制集成特定的引擎,并仅需关注数据库特定的知识。而数据库用户或管理员则可以使用相同的 API 与不同的数据库进行交互。这大大减少了与数据库管理相关的复杂性和学习曲线。
KubeBlocks 1.0 将在两个月内发布,欢迎加入我们的社区。
扫码添加小助手,进入社区群
移动云使用 KubeBlocks 的实践
我是来自中国移动云的丁顺。我是一名高级系统架构师。很高兴能与大家分享我们如何使用 KubeBlocks 来管理我们的云数据库,而无需编写专用的 Operator。
移动云 DBaaS 系统面对的挑战
在深入讨论技术细节之前,我先介绍一下中国移动云的 DBaaS 系统,这个系统管理着我们所有的云数据库。中国移动云的 DBaaS 系统拥有全面的产品线,涵盖了事务型数据库、分析型和搜索型数据库、NoSQL 数据库等。我们不仅为一些最受欢迎的开源数据库和第三方数据库提供数据库服务,还开发了自研数据库引擎并在其基础上提供服务。目前,我们服务超过 3.5 万个客户,涵盖政府、通信、金融、医疗、教育等 9 大主要行业。
我们的 15 个一级区域和 31 个二级区域运行着超过 13 万个数据库集群实例。除了数据库配置,我们还建立了一个强大的生态系统,帮助客户更高效地管理他们的数据库。我们构建了许多高效的管理工具和系统,如数据迁移、数据库管理控制台,以及具有 AIOps 能力的工具。中国移动云 DBaaS 平台以云原生的方式运行,这意味着我们大部分的数据库实例都运行在 K8s 集群内。
管理如此大规模的数据库实例是一项具有挑战性的任务。虽然我们已经建立了一个可以管理不同类型数据库实例的 DBaaS 系统,但我们仍面临着维护这一 DBaaS 系统的挑战。
目前,我们的 DBaaS 系统大致分为 API 层和 Operator 层,其中 Operator 层是核心部分。
我们的第一个挑战来自于我们为不同的数据库引擎开发了不同的 Operator。但这些 Operator 之间差异很大,比如开发人员无法快速从为引擎 A 开发的 Operator 切换到为引擎 B 开发 Operator,导致了开发资源无法灵活分配。
此外,开发 Operator 对开发人员的要求很高。他们不仅需要了解数据库引擎本身的原理,还需要熟悉整个 Operator 框架。虽然已有一些现成的框架可复用,但这些框架对开发人员仍然有很高的要求,也很难迅速将有生产力的开发人员投入团队。
更重要的是,我们正在开发自己的数据库引擎,并希望能快速为其构建一个 DBaaS 系统。
然而,由于前面提到的诸多挑战,我们无法快速为新的数据库引擎开发 DBaaS 系统。为此,我们需要成立一个既了解我们数据库引擎又了解 Operator 框架的高技能开发团队。然后,这些开发人员必须从头开始编写一个新的 Operator。由于这个数据库引擎是我们内部自主研发的引擎,所以我们无法在市面上找到现成的 Operator。重新编写意味着需要做大量冗余工作。即使这一引擎的某些逻辑与其他数据库引擎的 Operator 非常相似,但我们仍旧无法有效地复用。
因此,我们一直在找寻应对这些挑战的解决方案,如何使不同 Operator 具有类似的接口?如何降低对 DBaaS 系统开发人员的要求?如何快速集成新的数据库引擎?
为什么选择 KubeBlocks
于是我们发现了 KubeBlocks 项目,它能够很好地解决我们的问题。KubeBlocks 是一个专门为数据库工作负载设计的通用 Operator 框架。开发人员为不同的数据库引擎编写 addon,以集成到 KubeBlocks 系统中。这个项目吸引了我们几个特点:
首先,它是一个通用的 Operator 框架。这意味着只需要运行一个 Operator,即可支持不同类型的数据库引擎。开发人员只需维护一个 Operator 和一套 CRD。这使得在 Operator 层共享知识变得容易,可以灵活地分配到不同的数据库引擎团队中。
此外,该框架使用低代码开发模型。不同数据库引擎的集成通过编写不同的 addon 来实现,而不是从头开始编写专用的 Operator。
所用的 addon 只是包含 KubeBlocks 框架中 CR 对象的 Helm charts。开发 addon 时,我们只需要编写所需 CR 对象的 YAML 文件以及一些功能脚本。后面我们会详细介绍这些内容。Addon 中的 CR 对象是以声明性方式定义的。就像其他 Kubernetes 对象一样,开发人员只需描述期望的数据库集群运行状态,KubeBlocks 框架将进行调谐。这种低代码开发模型降低了为新数据库引擎开发 DBaaS 系统的门槛。开发人员只需了解数据库引擎的工作原理,就可以开始开发。
此外,较少的代码意味着潜在的 bug 较少,新数据库引擎的集成速度也加快了。这很好地满足了我们的需求。
更重要的是,KubeBlocks 是一个专门为数据库工作负载设计的通用框架。它有效地覆盖了 Kubernetes 上数据库的所有基本管理操作。例如,KubeBlocks 提供了生命周期管理、备份恢复、配置管理、高可用等功能。
此外,KubeBlocks 还提供了可扩展机制,允许特定数据库引擎管理操作无缝地集成到整体框架中。
基于 KubeBlocks 构建移动云 H-DB addon
经过详细调研,我们决定尝试使用 KubeBlocks。当时,有一个内部开发的数据库引擎需要集成到 DBaaS 系统中,这里我们使用 H-DB 代指该引擎。这是验证 KubeBlocks 在 DBaaS 系统中集成使用的绝佳机会。
首先,我简要介绍一下我们的 H-DB。它是一个自研的云原生分布式数据库引擎,实现了存算分离。通常,为如此复杂的数据库系统编写 Operator 是巨大的挑战,想要快速实现集成更是难上加难。但借助 KubeBlocks,我们可以以低代码的方式实现这一目标。
以下是我们构建 KubeBlocks addon 的过程:
-
设计集群拓扑,并搭建 addon 框架。通常,初始 addon 只包含一个粗略的 ClusterDefinition 框架和一个非常基本的 ClusterVersion,后者指定了所有组件容器的镜像。在我们的案例中,H-DB 集群中有两个组件:计算节点和数据节点。因此,我们定义了一个包含这两个组件的集群定义(Cluster Definition)对象。在 ClusterVersion 中配置了每个组件的镜像,并暂时在 ClusterDefinition 中设置了一个虚拟的启动命令。然后,我们编写一个简单的 Cluster CR 对象进行测试,以确保所有 addon 可以成功安装,Pods 能够成功启动。
-
完善 ClusterDefinition,在 ConfigMap 中设置正确的配置参数,并编写脚本以引导集群启动。我们调整配置和脚本,确保集群能够正常运行。这一步很重要,因为这意味着第一个可用的 addon 已经完成。
-
支持备份和恢复功能。我们需要编写备份和恢复的功能脚本,并将其集成到 KubeBlocks 的 ActionSet CR 对象中。我们可以创建一个备份 OpsRequest 和一个恢复 OpsRequest 来测试这些功能。
-
编写 ConfigConstraint,控制哪些参数可以被修改,是否可以动态配置,以及重新加载(reload)命令。这些配置使 addon 能够修改数据库引擎中的部分配置参数。
-
启用高可用性和角色检测,在我们的数据库集群中添加一些观测边车(sidecar),这些边车将收集数据库实例的指标和日志。
-
最后,我们可以添加更多的 Cluster 版本,以适配不同的内核版本。
至此,我们成功为 H-DB 开发了一个完整的 KubeBlocks addon。通过使用 KubeBlocks,我们在仅两个月内、仅用一个人完成了 H-DB 的第一个 DBaaS 系统。而且,这个过程可以更快,因为后续的 addon 构建步骤可以并行推进。这是中国移动云和 KubeBlocks 的首个集成案例。
以下是开发 KubeBlocks addon 与开发专用 Operator 的总结对比。这里,我们将 KubeBlocks addon 的开发过程与为类似的数据库引擎编写专用 Operator 的开发过程进行比较。
在开发人员资源投入方面,编写 KubeBlocks addon 只需要 2 人月,而为类似产品编写专用的 Operator 则需要大约 6 人月。
H-DB 的案例是一个很好的起点。它证实了我们可以通过使用 KubeBlocks 来解决目前在 DBaaS 系统中面临的问题。
关于未来
下一步,我们计划通过 KubeBlocks 进一步集成更多的数据库引擎,进行深入的评估,并尝试升级到 KubeBlocks 的新版本,评估我们感兴趣的一些功能。
在中国移动云,我们的理想目标是建立一个统一的云原生 DBaaS 平台。在这个平台上,我们旨在实现统一的多云架构、API 和 Operator 层的统一接口,支持不同架构的数据库集群,并且数据库实例可以根据需求部署在无服务器的 Kubernetes 集群上。这将形成一个统一的数据库编排和通用管理平台,支持公共云、私有云、专用云、边缘云等不同基础设施。
随着 KubeBlocks 的不断发展和改进,未来我们将考虑基于 KubeBlocks 框架重构我们现有的 DBaaS 系统。从长远来看,对于不同的数据库引擎,我们预计可以节省大约 50% 的开发资源。