跳到主要内容

概念

"统一 API 如何降低学习曲线"一节介绍了使用统一 API 表达各种数据库的优势。如果仔细查看这些示例,您会发现示例 YAML 文件中包含两个关键概念:Cluster(集群)Component(组件)。例如,test-mysql 是一个包含名为 mysql 组件的集群(组件定义为 apecloud-mysql)。test-redis 也是一个集群,包含两个组件:一个是 redis(组件定义为 redis-7),有两个副本;另一个是 redis-sentinel(组件定义为 redis-sentinel),有三个副本。

本文档将解释这两个概念背后的原因,并简要介绍其背后的 API(即 CRD, Custom Resource Definition)。

KubeBlocks 分层 API 的设计动机

在 KubeBlocks 中,为了通过统一 API 支持各种数据库的管理,我们需要抽象不同数据库的拓扑结构和特性。

我们观察到,生产环境中部署的数据库系统通常采用由多个组件组成的拓扑结构。例如,一个生产环境中的 MySQL 集群可能包括多个代理节点(如 ProxySQL、MaxScale、Vitess、WeScale 等)和多个 MySQL 服务器节点(如 MySQL 社区版、Percona、MariaDB、ApeCloud MySQL 等),以实现高可用性和读写分离。类似地,Redis 部署通常由一个主节点和多个只读副本组成,并通过 Sentinel 管理以确保高可用性。一些用户甚至使用 twemproxy 进行水平分片,以实现更大的容量和吞吐量。

这种模块化方法在分布式数据库系统中尤为常见,整个系统被划分为职责明确的独立组件,如数据存储、查询处理、事务管理、日志记录和元数据管理等。这些组件通过网络进行交互,确保系统能够像单节点数据库一样提供强一致性和事务保障,并实现负载均衡、分布式事务以及具备故障切换能力的灾难恢复等复杂操作。

因此,KubeBlocks 采用了分层 API(即 CRD)的设计,由 Cluster(集群)Component(组件) 组成,以适应数据库系统的多组件、高度可变的部署拓扑结构。这些抽象允许我们灵活地表达和管理部署在 Kubernetes 上的各种数据库系统拓扑,并根据所需拓扑轻松地将组件组装成集群。

组件是组成集群的积木块。事实上,数据库引擎插件开发者可以在 ClusterDefinition 中定义如何将多个组件组装成不同的拓扑结构。如果您只是普通用户,则无需过度关注 ClusterDefinition 的细节;您只需要知道 KubeBlocks 的插件可以提供不同的拓扑结构选择。例如,Redis 引擎插件支持三种拓扑:"standalone"(单机),"replication"(主从复制)和 "replication-twemproxy"(主从复制 + twemproxy)。您可以在创建集群时指定所需的拓扑。

以下是通过 clusterDefinitionReftopology 创建 Redis 集群的示例:

apiVersion: apps.kubeblocks.io/v1alpha1
kind: Cluster
metadata:
name: test-redis-use-topology
namespace: default
spec:
clusterDefinitionRef: redis
topology: replication
terminationPolicy: Delete
componentSpecs:
- name: redis
replicas: 2
disableExporter: true
resources:
limits:
cpu: '0.5'
memory: 0.5Gi
requests:
cpu: '0.5'
memory: 0.5Gi
volumeClaimTemplates:
- name: data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
- name: redis-sentinel
replicas: 3
resources:
limits:
cpu: '0.5'
memory: 0.5Gi
requests:
cpu: '0.5'
memory: 0.5Gi
volumeClaimTemplates:
- name: data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi

仔细看上面这个 YAML 文件,可以发现,通过在集群中指定 clusterDefinitionReftopology,则无需再为每个组件指定 componentDef

借助 Component API,KubeBlocks 将数据库容器打包成标准化的积木块,这些积木块可以根据指定的拓扑组装成数据库集群,并运行在 Kubernetes 上。我们认为这个过程很像用乐高积木搭建东西,这也是 KubeBlocks 这一名字的来源。

深入了解 KubeBlocks API

下图展示了 KubeBlocks 的主要 CRD,这里特别强调了 API 的分层结构。其他重要的 API,如 OpsRequest、Backup 和 Restore,并未包含在此图中。下图重点关注分层结构,图表展示更加清晰。我们将在其他文档中解释其他重要的 API。

KubeBlocks API Layers

KubeBlocks 的 CRD 可分为两大类:用户使用的 CRD 和 插件 CRD。

用户使用的 CRD

用户使用的 CRD 包括 Cluster、Component 和 InstanceSet。使用 KubeBlocks 创建数据库集群时,将生成以下 CR:

  • Cluster 对象:由用户创建。
  • Component 对象:KubeBlocks 集群控制器(Cluster Controller)在检测到 Cluster 对象时递归创建的子资源。
  • InstanceSet 对象:KubeBlocks 组件控制器(Component Controller)在检测到 Component 对象时递归创建的子资源。InstanceSet 控制器(InstanceSet Controller)随后递归创建 Pod 和 PVC 对象。

插件 CRD

插件使用的 CRD 包括 ClusterDefinition、ComponentDefinition 和 ComponentVersion。这些 CR 由数据库引擎插件开发者编写,并捆绑在插件的 Helm chart 中。

备注

您无需编写 ClusterDefinition 和 ComponentDefinition 的 CR,但仍需要使用这些 CR。如前面创建 Redis Cluster 所示,创建集群时,可以选择在每个组件的 componentDef 中指定相应的 ComponentDefinition CR 名称,或者在 clusterDefinitionRef 中指定相应的 ClusterDefinition CR 名称,并选择所需的拓扑结构。

用户使用的 KubeBlocks API

Cluster

Cluster 对象表示由 KubeBlocks 管理的整个数据库集群。一个集群可以包含多个 Component,用户在 Cluster API 中指定每个 Component 的配置,集群控制器将生成并调谐相应的 Component 对象。此外,集群控制器还管理在集群层暴露的所有服务地址。

对于像 Redis Cluster 这种采用无共享架构的分布式数据库,集群对象支持管理多个分片(shard),每个分片由一个单独的 Component 管理。这种架构还支持动态分片(dynamic resharding):如果需要扩展并添加新分片,只需添加一个新的 Component;反之,如果需要缩减分片数量,则移除相应的 Component。

Component

Component 是集群对象的基本模块。例如,一个 Redis 集群可以包含 redis、sentinel,也可能包含代理组件,如 twemproxy。

Component 对象负责管理 Component 内所有副本的生命周期,支持多种操作,包括实例的创建、停止、重启、终止、升级、配置变更、垂直和水平扩展、故障切换、主备切换、调度配置、服务暴露、系统账号管理等。

Component 是从用户提交的 Cluster 对象派生的内部子对象,主要供 KubeBlocks 控制器使用,不建议用户直接修改 Component 对象,应仅用于监控 Component 状态。

InstanceSet

从 KubeBlocks v0.9 开始,KubeBlocks 用 InstanceSet 替代 StatefulSet。

一个数据库实例(或副本)由一个 Pod 和其他辅助对象(如 PVC、Service、ConfigMap、Secret)组成。InstanceSet 是一个负责管理实例组的工作负载 CRD。在 KubeBlocks 中,所有工作负载最终都由 InstanceSet 管理。与 Kubernetes 原生的工作负载 CRD(如 StatefulSet 和 Deployment)相比,InstanceSet 融入了更多针对数据库领域的设计和考量,例如每个副本的角色、高可用性需求,以及对特定节点进行下线等操作的支持。

KubeBlocks Addon API

备注

只有引擎插件开发者需要了解 ClusterDefinition 和 ComponentDefinition API,普通用户可以跳过这部分内容。

ClusterDefinition

ClusterDefinition 是用于定义数据库集群所有可用拓扑的 API,提供了多种拓扑配置以满足不同的部署需求和场景。

每个拓扑都包含一个组件列表,每个组件都关联到一个 ComponentDefinition,提升了复用性并减少了冗余。例如,常用组件如 etcd 和 ZooKeeper 的 ComponentDefinition 可以只定义一次,实现在多个 ClusterDefinition 中复用,从而简化新系统的设置。

此外,ClusterDefinition 还指定了组件的启动、升级和关闭顺序,确保组件生命周期的可控管理。

ComponentDefinition

ComponentDefinition 是用于创建组件的可复用蓝图或模板,封装了组件描述、Pod 模板、配置文件模板、脚本、参数列表、环境变量及其来源、事件处理程序等必要的静态设置。ComponentDefinition 与 Component 的动态设置结合,在创建集群时实例化组件。

ComponentDefinition 可以定义的关键内容包括:

  • PodSpec 模板:指定组件使用的 PodSpec 模板。
  • 配置模板:指定组件所需的配置文件模板。
  • 脚本:提供管理组件所需的脚本。
  • 存储卷:指定组件的存储卷及其配置。
  • Pod 角色:定义组件内 Pod 的各种角色及其能力。
  • 暴露的 Kubernetes 服务:指定组件需要暴露的服务。
  • 系统账户:定义组件所需的系统账户。

ComponentDefinition 还支持定义组件对事件的响应行为,例如成员加入/离开、组件添加/删除、角色变更、切换等。这使得可以自动处理事件,从而封装组件的复杂行为。

插件(Addon)是什么

KubeBlocks 使用插件(Addon)机制来扩展对不同数据库引擎的支持。插件是某个特定数据库引擎的扩展,例如 MySQL Addon、PostgreSQL Addon、Redis Addon、MongoDB Addon 和 Kafka Addon。目前 KubeBlocks 提供了超过 30 种数据库引擎插件。

一个引擎插件包含基于 ClusterDefinition、ComponentDefinition 和 ComponentVersion CRD 的自定义资源(CR),以及一些 ConfigMap(用作配置模板或脚本文件模板)、脚本文件、定义备份和恢复操作的自定义资源和 Grafana 仪表板 JSON 对象。

KubeBlocks 的引擎插件将以 Helm chart 的形式打包和安装。用户安装某个数据库引擎插件后,可以在创建集群时引用该插件中包含的 ClusterDefinition CR 和 ComponentDefinition CR,从而创建相应数据库引擎的集群。