当前位置: 代码迷 >> 综合 >> 容器化 | ClickHouse Operator 原理解析
  详细解决方案

容器化 | ClickHouse Operator 原理解析

热度:0   发布时间:2023-12-06 15:15:41.0

作者:苏厚镇 青云科技数据库研究工程师

从事 RadonDB ClickHouse 相关工作,热衷于研究数据库内核。

通过《ClickHouse on K8s 部署篇》,对比了 RadonDB ClickHouse 集群在 Kubernetes 中部署的几种方案,表明使用 Operator 进行部署和管理是最方便快捷的。

那么到底什么才是 Operator,Operator 又是如何与 Kubernetes 进行协同工作的,Operator 的代码逻辑又是怎样的?本篇将基于 Operator 基本概念和源代码解析,深度解析 ClickHouse Operator 运行原理。

什么是 Operator?

在 Kubernetes 官方文档[1]中,对 Operator 的定义如下:

Operators are software extensions to Kubernetes that make use of custom resources to manage applications and their components. Operators follow Kubernetes principles, notably the control loop.

简单来说:Operator = 定制资源 + 控制器。

那么定制资源和控制器又是什么呢?

定制资源

在 Kubernetes 官方文档[1]中,对定制资源的定义如下:

Custom resources are extensions of the Kubernetes API.
It represents a customization of a particular Kubernetes installation.

Kubernetes 提供了一系列的资源,包括 Statefulset、Service、Configmap 等。但是这些资源并不能完全满足使用需求,例如在 K8s 中部署 ClickHouse 应用时,需定制一个 ClickHouse 应用资源。

Kubernetes 提供了两种方式向集群中添加定制资源:

  • CRD:无需编程。K8s 从 1.7 版本增加了 CRD 来扩展 API,通过 CRD 可以向 API 中增加新资源类型,无需修改 K8s 源码或创建自定义的 API server,该功能大大提高了 Kubernetes 的扩展能力。
  • API 聚合:需要编程。但支持对 API 行为进行更多的控制,例如数据如何存储以及在不同 API 版本间如何转换等。

ClickHouse Operator 在定制资源方面,选用了 CRD 方式添加定制资源。

但是使用 CRD 定制资源后,仅仅是让 Kubernetes 能够识别定制资源的身份。创建定制资源实例后,Kubernetes 只会将创建的实例存储到数据库中,并不会触发任何业务逻辑。在 ClickHouse 数据库保存定制资源实例是没有意义的,如果需要进行业务逻辑控制,就需要创建控制器

控制器

Controller 的作用就是监听指定对象的新增、删除、修改等变化,并针对这些变化做出相应的响应,关于 Controller 的详细设计,可以参考 Harry (Lei) Zhang 老师在 twitter 上的分享,基本架构图如下:

file

从图中可看出,定制资源实例的变化会通过 Informer 存入 WorkQueue,之后 Controller 会消费 WorkQueue,并对其中的数据做出业务响应。

Operator 其实就是图中除了 API Server 和 etcd 的剩余部分。由于 Client、Informer 和 WorkQueue 是高度相似的,所以有很多项目可以自动化生成 Controller 之外的业务逻辑(如 Client、Informer、Lister),因此用户只需要专注于 Controller 中的业务逻辑即可。

ClickHouse Operator 代码解析

代码结构

.
├── cmd         # metrics_exporter 和 operator 的入口函数
│   ├── metrics_exporter
│   └── operator
├── config      # ClickHouse 和 ClickHouse Operator 的配置文件,会通过 ConfigMap 挂载到 pod
├── deploy      # 各类组件的部署脚本和部署 yaml 文件
│   ├── dev         # clickhouse operator 开发版本安装部署
│   ├── grafana     # grafana 监控面板安装部署
│   ├── operator    # clickhouse operator 安装部署
│   ├── operator-web-installer
│   ├── prometheus  # prometheus 监控部署
│   └── zookeeper   # zookeeper 安装部署
├── dev         # 各类脚本,如镜像生成、应用构建、应用启动等
├── dockerfile  # 镜像 dockerfile
├── docs        # 文档
├── grafana-dashboard
├── hack
├── pkg         # 代码逻辑
│   ├── announcer   # 通知器
│   ├── apis        # api, 定制资源类型
│   │   ├── clickhouse.radondb.com
│   │   └── metrics
│   ├── chop        # clickhouse operator 类型
│   ├── client      # 自动生成,作用参考上面的图
│   │   ├── clientset
│   │   ├── informers
│   │   └── listers
│   ├── controller  # controller 逻辑,主要关心部分
│   ├── model       # controller 调用 model
│   ├── util        # util
│   └── version     # version 信息
└── tests       # 自动测试代码

代码逻辑

以下代码均为简化版,仅取核心逻辑部分。

Controller 中主要的工作逻辑存在于 Worker 中。

Run

Run 是 Worker 中整个工作逻辑入口。Run 是一个无休止的工作循环,期望在一个线程中运行。

func (w *worker) run() {
    ...for {
    // 消费 workqueue,该方法会阻塞,直到它可以返回一个项目item
  相关解决方案