写点什么

我们将 Helm 用至极限,然后创建了一个 Kubernetes Operator

Jeff Carpenter & John Sanda

  • 2022-01-15
  • 本文字数:3940 字

    阅读完需:约 13 分钟

我们将Helm用至极限,然后创建了一个Kubernetes Operator

K8ssandra是 Apache Cassandra®在 Kubernetes 上的一个发行版,由多个开源组件构建而成。从一开始直到最近的K8ssandra 1.3版本,K8ssandra 一直使用 Helm 图表进行安装和管理。虽然该项目的某些组件使用了 Kubernetes Operators——包括 Cassandra(cass-operator)和 Medusa(medusa-operator),但还没有一个 Operator 对所有组件进行整体管理。


K8ssandra 团队最近完成了一个我们讨论了几个月的决定:为 K8ssandra 项目创建一个 Operator。在本文中,我们介绍了我们使用 Helm 的经验,我们为 K8ssandra 创建 Operator 的决定,以及我们希望这将为项目带来的好处。



背景

K8ssandra 的核心是cass-operator,我们使用它来部署 Cassandra 节点。我们围绕它添加了一系列组件,组成一个生态系统,用于在 Kubernetes 中有效地运行 Cassandra。这些组件包括用于管理反熵修复(Reaper)和备份(Medusa)的操作工具。我们引入了用于指标收集和报告的 Prometheus/Grafana 技术栈。Stargate 则是一个数据网关,通过 REST、GraphQL 和 Document API 提供了对 Cassandra 更灵活的访问。


一开始,我们使用 Helm 来帮助管理这些组件的安装和配置。这使我们能够快速启动项目并开始组建社区。最初对该项目感兴趣的人主要是 Cassandra 社区的开发人员,他们不一定有很多 Kubernetes 的专业知识和经验。他们中的许多人发现掌握像 Helm 这样的包管理工具和安装程序比掌握 Operator 和 CRD(定制资源定义)更容易。这并不是说 Helm 是为“不太了解 Kubernetes 的人”准备的,因为 Kubernetes 生态的很大一部分都在使用 Helm。


进展:Helm 的优缺点


随着项目的发展,我们开始在 Helm 上遇到一些限制。虽然正确安装 K8ssandra 集群非常简单,但我们在升级和管理集群时遇到了比较多的问题。

编写复杂的逻辑


Helm 通过循环和 if 语句很好地支持控制流。然而,当嵌套层次比较多时,整个代码就很难理解和阅读,而且缩进也成为一个问题。特别是,我们发现对修改后的 Helm 图表进行同行评审变得相当困难。

重用和可扩展性


Helm 变量的作用范围被限制在声明它们的模板内。例如,我们在 Cassandra 数据中心模板中定义了一个变量,在 Stargate 模板中不可能重用它,我们必须在 Stargate 模板中重新创建相同的变量。这使得我们的代码很难保持DRY原则,我们发现这是缺陷的来源。


类似地,Helm 有一个很好很大的帮助模板函数库,但是这个库并没有涵盖所有用例,并且没有接口来定义您自己的函数。您可以定义自己的模板,模板可以被大量重用,但它们不能代替函数。

项目结构和继承


伞形图设计模式是 Helm 的最佳实践,但我们在尝试实现该模式时也遇到了困难。我们能够创建一个顶级 K8ssandra Helm 图表,其中包含 Cassandra 和 Prometheus 的子图表,但当我们试图为 Reaper 和 Stargate 创建额外的子图表时,却遇到了变量作用范围的问题。我们的目的是仅仅在顶级图表定义身份验证设置,这样它们不仅可以应用于 Cassandra,还可以应用于 Stargate 和 Reaper。Helm 的继承模型不支持这种将变量向下推到子图表的概念。

定制资源定义(CRD)管理


Helm 可以创建 Kubernetes 的定制资源定义(CRD),但不能管理它们。我们知道这是 Helm 开发者为 Helm 3 做出的深思熟虑的设计选择。由于定制资源的定义是集群范围的,如果多个 Helm 安装过程试图在不同版本的 CRD 上工作可能会带来一些混乱。然而,这给我们带来了一些困难。为了管理资源的更新——比如 Helm 内部的 Cassandra 数据中心,我们必须实现一个变通方案。我们实现了定制的 Kubernetes job,并将它们标记为升级前的钩子(Hook),这样 Helm 就可以在升级时执行它们。每个 job 都用 Go 语言编写,并打包成一个镜像。这本质上就像编写迷你控制器,并且在某种程度上开始感觉像编写 Operator。

临界点:多集群部署


虽然我们已经能够通过 1.3 版本解决这些 Helm 的问题,但我们路线图上的下一个主要特性是实现多集群 K8ssandra 部署(跨越多个 Kubernetes 集群的 K8ssandra/Cassandra 集群)。我们意识到,即使没有复杂的网络配置,我们也无法使用 Helm 有效实现这一步。

设定新方向


最后,我们意识到我们让 Helm 做得太多了。很容易陷入这样的情况:您学会了如何使用锤子,所有东西看起来都像钉子,但您真正需要的是螺丝刀。


结果,我们发现我们与Operator框架的创建者有一些共同点,他们已经为 Operator 定义了一个功能模型,我们将其展示在这里:



如图所示,Helm 最适合 Operator 前两个级别的功能,侧重于简单的安装和升级。执行更复杂的操作如故障处理和恢复、自动伸缩,以及更复杂的安装和升级应该用诸如 Ansible 或 Go 之类的编程语言来实现,而不是使用像 Helm 这样的模板语言。

构建一个 Operator:K8ssandra 2.0


基于这一分析,团队决定开始构建一个 Operator,我们将其称之为 K8ssandra 2.x 系列版本。2.0 版本的首要任务是移植我们在 Helm 图表中已有的功能,确保 Operator 具有相同的特性,并在其中增加多集群支持。我们仍然打算解决 1.x 版本中的 bug 或漏洞,但我们正试图将所有主要的新功能都集中在 Operator 上。

Helm 仍有一席之地


在工具方面,我们不认为 Helm 和 Operator 是相互排斥的。这两种方法是互补的,我们需要根据其优势来使用每一种方法。我们将继续使用 Helm 执行基本的安装操作,包括安装 Operator 以及设置 Cassandra 和其他组件使用的管理员服务帐号(Administrator Service Account)。这些都是 Helm 这样的包管理器最擅长的功能。

Operator 设计和实现的选择


在 K8ssandra Operator 的设计和实现中,我们做出了几个关键的选择。

模块化设计

虽然 Reaper Operator、Medusa Operator 和 Stargate Operator 有单独的仓库,但我们计划将它们合并到 K8ssandra Operator 中。K8ssandra Operator 将在单个 pod 中运行,但将包含与每个 CRD 对应的多个控制器。我们将会有多个 CRD 和多个控制器。因为 cass operator 已经被独立使用,所以它仍将是独立的,并将成为 K8ssandra Operator 的一个依赖项。



虽然目前这不是微服务架构,但它是松耦合和模块化的,所以未来如果需要,我们可以将控制器重新打包为独立的微服务。

基于 Operator SDK 使用 Go 语言开发


我们决定基于 Operator SDK 使用 Go 语言编写 K8ssandra Operator。对于我们来说,这是一个简单的选择,因为我们已经从开发 cass-operator 中熟悉了它。我们相信使用像 Go 语言这样的全功能编程语言会比使用 YAML 模板更有吸引力,并有助于吸引新的贡献者加入项目。这还将使我们能够使用该语言的全部功能。例如,Go 可以很容易地创建易于重用的辅助函数。

K8ssandra 集群级状态


新的 K8ssandra 集群 CRD 有一个状态字段,可以让您大致了解集群的状态,包括是否已经就绪(ready)、尚未就绪(not ready)、正在初始化(initializing)等等。该状态将汇总组成集群的所有对象的健康状况,包括 Cassandra 集群、Stargate、Reaper 和其他任何部署在其中的对象,而这不是 Helm 可以做到的。

与 Kubernetes 的方式更加一致


我们为每个定制资源开发控制器的设计方法与 Kubernetes 中管理资源的标准方法更加一致。例如,我们有一个特定的启动顺序,我们想定义如下规则:在 Cassandra 初始化之前不启动 Stargate。开箱即用的 Helm 无法实现这一功能。我们必须在 Stargate pod 中添加一个初始化容器,以执行集群启动和运行的基本检查。有了新的 Operator,Stargate 可以检查 Cassandra 数据中心 CRD 的状态变化。当它被调协器(reconciliation)触发运行,它查询获得 Cassandra 数据中心的状态,一旦其状态变为就绪(ready),Operator 就将部署 Stargate。

测试覆盖率


这种方式也将改进测试。有很多可用的测试覆盖工具,例如我们正在使用的 SonarCloud。然而,我们不能将 SonarCloud 与 Helm 模板一起使用。所以我们现在没有一个好的方法来衡量测试中的覆盖水平,而且 IDE 的支持也不像对静态语言那么好。

我们仍在研究的事情

在开发 Operator 的过程中,我们还在继续探索和学习一些领域。

加速迭代开发


Helm 模板非常适合快速迭代,但 Operator 的开发步骤更复杂。在修改 Operator 代码之后,我们必须重新构建 Operator 镜像并部署它,然后部署 Operator 管理的定制资源,以便它随后生成 Deployment 对象,然后我们就可以验证部署了。这个过程涉及更多步骤,所以我们正在寻求改进方法,使其更加自动化。

多集群集成测试


测试多集群 K8ssandra 部署存在一些挑战。到目前为止,我们已经能够使用 GitHub Actions 进行大多数持续集成测试(使用免费的 tier runner),但我们发现这在涉及多集群资源的时候是不够的。


我们正在调研的集成测试工具之一是Kuttl。使用 Kuttl,测试用例和预期结果都在 YAML 文件中描述,这意味着您不必是 Go 语言或 Kubernetes API 的专家也可以贡献测试。我们相信这会让开发人员更容易参与测试并立即做出贡献,然后如果他们愿意,可以按照自己的节奏开始使用 Go。

您应该使用 Operator 吗?您应该开发一个 Operator 吗?


如果您已经读到这里,您可能想知道这对您自己的项目的影响。如果您在 Kubernetes 中使用数据库或其他基础设施,那么使用 Operator 尽可能自动化的操作工作负载肯定是有意义的。


如果您为数据基础设施供应商工作,或者为开源数据基础设施项目做出贡献,您可能会好奇何时应该开始构建 Operator。我们在自己的过渡过程中进行了很多思考,特别是在时间安排和对用户的影响方面。最终我们的建议是:您在很多情况下发现您所使用的工具对您不利,而不是对您有利,此时可能是时候考虑不同的解决方案了。

建立社区


我们现在看到对 K8ssandra 的贡献有所增加,尤其是在问题创建方面。现在我们已经开始在 Operator 的发展中获得动力,不断增长的用户社区帮助我们认识到为了加快产品成熟而需要做的事情,这是拥有这样一个社区的巨大好处。


我们还想继续加强代码贡献团队。如果您有兴趣在 Kubernetes 上运行 Cassandra 或构建 Operator,我们很乐意让您成为 K8ssandra 项目的一员。您可以查看我们的网站,也可以在论坛或我们的Discord服务上提出任何问题。


原文链接(This article initially appeared on The New Stack

2022-01-15 09:006672

评论

发布
暂无评论
发现更多内容

头脑风暴:除数博弈

HelloWorld杰少

8月月更

HMS Core分析服务智能运营6.5.1版本上线

HarmonyOS SDK

生于云、长于云,RocketMQ 5.0 再出发

阿里巴巴云原生

阿里云 RocketMQ 云原生 消息队列

项目管理流程及各环节要点

爱吃小舅的鱼

开源一夏 | 牛plus,多层嵌套动态JSON该如何解析总结

知识浅谈

开源 8月月更

结合实际聊聊防反接电路(防反接电路总结)

矜辰所致

防反接电路设计 8月月更

图数据科学和机器学习图数据科学GDS概览

flow

8月月更

Redis 定长队列的探索和实践

vivo互联网技术

redis 数据结构 消息队列 Lua脚本

【LeetCode】受限条件下可到达节点的数目Java题解

Albert

LeetCode 8月月更

梦回战国,领略两千多年前公孙龙如何将面向对象运用得炉火纯青

迷彩

Java 面向对象 签约计划第三季 8月月更 面向过程编程

2022秋招前端面试题(六)(附答案)

helloworld1024fd

前端面试题

数据治理(三):数据质量管理

Lansonli

大数据 数据治理 8月月更

语音聊天app开发——对用户更具吸引力的设计

开源直播系统源码

软件开发 语聊房 开源源码 语音直播系统 语音源码

面试突击72:输入URL之后会执行什么流程?

王磊

Java 面试

Python逆向之 eval 函数解析,看着一篇就会了,案例掌房

梦想橡皮擦

Python 爬虫 8月月更

数据库不推荐使用外键的9个理由!

TimeFriends

8月月更

用户权限-Linux系统ACL控制

Albert Edison

Linux centos 运维 服务器 8月月更

开源一夏|Flutter实现搜索的三种方式

坚果

开源 OpenHarmony 8月月更

「控制反转」和「依赖倒置」,傻傻分不清楚?

蝉沐风

ioc 依赖倒置原则 DIP DI 控制反转

Shell脚本中常用命令复习

Albert Edison

Linux centos 运维 shell脚本编程 8月月更

阿里云云原生加速器企业硬之城携手阿里云 Serverless 应用引擎(SAE)打造低代码平台

阿里巴巴云原生

阿里云 Serverless 云原生 合作伙伴

高层次综合(HLS)

贾献华

8月月更

《MySQL入门很轻松》第2章:MySQL管理工具介绍

乌龟哥哥

8月月更

3 款非常实用的 Node.js 版本管理工具

Geek_z9ygea

JavaScript node.js 前端

左益豪:用代码创造一个新世界|OneFlow U

OneFlow

实习 社区之星

产品经理必备的19类工具网站

爱吃小舅的鱼

部署spark2.2集群(standalone模式)

程序员欣宸

spark 8月月更

国内最主流的5大项目工时管理系统

爱吃小舅的鱼

2022秋招前端面试题(五)(附答案)

helloworld1024fd

前端面试题

STM32F103ZE+SHT30检测环境温度与湿度(IIC模拟时序)

DS小龙哥

8月月更

提升领导力的有效方法

宇宙之一粟

领导力 8月月更

我们将Helm用至极限,然后创建了一个Kubernetes Operator_架构_InfoQ精选文章