本文已超过一年。较旧的文章可能包含过时的内容。请检查页面中的信息自发布以来是否已变得不正确。
GSoC 2020 - 为集群插件构建操作符
简介
Google 编程之夏是一个旨在向学生介绍开源的全球性计划。学生与开源组织配对,在夏季的三个月内与他们合作。
我的名字是 Somtochi Onyekwere,来自尼日利亚奥韦里联邦理工大学。今年,我有机会与 Kubernetes(在 CNCF 组织下)合作,这让我度过了一个美好的夏天,学习、贡献并与社区互动。
具体来说,我致力于集群插件:打包所有东西!项目。该项目专注于构建操作符,以便更好地管理各种集群插件,扩展构建这些操作符的工具,并使这些操作符的创建过程顺利进行。
背景
在过去的几年中,Kubernetes 取得了巨大的进步,拥有蓬勃发展的社区和大量的贡献者。代码库正逐渐从所有代码都位于 kubernetes/kubernetes 存储库中的单体结构转变为拆分为多个子项目。集群插件的部分重点是使这些子项目以一种易于组装、自我监控、自我修复且 Kubernetes 原生的方式协同工作。它使它们能够在没有人为干预的情况下无缝工作。
社区正在探索使用操作符作为一种机制来监控集群中的各种资源并正确管理这些资源。除此之外,它还提供了自我修复,并且它是一种 Kubernetes 原生的模式,可以编码这些插件的最佳工作方式并正确管理它们。
什么是集群插件?集群插件是用于为 Kubernetes 集群提供额外功能的一组资源(例如服务和部署)。它们的范围从像 Kubernetes 仪表板(用于可视化)这样简单的东西到像 Calico(用于网络)这样更复杂的东西。这些插件对于集群中运行的不同应用程序和集群本身至关重要。插件操作符提供了一种更好的方式来管理这些插件,并了解构成插件的各种资源的运行状况和状态。您可以在这篇文章中获得更深入的概述。
操作符是具有自定义资源定义的自定义控制器,它编码特定于应用程序的知识,并用于管理复杂的有状态应用程序。这是一种被广泛接受的模式。通过操作符管理插件,这些操作符编码了插件最佳工作方式的知识,在设置易于遵循和扩展的标准的同时,引入了许多优势。这篇文章很好地解释了操作符。
插件操作符可以解决许多问题,但它们也存在挑战。 cluster-addons 项目下的操作符缺少一些部分,仍然只是概念验证。为操作符生成 RBAC 配置很麻烦,有时操作符被赋予了过多的权限。操作符的可扩展性不是很强,因为它仅从本地文件系统或 HTTP(s) 服务器拉取清单,并且许多简单的插件正在生成相同的代码。我整个夏天都在研究这些问题,以全新的视角看待它们,并为已知和未知的问题提出解决方案。
kubebuilder-declarative-pattern 的各种新增功能
kubebuilder-declarative-pattern(以下简称 KDP)存储库是 kubebuilder SDK 之上的额外一层插件特定工具,通过将实验性的 --pattern=addon
标志传递给 kubebuilder create
命令来启用。它们一起为插件操作符创建了基本代码。在实习期间,我研究了 KDP 和集群插件中的几个功能。
操作符版本检查
即使操作符具有复杂的逻辑,为操作符启用版本检查也有助于使插件不同版本的升级/降级更安全。这是一种将插件版本与知道如何很好地管理它的操作符版本相匹配的方法。大多数插件都有不同的版本,这些版本可能需要不同的管理方式。此功能检查自定义资源中的 addons.k8s.io/min-operator-version
注释,该注释说明了管理该版本所需的最低操作符版本,以对照操作符版本进行检查。如果操作符版本低于所需的最低版本,则操作符会暂停并显示错误,告知用户操作符版本过低。这有助于确保为插件使用正确的操作符。
用于存储清单的 Git 存储库
以前,仅支持本地文件目录和 HTTPS 存储库来存储清单。让插件操作符的创建者能够将清单存储在 GitHub 存储库中,从而加快了开发速度和版本控制。启动控制器时,您可以传递一个标志来指定通道目录的位置。通道目录包含不同版本的清单,控制器从该目录中拉取清单并将其应用于集群。在实习期间,我将其扩展为包含 Git 存储库。
用于临时禁用协调的注释
确保所需状态与实际状态匹配的协调循环会阻止修改集群中的对象。这使得很难在集群中进行实验或调查可能出现的问题,因为所做的任何更改都会立即恢复。我通过允许用户在他们不希望控制器协调的资源上放置 addons.k8s.io/ignore
注释来解决此问题。控制器检查此注释,并且不协调该对象。要恢复协调,可以从资源中删除该注释。
kubebuilder-declarative-pattern 中的非结构化支持
我参与的一个操作符是一个通用控制器,它可以管理多个不需要额外配置的集群插件。为此,操作符不能使用特定类型,并且需要 kubebuilder-declarative-repo 支持使用 unstructured.Unstructured 类型。 kubebuilder-declarative-pattern 中有各种函数无法处理此类型,如果传入的对象不是 addonsv1alpha1.CommonObject
类型,则会返回错误。修改了这些函数以同时处理 unstructured.Unstructured
和 addonsv1alpha.CommonObject
。
工具和 CLI 程序
我还编写了一些命令行程序,可以用来简化插件操作符的使用。它们中的大多数在插件操作符之外也有用途,因为它们试图解决在使用 Kubernetes 时可能出现的特定问题。我鼓励您有时间查看它们!
RBAC 生成器
操作符最大的问题之一是 RBAC。您必须手动查看清单,并为每个资源添加 RBAC 规则,因为它需要具有 RBAC 权限才能在集群内运行时创建、获取、更新和删除清单中的资源。构建 RBAC 生成器自动执行了编写 RBAC 角色和角色绑定的过程。 RBAC 生成器的功能很简单。它接受清单的文件名作为标志。然后,它解析清单并获取资源的 API 组和资源名称,并将其添加到角色中。如果解析了 --out
标志,它会将角色和角色绑定输出到 stdout 或文件。
此外,该工具使您能够通过分离清单中的集群角色来拆分 RBAC。这减轻了操作符被过度授权的安全隐患,因为它需要具有集群角色拥有的所有权限。如果您想自己应用集群角色而不给操作符这些权限,您可以传入 --supervisory
布尔标志,以便生成器不会将这些权限添加到角色。 CLI 程序位于此处。
Kubectl Ownerref
很难一目了然地找出哪些对象是由插件自定义资源创建的。此 kubectl 插件通过显示集群中资源具有 ownerrefs 的所有对象来减轻这种痛苦。您只需将资源的种类和名称作为参数传递给程序,它就会检查集群中的对象,并提供对象的种类、名称和命名空间。通过传入自定义资源的名称和种类,它可以用来获得控制器正在协调的所有对象的总体概述。 CLI 程序位于此处。
插件操作符
要充分理解插件操作符,并对其创建方式进行更改,您必须尝试创建和使用它们。在夏季期间,我们花了一些时间为一些流行的插件构建操作符,例如 Kubernetes 仪表板、flannel、NodeLocalDNS 等。请查看 cluster-addons 存储库,了解不同的插件操作符。在本节中,我将重点介绍一个与其他操作符略有不同的操作符。
通用控制器
通用控制器可以在不需要太多配置的插件之间共享。这可以最大限度地减少集群上的资源消耗,因为它减少了需要运行的控制器数量。此外,您可以使用通用控制器,而不是构建自己的操作符。当您觉得自己的需求增长并且需要更复杂的操作符时,您可以随时使用 kubebuilder 脚手架代码,并从通用操作符停止的地方继续。要使用通用控制器,您可以使用此工具生成 CustomResourceDefinition (CRD) (generic-addon)。您需要传入 kind、group 和通道目录的位置(也可以是 Git 存储库!)。该工具会为您生成 CRD、RBAC 清单和两个自定义资源。
过程如下:
- 创建通用 CRD
- 使用
generic-addon 工具
生成所需的所有清单。
此工具会创建:
- 您的插件的 CRD
- CustomResourceDefinition 的 RBAC 规则
- 应用清单的 RBAC 规则
- 您的插件的自定义资源
- 一个通用自定义资源
通用自定义资源如下所示:
apiVersion: addons.x-k8s.io/v1alpha1
kind: Generic
metadata:
name: generic-sample
spec:
objectKind:
kind: NodeLocalDNS
version: "v1alpha1"
group: addons.x-k8s.io
channel: "../nodelocaldns/channels"
应用这些清单,但请确保先应用 CRD,然后再应用 CR。然后,在您的机器上或集群内运行通用控制器。
如果您有兴趣构建操作符,请查看本指南。
相关链接
- 实习期间完成工作的详细分解
- 插件操作符 (KEP)
- 原始 GSoC 问题
- 为 GSoC 提交的提案
- 所有提交到 kubernetes-sigs/cluster-addons 的内容
- 所有提交到 kubernetes-sigs/kubebuilder-declarative-pattern 的内容
进一步的工作
在 GSoC 期间,集群插件方面的工作确实做了很多。但是,我们需要更多的人构建操作符并在集群中使用它们。我们需要社区更广泛地采用。为您最喜欢的插件构建操作符,并告诉我们进展如何,以及您是否遇到任何问题。请查看此README.md以开始使用。
感谢
我真的要感谢我的导师 Justin Santa Barbara (Google) 和 Leigh Capili (Weaveworks)。我的实习很棒,因为他们很棒。他们为指导树立了黄金标准。他们平易近人,随时可以消除任何困惑。我想我最喜欢的是,他们不仅仅是布置任务,而是就问题所在和可以改进的地方进行了公开讨论。他们真的是最棒的,我希望将来能再次与他们合作!此外,我要非常感谢 Lubomir I. Ivanov 审阅这篇博文!
结论
到目前为止,我学到了很多关于 Go、Kubernetes 内部机制和操作符的知识。我想鼓励大家为开源 (尤其是 Kubernetes :)) 做贡献,无论您的经验水平如何。对我来说,这是一次全面的体验,我已经爱上了这个社区。这是一个很棒的倡议,也是学习和结识优秀人士的好方法。特别感谢 Google 组织这个项目。
如果您对集群插件和了解更多有关插件操作符的信息感兴趣,欢迎加入我们在 Kubernetes #cluster-addons 上的 slack 频道。
Somtochi Onyekwere 是一位热爱为开源做贡献并探索云原生解决方案的软件工程师。