Kubernetes 笔记|为自己的云原生系统开发一个 Kubernetes Operator

1. 背景和动机

"云原生"俨然是时下的热词。本质上,它是指在云上运行的具有弹性、可管理性和可观察性的系统。RisingWave 就是一个云原生的流式数据库,它的设计宗旨是充分利用云计算带来的弹性。

但是,在云上部署和维护 RisingWave 仍然是一个具有挑战性的"技术活"。特别是考虑到以下问题:

  • 如何在云服务供应商(如 AWS、Azure 和 GCP)上部署流式数据库?
  • 当负载过大时如何扩展数据库?能否自动进行扩展?
  • 当一些组件出现故障时如何进行快速恢复?

还好,有 Kubernetes。Kubernetes 是一个开源系统,可在计算机集群上自动化部署、扩展和管理容器化应用程序。它提供了大量的 API 用于抽象所需资源。有了 Kubernetes,人们在部署应用程序时不必担心被云服务供应商深度绑定。

我们开发了 Kubernetes Operator for RisingWave(下文简写为"Operator"),一个能在Kubernetes 上管理 RisingWave 的扩展插件。编写 Operator 颇具挑战,这篇博文将概述 Operator 的功能特性、实现过程中的挑战以及我们的解决方案,供有相同需求的用户参考。

2. Kubernetes operator 基础知识

在讲到operator之前,先简要介绍一下Kubernetes中的一些核心概念。

  • Pod是Kubernetes中可被调度的最小单元。每个Pod可包含多个容器(Containers),Pod之间通常共享相同的命名空间隔离(namespace isolation)。Pod是Kubernetes提供的抽象计算资源的基本组件。不夸张地说,整个世界都是建立在它的基础上的。
  • Service是一种抽象,用于将一组Pod上运行的应用程序公开为网络服务。
  • Deployment和StatefulSet都是工作负载资源(workload resources)。工作负载资源能帮助你在Kubernetes上运行应用程序,并能提供高级功能。例如,使用Deployment,你可以简单地通过设置所需的副本来扩容或缩容应用。Deployment和StatefulSet的主要区别在于,Deployment仅适用于无状态应用(stateless applications),而StatefulSet则尽可能保持状态活跃,例如挂载的持久卷。

除了内置资源之外,Kubernetes还引入了自定义资源(即CustomResourceDefinition,CRD),以扩展其API。CRD API允许用户自定义自己的资源。通常,每种资源类型都有一个控制器(controller)。但是Kubernetes核心组件中没有针对自定义资源的控制器。开发者通常会提供与自定义资源相配对的控制器。

那么,Kubernetes operator到底是什么?广义上,Kubernetes operator是一组CRD和相应的控制器。控制器通过遵循operator模式确保扩展的API最终按预期运作。

在介绍了Kubernetes operator的一些基础知识后,接下来的部分将详细说明Kubernetes Operator for RisingWave是如何建立在这些抽象之上的。

3. 实现Kubernetes Operator for RisingWave

Operator 能管理 RisingWave 集群。它使得部署、升级、监控和扩展 RisingWave 集群的操作变得简单、高效、自动化。要实现 Operator,技术上主要有两方面挑战:

  • 如何在 Kubernetes 中体现 RisingWave?
  • 如何在控制器中建立管理不同组件的工作流程?

4. 在 Operator 中抽象 RisingWave

要在 Kubernetes 中抽象 RisingWave,需要解决三个主要问题。

4.1 使用工作负载资源抽象组件

RisingWave有四个主要组件:元数据服务器、前端、计算节点和compactor节点。有关详细信息,可参考设计文档。我们可以将所有组件节点都看作是无状态的,因为RisingWave是建立在云原生共享存储上的。因此,将Deployment用于每个组件再直截了当不过。但是,考虑到计算节点中的本地缓存,我们使用了StatefulSet而不是Deployment来管理它们。StatefulSet在状态方面有许多保证,例如,它会在升级副本时保持顺序,但我们所需的是它的存储守护。

4.2 用于通信的稳定网络标识符

在Kubernetes中,每个Pod在创建时都会分配一个内部IP。除非存在进一步的限制,这个IP在Kubernetes内部是可访问的。但是,这些内部IP不能直接用于进程之间的通信。例如,当发生故障或升级时,Pod常常会被销毁并重建。在这些情况下,同一组件的IP也会在RisingWave实例的生命周期中发生变化。因此,我们为每个组件启用了一个单独的Service。这些Service会保留不可变的内部IP作为稳定的标识符。我们利用Service的发现机制让节点之间"认识"彼此。

4.3 连接不同的资源

那这些资源能够为RisingWave实例提供所需的功能吗?不幸的是,对于实现一个可用于生产环境的operator来说,答案是否定的。为了在部署和管理上有更多灵活性,我们还开发和使用了:

  • ConfigMap------用于存储配置。它将挂载到运行的Pod上。

  • 工作负载资源组------同一组件的工作负载资源可以分成多个组并单独管理。例如,我们允许计算节点在两个可用区(availability zones)运行。

  • ServiceMonitor------用于声明Prometheus的抓取任务。这是个可选的子资源。它只会在安装Prometheus operator时同步。

这是RisingWave不同子资源之间关系的概览。

5. 实现控制器

在 Kubernetes 中,这些管理不同资源的工作流是在控制器中定义的。在下文中,我们将讨论在 Operator 中实现控制器的细节。

5.1 反应作为基本单元

实现控制器非常复杂。每个不同的子资源都有自己的状态和逻辑。我们将复杂的过程分成小的片段:每个片段只关注一些子资源,并尽力做到最好。例如,前端Deployment只应在有相关规格更改时更新,例如修改副本、资源或节点选择器时。在这种情况下,我们只需进行以下其中一种操作:

  • 在找不到此类资源时创建一个。
  • 根据RisingWave的规格进行更新。
  • 如果已过时且不再需要,则删除。

这些操作构成了对RisingWave规格和实际状态的反应(reaction)。每个子资源都有自己的反应。无论发生什么,反应都会找到一种方法来确保Deployment最终在线并与规格保持一致。

5.2 反应式工作流

我们设计了一个反应式工作流,并提供两个原语来有序地组织反应。

  • Join反应允许反应运行,但将结果合并。本质上,Join是用于同时运行多个独立反应的。
  • Sequential反应允许反应按顺序运行。它能确保依赖的反应在条件满足之前不会运行。

除了用于将反应组织到工作流中的原语之外,我们还设计了几个装饰器来增强反应,但不改变它们的意图:

  • Timeout可装饰反应,并尽可能在给定时间过后使程序超时。
  • Retry在遇到意外错误时会重试反应,直到达到限制次数。
  • Parallel可并行运行基础反应。
  • Shared可标记反应为共享反应,让不同的工作流分支可以共享该反应,但只运行一次。

此外,工作流原语还支持构建结构化并发工作流,这可能是并行编程的最佳模式。你可以参考代码库中的ctrlkit包了解有关设计的更多细节。下图展示了当前运行的工作流:

在上方图表中,Sync Components and Sub-resources是一个共享的子工作流,如下所示:

有了反应和工作流,开发者能从这几方面受益:

  • 专注于一个小单元(通常只考虑单个方面的子资源)使得代码更具鲁棒性、更易于维护。
  • 用原语来组织工作流能最大限度给予调整行为的灵活性,并将常用的装饰器与反应解耦。在Operator的工作流中,我们追求极致的效率,几乎并行化了每个独立的反应。

6. 碎碎念

我们还遇到了很多其他的技术难题,例如使用客户端缓存所带来的问题,客户端缓存对象并提供Get操作(那么数据的新鲜度始终不够好)。这些我们会留到以后的文章中再探讨。

7. 改进计划

在经过上文讲述的所有努力之后,Operator已经整合了在云上管理RisingWave集群的基本功能。但是,我们还有很多工作要做。在我们发布这篇文章的时候,许多令人兴奋的功能的设计和开发正如火如荼地进行着:

  • kubectl插件------可帮助用户在Kubernetes上更自然地操作RisingWave。
  • Helm图表------可用于部署Operator、RisingWave和依赖项。
  • 与Grafana和Prometheus的即插即用集成。Operator将来还会附带可用于生产环境的仪表板。

8. 总结

本文概述了开发 Kubernetes Operator for RisingWave 过程中的主要技术挑战以及我们的解决方案。Operator 能帮助用户在 Kubernetes 中运行 RisingWave。它支持即开即用式的对RisingWave 集群的重启、扩展和升级操作。

声明:Kubernetes Operator for RisingWave 于 2022 年底就已经开发完成,部分技术细节可能失去时效性

相关推荐
一 乐1 小时前
民宿|基于java的民宿推荐系统(源码+数据库+文档)
java·前端·数据库·vue.js·论文·源码
hackchen2 小时前
NexusTerminal一款视频移动端的webSSH
docker·云原生·eureka·web-ssh
美林数据Tempodata3 小时前
大模型驱动数据分析革新:美林数据智能问数解决方案破局传统 BI 痛点
数据库·人工智能·数据分析·大模型·智能问数
野槐3 小时前
node.js连接mysql写接口(一)
数据库·mysql
Zzzone6834 小时前
PostgreSQL日常维护
数据库·postgresql
chxii4 小时前
1.13使用 Node.js 操作 SQLite
数据库·sqlite·node.js
冰刀画的圈4 小时前
修改Oracle编码
数据库·oracle
这个胖子不太裤4 小时前
Django(自用)
数据库·django·sqlite
麻辣清汤4 小时前
MySQL 索引类型及其必要性与优点
数据库·mysql
2501_915374355 小时前
Neo4j 图数据库安装教程(2024最新版)—— Windows / Linux / macOS 全平台指南
数据库·windows·neo4j