Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

该报告专门讨论了在 Kubernetes 中开发算子、设计其架构和基本操作原理的实际问题。

在报告的第一部分,我们将考虑:

  • Kubernetes 中的操作符是什么以及为什么需要它;
  • 操作员究竟如何简化复杂系统的管理;
  • 操作员可以做什么和不能做什么。

接下来我们继续讨论算子的内部结构。 下面我们一步步看一下算子的架构和操作。 让我们详细看看:

  • 运营商与 Kubernetes 之间的交互;
  • Operator 承担哪些职能以及将哪些职能委托给 Kubernetes。

让我们看看在 Kubernetes 中管理分片和数据库副本。
接下来我们讨论一下数据存储问题:

  • 从操作员的角度如何使用持久存储;
  • 使用本地存储的陷阱。

在报告的最后部分,我们将考虑实际的应用示例 clickhouse-操作员 与亚马逊或谷歌云服务。 该报告以ClickHouse运营商的开发和运营经验为例。

视频:

我的名字是弗拉迪斯拉夫·克里门科。 今天我想讲一下我们开发和运营一个算子的经验,这是一个专门用于管理数据库集群的算子。 例如 ClickHouse 操作员 管理 ClickHouse 集群。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

为什么我们有机会来谈谈算子和ClickHouse?

  • 我们支持并开发ClickHouse。
  • 目前,我们正在努力慢慢为ClickHouse的发展做出自己的贡献。 就 ClickHouse 的更改量而言,我们位居第二,仅次于 Yandex。
  • 我们正在尝试为 ClickHouse 生态系统创建更多项目。

我想向您介绍其中一个项目。 这是关于 Kubernetes 的 ClickHouse-operator。

在我的报告中,我想谈两个主题:

  • 第一个主题是我们的 ClickHouse 数据库管理操作器如何在 Kubernetes 中工作。
  • 第二个主题是 Operator 如何工作,即它如何与 Kubernetes 交互。

然而,这两个问题将贯穿我的报告。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

谁有兴趣听听我想讲述的内容?

  • 这将是那些运营运营商的人最感兴趣的。
  • 或者对于那些想要自己制作的人来说,以了解它的内部工作原理、操作员如何与 Kubernetes 交互以及可能出现的陷阱。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

为了更好地理解我们今天要讨论的内容,最好了解 Kubernetes 的工作原理并进行一些基本的云培训。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

什么是ClickHouse? 这是一个列式数据库,具有用于在线处理分析查询的特定功能。 而且它是完全开源的。

对我们来说,重要的是只知道两件事。 你需要知道这是一个数据库,所以我将告诉你的内容几乎适用于任何数据库。 事实上,ClickHouse DBMS 的扩展性非常好,提供了几乎线性的可扩展性。 因此,集群状态是 ClickHouse 的自然状态。 我们最感兴趣的是讨论如何在 Kubernetes 中为 ClickHouse 集群提供服务。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

那里为什么需要他? 为什么我们不能继续自己经营呢? 答案部分是技术性的,部分是组织性的。

  • 在实践中,我们越来越多地遇到这样的情况:在大公司中,几乎所有组件都已经在 Kubernetes 中了。 数据库保留在外部。
  • 越来越多的人提出这样的问题:“这个可以放在里面吗?” 因此,大公司都在努力实现管理的最大程度的统一,以便能够快速地管理他们的数据仓库。
  • 如果您需要最大的机会在新的地方重复相同的事情,即最大的可移植性,这尤其有帮助。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

它有多容易或多困难? 当然,这可以手工完成。 但事情并没有那么简单,因为我们增加了管理 Kubernetes 本身的复杂性,但同时又叠加了 ClickHouse 的细节。 这样的聚合结果。

所有这些都提供了相当大的技术集,这变得非常难以管理,因为 Kubernetes 将其自己的日常问题带入操作中,而 ClickHouse 将其自己的问题带入日常操作中。 特别是如果我们有多个 ClickHouse,并且我们需要不断地用它们做一些事情。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

通过动态配置,ClickHouse 存在相当多的问题,这些问题会给 DevOps 带来持续的负载:

  • 当我们想要更改 ClickHouse 中的某些内容(例如添加副本或分片)时,我们需要管理配置。
  • 然后更改数据架构,因为ClickHouse有特定的分片方法。 您需要在那里布置数据图,布置配置。
  • 您需要设置监控。
  • 收集新分片、新副本的日志。
  • 注意恢复。
  • 并重新启动。

这些都是日常任务,我非常希望使其更易于使用。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

Kubernetes 本身在操作方面有很好的帮助,但在基本的系统方面。

Kubernetes 擅长促进和自动化以下事情:

  • 恢复。
  • 重新开始。
  • 存储系统管理。

很好,方向是对的,但是他完全不知道如何操作数据库集群。

我们想要更多,我们希望整个数据库都能在 Kubernetes 中运行。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

我想要一个像一个大的神奇红色按钮这样的东西,您可以按下它,并在整个生命周期中部署和维护需要解决的日常任务的集群。 Kubernetes 中的 ClickHouse 集群。

我们试图制定一个解决方案,让工作变得更轻松。 这是 Altinity 的 Kubernetes 的 ClickHouse 运算符。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

操作员是一个程序,其主要任务是管理其他程序,即它是一个管理器。

它包含行为模式。 您可以将其称为有关该主题领域的编纂知识。

他的主要任务是让DevOps的生活变得更轻松,减少微观管理,让他(DevOps)已经在高层思考,也就是说,让他(DevOps)不从事微观管理,让他不配置所有细节都是手动的。

而操作员只是一个机器人助手,负责处理微任务并帮助 DevOps。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

为什么需要操作员? 他在两个方面表现尤其出色:

  • 当处理ClickHouse的专家没有足够的经验,但已经需要操作ClickHouse时,运维人员会方便操作,允许您操作一个配置相当复杂的ClickHouse集群,而无需过多详细说明它是如何工作的里面。 你只要给他布置高层次的任务,它就会起作用。
  • 它表现最好的第二个任务是当需要自动化大量典型任务时。 从系统管理员中删除微任务。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

对于那些刚刚开始他们的旅程的人,或者那些需要进行大量自动化的人来说,这是最需要的。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

基于操作员的方法与其他系统有何不同? 有头盔。 它还有助于安装 ClickHouse;您可以绘制 helm 图表,甚至可以安装整个 ClickHouse 集群。 那么,操作员和 Helm 等操作员之间有什么区别呢?

主要的根本区别在于 Helm 是包管理,而 Operator 更进一步。 这是对整个生命周期的支持。 这不仅仅是安装,这些都是日常任务,包括扩展、分片,即生命周期中需要完成的所有事情(如果需要,也可以删除)——这都是由操作员决定的。 它试图自动化和维护整个软件生命周期。 这是它与所提出的其他解决方案的根本区别。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

这是介绍部分,让我们继续。

我们如何构建我们的算子? 我们正在尝试解决这个问题,将 ClickHouse 集群作为单一资源进行管理。

这里我们在图片的左侧输入数据。 这是带有集群规范的 YAML,通过 kubectl 以经典方式传递到 Kubernetes。 在那里,我们的操作员拿起它并施展他的魔法。 在输出中我们得到以下方案。 这是 ClickHouse 在 Kubernetes 中的实现。

然后我们会慢慢看看操作员到底是如何工作的,可以解决哪些典型任务。 因为时间有限,我们只会考虑典型的任务。 并且并不是运营商可以决定的所有事情都会被讨论。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

让我们从实践开始吧。 我们的项目是完全开源的,所以你可以在 GitHub 上看到它是如何工作的。 并且您可以从考虑出发,如果您只是想启动它,那么您可以从快速入门指南开始。

如果您想详细了解,那么我们会尝试以或多或少合适的形式维护文档。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

我们先从一个实际问题开始。 我们都想开始的第一个任务是以某种方式运行第一个示例。 即使我真的不知道它是如何工作的,如何使用操作符启动 ClickHouse? 我们正在写一份宣言,因为…… 所有与 k8s 的通信都是通过清单进行通信。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

这是一份如此复杂的宣言。 我们用红色突出显示的内容是我们需要关注的内容。 我们要求运营商创建一个名为 demo 的集群。

这些是目前的基本示例。 尚未描述存储,但稍后我们将回到存储。 现在,我们将观察集群的发展动态。

我们制定了这份宣言。 我们将其提供给我们的操作员。 他工作,他创造魔法。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

我们看一下控制台。 我们感兴趣的三个组件是:一个 Pod、两个服务和一个 StatefulSet。

操作员已经工作了,我们可以看到他到底创造了什么。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

他创造了这样的东西。 我们有一个 StatefulSet、Pod、每个副本的 ConfigMap、整个集群的 ConfigMap。 需要服务作为集群的入口点。

服务是中央负载均衡器服务,也可用于每个副本、每个分片。

我们的基本集群看起来像这样。 它来自一个单一节点。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

让我们更进一步,让事情复杂化。 我们需要对集群进行分片。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

我们的任务越来越多,动力正在开始。 我们想要添加一个分片。 我们关注事态发展。 我们正在更改我们的规格。 我们表明我们需要两个分片。

这是随着系统的增长而动态发展的同一个文件。 存储 否,存储将进一步讨论,这是一个单独的主题。

我们向 YAML 运算符提供数据,看看会发生什么。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

操作者思考并制作了以下实体。 我们已经有两个 Pod、三个服务,突然还有 2 个 StatefulSet。 为什么需要 2 个 StatefulSet?

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

在图表上是这样的 - 这是我们的初始状态,当时我们有一个 Pod。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

就变成这样了。 到目前为止一切都很简单,它已经被复制了。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

还有为什么会变成两个StatefulSet呢? 这里我们需要岔开话题,讨论一下 Kubernetes 中如何管理 Pod 的问题。

有一个名为 StatefulSet 的对象,它允许您从模板创建一组 Pod。 这里的关键因素是模板。 您可以使用一个 StatefulSet 中的一个模板来启动多个 Pod。 这里的关键词是“一个模板有多个 Pod”。

并且有一个很大的诱惑就是创建整个集群,将其打包到一个 StatefulSet 中。 它会起作用,没有问题。 但有一点需要注意。 如果我们想要组装一个异构集群,即由多个版本的 ClickHouse 组成的集群,那么问题就开始出现了。 是的,StatefulSet可以做滚动更新,在那里你可以推出一个新版本,说明你需要同时尝试不超过这么多的节点。

但是,如果我们推断任务并说我们想要创建一个完全异构的集群,并且我们不想使用滚动更新从旧版本更改为新版本,但我们只是想创建一个异构集群ClickHouse的不同版本以及不同的存储方面。 例如,我们希望在单独的磁盘上制作一些副本,一般来说,在慢速磁盘上制作一些副本,以完全构建异构集群。 而且由于 StatefulSet 从一个模板中创建了一个标准化的解决方案,所以没有办法做到这一点。

经过一番思考,我们决定这样做。 我们在自己的 StatefulSet 中拥有每个副本。 该解决方案有一些缺点,但实际上它完全由操作员封装。 而且还有很多优点。 我们可以构建我们想要的确切集群,例如,一个绝对异构的集群。 因此,在一个拥有两个分片和一个副本的集群中,我们将拥有 2 个 StatefulSet 和 2 个 Pod,正是因为我们出于上述原因选择了这种方法,以便能够构建异构集群。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

让我们回到实际问题。 在我们的集群中,我们需要配置用户,即您需要在 Kubernetes 中对 ClickHouse 进行一些配置。 运营商为此提供了所有可能性。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

我们可以直接在YAML中编写我们想要的内容。 所有配置选项都直接从此 YAML 映射到 ClickHouse 配置中,然后分布在整个集群中。

你可以这样写。 这是例如。 密码可以加密。 绝对支持所有 ClickHouse 配置选项。 这只是一个例子。

集群配置作为 ConfigMap 进行分发。 实际上,ConfigMap 更新不会立即发生,因此如果集群很大,那么推送配置的过程需要一些时间。 但这一切使用起来都非常方便。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

让我们把任务复杂化吧。 集群正在发展。 我们想要复制数据。 也就是说,我们已经有两个分片,每个分片一个副本,并且用户已配置。 我们正在成长并希望进行复制。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

我们需要什么来进行复制?

我们需要动物园管理员。 在 ClickHouse 中,复制是使用 ZooKeeper 构建的。 需要 ZooKeeper,以便不同的 ClickHouse 副本就哪些数据块位于哪个 ClickHouse 上达成共识。

ZooKeeper 任何人都可以使用。 如果企业有外部ZooKeeper,那么就可以使用。 如果没有,您可以从我们的存储库安装它。 有一个安装程序可以使整个事情变得更容易。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

整个系统的交互图是这样的。 我们有 Kubernetes 作为平台。 它执行 ClickHouse 运算符。 我在这里想象了动物园管理员。 操作员与 ClickHouse 和 ZooKeeper 进行交互。 也就是交互的结果。

而这一切都是 ClickHouse 成功复制 k8s 中数据所必需的。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

现在让我们看看任务本身,看看复制清单是什么样子的。

我们正在清单中添加两个部分。 第一个是从哪里获取 ZooKeeper,它可以位于 Kubernetes 内部,也可以位于外部。 这只是一个描述。 我们订购复制品。 那些。 我们想要两个副本。 总共,我们应该在输出处有 4 个 pod。 我们记得存储,稍后会回来。 存储是一个单独的故事。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

事情就是这样的。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

就变成这样了。 添加副本。 第四个不合适,我们相信那里可能有很多。 并且ZooKeeper是添加到一边的。 这些计划正变得更加复杂。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

是时候添加下一个任务了。 我们将添加持久存储。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)对于持久存储,我们有多种选择。

如果我们运行在云提供商中,例如使用亚马逊、谷歌,那么使用云存储就有很大的诱惑。 很方便,很好。

还有第二种选择。 当我们每个节点上都有本地磁盘时,这适用于本地存储。 这个选项实施起来要困难得多,但同时它的生产力也更高。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

让我们看看我们有哪些关于云存储的内容。

有优点。 配置非常简单。 我们只需从云提供商处订购,请为我们提供此类容量、此类容量的存储。 课程由提供者独立安排。

还有一个缺点。 对于某些人来说,这是一个不重要的缺点。 当然,也会存在一些性能问题。 它使用起来非常方便且可靠,但也存在一些潜在的性能缺陷。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

并且因为ClickHouse特别注重生产力,甚至可以说它竭尽全力,这就是为什么许多客户试图压榨最大生产力。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

为了充分利用它,我们需要本地存储。

Kubernetes 为在 Kubernetes 中使用本地存储提供了三种抽象。 这:

  • 空目录
  • 主机路径。
  • 本地品牌

让我们看看它们有何不同以及有何相似之处。

首先,在所有三种方法中,我们都有存储 - 这些是位于同一物理 k8s 节点上的本地磁盘。 但它们有一些区别。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

让我们从最简单的一个开始,即emptyDir。 这在实践中是什么? 在我们的规范中,我们要求容器化系统(最常见的是 Docker)为我们提供对本地磁盘上文件夹的访问权限。

在实践中,Docker 在其自己的路径上的某个位置创建一个临时文件夹,并将其称为长哈希。 并提供了访问它的接口。

这将如何在性能方面发挥作用? 这将以本地磁盘速度工作,即这是对螺丝的完全访问。

但这种情况有其缺点。 持久在这件事上是相当可疑的。 Docker 第一次与容器一起移动时,持久性就丢失了。 如果 Kubernetes 由于某种原因想要将这个 Pod 移动到另一个磁盘,数据将会丢失。

这种方法对于测试很有用,因为它已经显示了正常速度,但对于严重的情况,此选项不适合。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

因此还有第二种方法。 这是主机路径。 如果您查看上一张幻灯片和这张幻灯片,您只能看到一个区别。 我们的文件夹从 Docker 直接移至 Kubernetes 节点。 这里稍微简单一点。 我们直接指定本地文件系统上要存储数据的路径。

这种方法有其优点。 这已经是真正的持久性,而且是经典。 我们将数据记录在磁盘的某个地址上。

也有缺点。 这就是管理的复杂性。 我们的 Kubernetes 可能想将 Pod 移动到另一个物理节点。 这就是 DevOps 发挥作用的地方。 他必须向整个系统正确解释这些 Pod 只能移动到那些沿着这些路径安装了某些东西的节点,并且一次不能超过一个节点。 这是相当困难的。

特别是出于这些目的,我们在运算符中制作了模板,以隐藏所有这些复杂性。 您可以简单地说:“我想为每个物理节点以及沿着这样那样的路径拥有一个 ClickHouse 实例。”

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

但我们并不是唯一有这种需求的人,所以来自 Kubernetes 本身的先生们也明白人们想要访问物理磁盘,所以他们提供了第三层。

这叫本地。 与上一张幻灯片实际上没有什么区别。 只是之前需要手动确认我们无法将这些 Pod 从一个节点转移到另一个节点,因为它们必须沿着某个路径附加到本地物理磁盘,但现在所有这些知识都封装在 Kubernetes 本身中。 事实证明它的配置要容易得多。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

让我们回到我们的实际问题。 让我们回到 YAML 模板。 这里我们有真正的存储。 我们回来了。 我们像 k8s 中一样设置经典的 VolumeClaim 模板。 我们描述了我们想要什么样的存储。

之后,k8s将请求存储。 会在StatefulSet中分配给我们。 最终它将由 ClickHouse 使用。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

我们有这个计划。 我们的持久存储是红色的,这似乎暗示需要完成它。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

它变成绿色。 至此ClickHouse on k8s集群方案已经彻底敲定。 我们有分片、副本、ZooKeeper,我们有真正的持久化,它以某种方式实现。 该计划已经全面投入运行。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

我们继续生活下去。 我们的集群正在发展。 Alexey 尝试并发布了 ClickHouse 的新版本。

出现了一个实际任务 - 在我们的集群上测试新版本的 ClickHouse。 而且,自然地,您不想将其全部推出;您想将新版本放入远角某处的一个副本中,并且可能不是一个新版本,而是一次两个,因为它们经常出现。

对此我们能说些什么呢?

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

我们这里正好有这样的机会。 这些是 Pod 模板。 你可以写我们的算子完全可以让你构建异构集群。 那些。 配置,从一堆中的所有副本开始,到每个个人副本结束,我们想要ClickHouse哪个版本,我们想要存储哪个版本。 我们可以使用我们需要的配置来完全配置集群。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

让我们更深入地了解一下。 在此之前,我们讨论了 ClickHouse-operator 如何与 ClickHouse 的具体细节相关的工作方式。

现在我想谈谈 Operator 的一般工作原理,以及它如何与 K8s 交互。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

我们先来看看与 K8s 的交互。 当我们执行 kubectl apply 时会发生什么? 我们的对象通过 API 出现在 etcd 中。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

例如,基本的 Kubernetes 对象:pod、StatefulSet、service 等等。

与此同时,身体上还没有发生任何事情。 这些对象必须在集群中具体化。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

为此,出现了控制器。 控制器是一个特殊的k8s组件,可以实现这些描述。 他知道如何做以及做什么。 他知道如何运行容器,以及需要配置什么才能使服务器正常工作。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

它在 K8s 中具体化了我们的对象。

但我们不仅想要操作 pod 和 StatefulSet,我们还想创建一个 ClickHouseInstallation,即 ClickHouse 类型的对象,以便将其作为一个整体进行操作。 目前为止还没有这种可能性。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

但 K8s 有以下好处。 我们希望我们有一个像这个复杂实体一样的地方,我们的集群将由 pod 和 StatefulSet 组装而成。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

为此需要做什么? 首先,自定义资源定义出现。 这是什么? 这是对 K8s 的描述,您将多一种数据类型,我们要向 pod 添加自定义资源 StatefulSet,其内部会很复杂。 这是数据结构的描述。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

我们还通过 kubectl apply 将其发送到那里。 Kubernetes 很高兴地接受了。

现在在我们的存储中,etcd 中的对象有机会记录一个名为 ClickHouseInstallation 的自定义资源。

但目前不会再发生任何事情。 也就是说,如果我们现在创建描述分片和副本的 YAML 文件并说“kubectl apply”,那么 Kubernetes 将接受它,将其放入 etcd 中并说:“很好,但我不知道该怎么做用它。 我不知道如何维护 ClickHouseInstallation。”

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

因此,我们需要有人帮助 Kubernetes 服务新的数据类型。 左侧有一个可处理本机数据类型的本机 Kubernetes 控制器。 在右侧,我们应该有一个可以处理自定义数据类型的自定义控制器。

换句话说,它被称为运算符。 我在这里特别将其作为 Kubernetes 包含在内,因为它也可以在 K8s 之外执行。 当然,大多数情况下,所有算子都在 Kubernetes 中执行,但没有什么可以阻止它站在外面,所以这里特意将其移到了外面。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

反过来,自定义控制器(也称为操作员)通过 API 与 Kubernetes 进行交互。 它已经知道如何与 API 交互。 他已经知道如何实现我们想要从自定义资源制作的复杂电路。 这正是操作员所做的。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

运营商如何工作? 让我们看看右侧,看看他是如何做到的。 让我们看看运营商如何实现这一切以及如何与 K8s 进行进一步的交互。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

运算符是一个程序。 她以事件为导向。 操作员使用 Kubernetes API 订阅事件。 Kubernetes API 有入口点,您可以在其中订阅事件。 如果 K8s 发生变化,Kubernetes 就会向每个人发送事件,即任何订阅此 API 点的人都会收到通知。

操作员订阅事件并且必须做出某种反应。 它的任务是响应新出现的事件。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

事件是由某些更新生成的。 我们的带有 ClickHouseInstallation 描述的 YAML 文件已到达。 他通过 kubectl apply 去了etcd。 那里触发了一个事件,结果这个事件到达了 ClickHouse-operator。 操作员收到此描述。 他必须做点什么。 如果 ClickHouseInstallation 对象有更新,则需要更新集群。 而操作员的任务就是更新集群。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

他在做什么? 首先,我们需要为这次更新制定一个行动计划。 更新可能非常小,即YAML 执行量很小,但可能需要对集群进行非常大的更改。 因此,操作员制定一个计划,然后坚持执行。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

根据这个计划,他开始在内部烹饪这个结构,以实现 Pod、服务,即做他的主要任务。 这就是如何在 Kubernetes 中构建 ClickHouse 集群。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

现在让我们来谈谈这样一个有趣的事情。 这是 Kubernetes 和运营商之间的责任划分,即Kubernetes 做什么,操作员做什么,以及它们如何相互交互。

Kubernetes 负责系统事务,即用于可以解释为系统范围的一组基本对象。 Kubernetes 知道如何启动 pod、如何重启容器、如何挂载卷、如何使用 ConfigMap,即一切可以称为系统的东西。

运营商在域中进行操作。 每个操作员都是针对自己的主题领域而设计的。 我们为 ClickHouse 做到了。

操作员可以根据主题区域进行精确交互,例如添加副本、制作图表、设置监控。 这导致了分裂。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

让我们看一个实际示例,了解当我们执行添加副本操作时如何发生这种责任划分。

操作员收到一个任务 - 添加副本。 运营商做什么的? 操作员将计算需要创建一个新的 StatefulSet,其中必须描述这样那样的模板、卷声明。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

他准备好了一切并将其传递给 K8s。 他说他需要ConfigMap、StatefulSet、Volume。 Kubernetes 正在工作。 他具体化了他所运用的基本单位。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

然后 ClickHouse-operator 再次发挥作用。 他已经有了一个物理舱,他已经可以在上面做一些事情了。 ClickHouse-operator 再次在领域术语中工作。 那些。 特别是 ClickHouse,为了在集群中包含副本,您必须首先配置该集群中存在的数据模式。 其次,这个副本必须包含在监控中,以便可以清楚地追踪。 运营商已经对此进行了配置。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

只有在 ClickHouse 本身发挥作用之后,即另一个更高级别的实体。 这已经是一个数据库了。 它有自己的实例,另一个已配置的副本,已准备好加入集群。

事实证明,添加副本时的执行链和责任划分相当长。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

我们继续开展实际工作。 如果您已有集群,则可以迁移配置。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

我们这样做是为了让您可以直接粘贴到 ClickHouse 可以理解的现有 xml 中。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

您可以微调ClickHouse。 分区部署就是我在解释hostPath,本地存储时谈到的。 这是正确进行分区部署的方法。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

下一个实际任务是监控。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

如果我们的集群发生变化,那么我们需要定期配置监控。

让我们看一下图表。 我们已经看过这里的绿色箭头。 现在让我们看看红色箭头。 这就是我们想要监控集群的方式。 ClickHouse 集群的指标如何进入 Prometheus,然后进入 Grafana。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

监控的难点是什么? 为什么这被描述为某种成就? 困难在于动态。 当我们有一个集群并且它是静态的时,我们可以设置一次监控而不再打扰。

但如果我们有很多集群,或者某些东西在不断变化,那么这个过程就是动态的。 并且不断地重新配置监控是浪费资源和时间,即甚至只是懒惰。 这需要自动化。 困难在于过程的动态性。 操作员可以很好地实现自动化。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

我们的集群是如何发展的? 一开始他就是这样的。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

然后他就这样了。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

最后,他就变成了这样。

监控由操作员自动完成。 单点入口。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

就在出口处,我们查看 Grafana 仪表板,看看集群内部的运行状况如何。

顺便说一句,Grafana 仪表板也直接在源代码中与我们的操作员一起分发。 您可以连接并使用。 我们的 DevOps 给了我这个屏幕截图。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

接下来我们想去哪里? 这:

  • 开发测试自动化。 主要任务是新版本的自动化测试。
  • 我们也非常希望自动化与 ZooKeeper 的集成。 并且有计划与 ZooKeeper-operator 集成。 那些。 已经为 ZooKeeper 编写了一个运算符,这两个运算符开始集成以构建更方便的解决方案是合乎逻辑的。
  • 我们想做更复杂的生命体征。
  • 我用绿色突出显示,我们正在接近模板的继承 - 完成,即在操作符的下一个版本中,我们将已经拥有模板的继承。 这是一个功能强大的工具,可让您从多个部分构建复杂的配置。
  • 我们希望复杂任务的自动化。 主要的一个是重新分片。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

让我们看一些中间结果。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

我们得到什么结果? 这是否值得做? 是否有必要尝试将数据库拖入 Kubernetes 并使用一般运算符,特别是 Alitnity 运算符?

在输出中我们得到:

  • 配置、部署和维护的显着简化和自动化。
  • 立即内置监控。
  • 以及适用于复杂情况的现成编码模板。 添加副本等操作不需要手动完成。 运营商这样做。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

只剩下最后一个问题了。 我们已经有了 Kubernetes 中的数据库、虚拟化。 这种解决方案的性能如何,特别是 ClickHouse 针对性能进行了优化?

答案是一切都很好! 我不会详细讨论;这是单独报告的主题。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

但是有一个像 TSBS 这样的项目。 它的主要任务是什么? 这是数据库性能测试。 这是一种比较暖与暖、软与软的尝试。

他如何工作? 生成一组数据。 然后使用同一组测试在不同的数据库上运行这组数据。 每个数据库都以其知道的方式解决一个问题。 然后您可以比较结果。

它已经支持大量数据库。 我已经确定了三个主要的问题。 这:

  • 时间刻度数据库。
  • InfluxDB。
  • 单击房屋。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

还与另一个类似的解决方案进行了比较。 与 RedShift 的比较。 在亚马逊上进行了比较。 ClickHouse 在这件事上也远远领先于大家。

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

从我所说的可以得出什么结论?

  • Kubernetes 中的数据库是可能的。 也许任何一种都有可能,但总的来说,看起来都是可能的。 在我们运营商的帮助下,Kubernetes 中的 ClickHouse 绝对是可能的。
  • 操作员有助于实现流程自动化,真正让生活变得更轻松。
  • 性能正常。
  • 在我们看来,这可以而且应该被使用。

开源 - 加入我们!

正如我已经说过的,该算子是一个完全开源的产品,所以如果有尽可能多的人使用它就非常好。 加入我们! 我们正在等待大家!

谢谢你!

问题

Kubernetes 中的 Operator,用于管理数据库集群。 Vladislav Klimenko(Altinity,2019)

感谢您的报告! 我叫安东。 我来自 SEMrush。 我想知道日志记录是怎么回事。 如果我们谈论整个集群,我们会听说过监控,但没有听说过日志记录。 比如我们在硬件上提出了一个集群。 我们使用集中式日志记录,使用标准方法将它们收集到一个公共堆中。 然后从那里我们得到我们感兴趣的数据。

好问题,即登录待办事项列表。 我们的操作员还没有自动执行此操作。 它仍在开发中,该项目还很年轻。 我们了解日志记录的需求。 这也是一个非常重要的话题。 它的重要性可能不亚于监控。 但首先要实施的是监控。 会有日志记录。 当然,我们尝试使集群生活的各个方面实现自动化。 因此,答案是,不幸的是,目前运营商不知道如何做到这一点,但它在计划中,我们会这样做。 如果您想加入,请提出请求。

你好! 感谢您的报告! 我有一个与持久卷相关的标准问题。 当我们使用此操作符创建配置时,操作符如何确定我们在哪个节点上附加了特定的磁盘或文件夹? 我们首先要跟他解释一下,请将我们的ClickHouse放在这些有磁盘的节点上好吗?

据我了解,这个问题是本地存储的延续,尤其是其中的hostPath部分。 这就像向整个系统解释,pod需要在某个节点上启动,我们有一个物理连接的磁盘,沿着某个路径挂载。 这是我非常肤浅地触及的整个部分,因为那里的答案相当大。

简而言之,它看起来像这样。 当然,我们需要提供这些卷。 目前,本地存储中没有动态配置,因此 DevOps 必须切割磁盘本身,即这些卷。 他们必须解释 Kubernetes 配置,您将拥有此类此类的持久卷,这些卷位于此类节点上。 然后,您需要向 Kubernetes 解释,需要这样那样的本地存储类的 pod 只需使用标签定向到这样那样的节点。 出于这些目的,操作员能够分配某种标签,并为每个主机实例分配一个标签。 事实证明,Pod 将由 Kubernetes 路由,仅在满足要求(简单来说就是标签)的节点上运行。 管理员手动分配标签并配置磁盘。 然后它就会扩展。

第三个选项是本地选项,它可以让这件事变得更容易一些。 正如我已经强调的,这是一项艰苦的调优工作,最终有助于获得最大的性能。

我还有与此相关的第二个问题。 Kubernetes 的设计方式是,无论是否丢失节点,对我们来说都无关紧要。 在这种情况下,如果我们丢失了分片挂起的节点,我们该怎么办?

是的,Kubernetes 最初的定位是我们与 Pod 的关系就像牛一样,但在这里,每个磁盘都变得像宠物一样。 存在这样一个问题,我们不能把它们扔掉。 而 Kubernetes 的发展正朝着无法完全哲学地对待它的方向发展,就好像它是一个完全被丢弃的资源一样。

现在提出一个实际问题。 如果磁盘所在的节点丢失了怎么办? 在这里,问题正在更高的层面上得到解决。 就 ClickHouse 而言,我们有在更高级别工作的副本,即在 ClickHouse 级别。

结果是什么? DevOps 负责确保数据不丢失。 他必须正确设置复制并确保复制正在运行。 ClickHouse级别的副本必须有重复的数据。 这不是操作员要解决的任务。 而不是 Kubernetes 本身解决的问题。 这是在 ClickHouse 级别。

如果你的铁节点脱落了怎么办? 事实证明,您需要安装第二个光盘,在其上正确配置光盘并粘贴标签。 之后,它将满足 Kubernetes 可以在其上启动实例 pod 的要求。 Kubernetes 将启动它。 您的 Pod 数量不足以满足指定数量。 它将经历我展示的循环。 在最高级别,ClickHouse 会明白我们已经进入了一个副本,它仍然是空的,我们需要开始向它传输数据。 那些。 这个过程还没有很好地自动化。

感谢您的报告! 当各种令人讨厌的事情发生时,操作员崩溃并重新启动,而此时事件到来,您是否以某种方式处理这个问题?

如果操作员崩溃并重新启动会发生什么,对吧?

是的。 就在那时,事件发生了。

在这种情况下要做什么的任务部分由操作员和 Kubernetes 共同承担。 Kubernetes 能够重播已发生的事件。 他重播。 而操作员的任务是确保当事件日志在他身上重播时,这些事件是幂等的。 这样同一事件的重复发生就不会破坏我们的系统。 我们的操作员负责这项任务。

你好! 感谢您的报告! 德米特里·扎维亚洛夫,公司 斯梅多娃。 是否有计划向运营商添加使用 haproxy 配置的功能? 除了标准平衡器之外,我还对其他平衡器感兴趣,这样它就很智能,并且能够理解 ClickHouse 确实存在。

你是在谈论 Ingress 吗?

是的,用 haproxy 替换 Ingress。 在 haproxy 中,您可以指定具有副本的集群的拓扑。

我们还没有考虑过。 如果你需要它并且能够解释为什么需要它,那么就有可能实现它,特别是如果你想参与的话。 我们将很乐意考虑这个选择。 简短的回答是否定的,我们目前没有这样的功能。 感谢您的提示,我们会​​调查此事。 如果您还解释了用例以及为什么在实践中需要它,例如,在 GitHub 上创建问题,那就太好了。

已经有了。

美好的。 我们愿意接受任何建议。 并且 haproxy 已添加到待办事项列表中。 待办事项清单正在增加,但尚未缩小。 但这是好事,说明该产品有需求。

来源: habr.com

添加评论