Open daylight 容器技术结合 容器operator_kubernetes

Operator 是 Kubernetes 的重要扩展机制,本文从 Operator 概念开始,解释并实践了 Operator 的创建,希望可以帮助大家进一步了解其概念和作用。

Operator

Open daylight 容器技术结合 容器operator_linux_02

Operator 概念

Kubernetes 文档中 Operator 定义是这样的:

Operator 模式旨在捕获(正在管理一个或一组服务的)运维人员的关键目标。负责特定应用和 service 的运维人员,在系统应该如何运行、如何部署以及出现问题时如何处理等方面有深入的了解。

在 Kubernetes 上运行工作负载的人们都喜欢通过自动化来处理重复的任务。Operator 模式会封装我们编写的(Kubernetes 本身提供功能以外的)任务自动化代码。

Operator 的工作方式

《Kubernetes Operator》一书定义为:

Operator 通过扩展 Kubernetes 控制平面和 API 进行工作。Operator 将一个 endpoint(称为自定义资源 CR)添加到 Kubernetes API 中,该 endpoint 还包含一个监控和维护新类型资源的控制平面组件。

Operator 和 Controller 之间的联系是什么

Operator 由一组监听 Kubernetes 资源的 Controller 组成。Controller 可以实现调协(reconciliation loop),另外每个 Controller 都负责监视一个特定资源,当创建、更新或删除受监视的资源时就会触发调协。

Operator 创建工具

有一些用于创建 Kubernetes Operator 的开源项目,例如:

  • Operator SDK
  • Kubebuilder
  • KUDO
  • Metacontroller

下文将介绍 Operator-SDK 和 Kubebuilder,它们是我们最常用到的工具,这二者现在还在互相融合。

Kubernetes Controller

Open daylight 容器技术结合 容器operator_linux_02

Controller 是一个非终止循环,用于调节系统状态,它会使 current 状态尽可能接近 desired 状态(亦称:调协,Reconciliation loop)。

Open daylight 容器技术结合 容器operator_kubernetes_04

reconciliation loop

我们设定温度,等于告诉恒温器我们所需状态。实际室温是当前状态。通过打开或关闭设备,恒温器会让当前状态更接近所需状态。

在 Kubernetes 中,有一组内置的 Controller 在主节点中的 controller-manager 内部运行。

Open daylight 容器技术结合 容器operator_linux_05

内置 Controller

与内置 Controller 类似,我们可以创建自己的自定义 Operator 来管理应用程序资源的状态,无论是无状态还是有状态 。

创建 Operator

Open daylight 容器技术结合 容器operator_linux_02

接下来是创建 Operator—Operator-SDK Scaffolding。

什么是 Operator-SDK?

Operator-SDK 是 Operator Framework 的组件,用于创建 Kubernetes 本机应用程序所需的代码。

Open daylight 容器技术结合 容器operator_docker_07

Operator Framework 是一个开放源代码工具包,使用有效、自动化和可扩展的方式管理 Kubernetes 本地应用程序。

  • Operator Framework 包括:
  • Operator SDK
  • Operator Lifecycle Management(OLM)
  • Operator Metering

我应该创建哪种类型的运算符?

Operator-SDK 允许我们创建三种不同类型的运算符:

  • Helm:我们可以创建一个 Operator,使用 Helm 图表并管理创建的 Kubernetes 资源生命周期(CRUD)。
  • Ansible:与 Helm 类似,我们可以创建 Operator 来管理 Ansible playbook 和 role,以对跟踪的 Kubernetes 资源(通常是 CR)更改做出反应。
  • Go:与 Helm 和 Ansible 不同,基于 Go-lang 的 Operator 需要创建自定义逻辑,以监控资源以及协调应用程序状态。相对而言,它更为复杂,但它可以提供自由灵活的方式来实现我们想要的逻辑,当然,这需要我们比较熟悉 Go 编程语言。

Operator Libraries

Operator 利用 library 与 Kubernetes API 进行交互,例如 client-go 和 controller-runtime。了解它们的工作方式(Informer、Lister、WorkQueue、runtime.Object 和 Scheme)非常重要,如果创建 Go Operator,那就需要编写代码。

Operator-SDK 和 Kubebuilder 融合

在 GitHub 上,层级有两个不同的开源项目用于创建 Operator,现在它们为实现同一目标而共同努力。它们之前生成代码,是不同的项目结构,但现在可以使用相同的结构样式。

Operator 例子

Operator 通常会对资源(Deployment、Job、Secret、Service、Pod 等)进行 CRUD 操作,并更新它们的状态。利用 go 模板或第三方库(例如 Manisfestival)可以使用程序模板或声明性方法来创建或编辑资源。

GitHub 上有一个不错的精选列表,叫 Awesome Operators,它有很多 Operator 脚手架工具(scaffolding tool)创建的不同项目。

列表地址:github.com/operator-framework/awesome-operators

Operator Hub

Kubernetes 社区创建了一个 Operator 托管场所,称为 Operator Hub。在这里,我们可以发布我们的 Operator,类似于其他 Hub,例如 Docker、Helm 等。

Helm vs Operator

大家可能有这么一个疑问,如果使用 Operator 管理 Kubernetes 生命周期资源(例如 CRUD 操作),为什么不用 Helm?我们可以这么理解,Helm 是针对第 1 天的操作,而 Operator 则针对第 2 天的操作。

  • 第 0 天:在软件开发中,它代表了设计阶段,在此阶段我们收集解决方案的所有要求。
  • 第 1 天:这是我们首次安装应用程序和基础架构的时间。
  • 第 2 天:这个时间我们在管理生产中应用程序和软件的生命周期,以确保一切都正常运行,如备份、还原、故障转移、后备。

例如,我们通过 Helm 图表安装了一个应用程序(假设它创建了 Deployment、Service 和 Ingress),然后不小心删除了 Service,应用程序将停止运行。从 Helm 角度来看,在应用新配置之前,它看上去是正常的,我们不会意识到更改。这就是 Operator 发挥作用的地方,在这个例子中,如果有人误删除了 Service,并且 Operator 正在监控该资源,它将在恢复过程中重新创建,因此应用程序将恢复正常。Helm 和 Operators 是互补的,不是互斥的。

Open daylight 容器技术结合 容器operator_linux_08

Operation Days

一个简单的 CI/CD Operator

Open daylight 容器技术结合 容器operator_linux_02

现在开始创建一个简单的 CI/CD Operator,我们可以在 GitHub、Bitbucket 存储库中获取源代码,构建镜像,将其推送到 Docker 注册表,再部署在 Kubernetes 上。

目的

一定程度的自动化可以减少我们的工作量,Operator 就可以帮助我们有更多的时间工作,并改善和增强其他功能。

创建 Kubernetes 集群测试 Operator

首先,我们创建 Kubernetes 集群,以便部署自定义 Operator。我们使用 KinD,这是一个使用 Docker 容器创建 Kubernetes 集群的开源工具。

创建 KinD 集群非常简单,我们创建一个具有一个主节点、两个工作节点和一个 docker 注册表的集群,以便我们构建、推送和部署 Operator 到 Kubernetes 中。

这里创建了一个 GitHub Gist,它使用简单的 bash 脚本。对了,作为运行脚本的先决条件,需要在计算机上安装 Docker 引擎(engine)和 kubectl。

Open daylight 容器技术结合 容器operator_java_10

运行 KinD 集群

Open daylight 容器技术结合 容器operator_kubernetes_11

在本地计算机上执行上述脚本后,我们就有了一个功能齐全的 Kubernetes 集群。另外,集群的每个节点都有一个已安装的目录,以备将来需要创建持久卷时使用。

CI/CD Operator 架构 

下图是 CI/CD Operator 的体系结构拓扑,它描述了 Operator 安装到 Kubernetes 集群后是如何工作的。

Open daylight 容器技术结合 容器operator_java_12

a)在 Kubernetes 集群上安装了 Operator 后,human Operator 或管道(pipeline)便会通过 kubectl 创建自定义资源。

b)Operator 控制器循环(controllers loop)监控通过 API Server 创建的资源,并触发协调方法。

c)CI 控制器(controller)将触发协调方法,该方法会创建 Job 以构建代码。

d)Job 包含一个带有 Git-Sync 的 init 容器,将 Git 存储库代码克隆到容器上的工作区目录中。

e)初始化容器完成其任务时,带有 Kaniko 镜像的主容器将构建代码并将其推送到内部 Docker 注册表。

f)Job完成(complete 状态)后,将启动 CD 控制器以创建 Deployment 资源。

g)Deployment 被创建后,会被步骤 e 中推送的镜像从注册表中拉取。目前还没有为应用程序创建 Service 和 Ingress。

生成 Operator 代码

我们使用 Operator-SDK CLI 生成样板代码,并开始对其进行迭代。我们要先在本地计算机上安装 Operator-SDK、Go-lang 和 Git。

Open daylight 容器技术结合 容器operator_python_13

现在我们已经搭建了 Operator 代码,最初生成的代码能够监视自定义资源,然后创建一个由 Operator 管理的简单 Pod。

下一步:创建 type 或数据结构,我们再将其作为 Operator 逻辑的一部分实现。在示例中有几个属性,如 GitHub 存储库 endpoint、连接到凭据的 SSH secret、在 mono 存储库下的 subContext(subPath)、Docker Registry 中的镜像目标以及 GitHub 分支获取并构建代码。

Open daylight 容器技术结合 容器operator_python_14

CIBuild Type

在控制器(controller)中定义了数据结构(Spec)和自定义逻辑后,就可以进行构建并推送到注册表。

Open daylight 容器技术结合 容器operator_linux_15

成功构建 Operator 后,我们就可以在 Kubernetes 上运行、部署它了。

Open daylight 容器技术结合 容器operator_linux_16

一旦 Operator 启动并运行,我们为 GitHub、Bitbucket 和 CI/CD 自定义资源创建一个 secret 。

Open daylight 容器技术结合 容器operator_python_17

Open daylight 容器技术结合 容器operator_docker_18

Bitbucket SSH 配置

Open daylight 容器技术结合 容器operator_kubernetes_19

GitHub SSH 配置

这样,我们在 Kubernetes 上启动并运行 Operator 和 controller,再由 Operator 创建的 Job(git-sync)复制源代码的 Git secret。接着,我们创建自定义资源(CR),将 CR 安装到 Kubernetes API 扩展中。CI controller 将调用和解方法(reconcile method)来创建 Job,以构建、push 容器到 Docker 注册表。Job 完成后,CD controller 将基于注册表提取镜像来创建应用程序 deployment 资源。

Open daylight 容器技术结合 容器operator_python_20

Open daylight 容器技术结合 容器operator_linux_21

Ace 应用程序

Open daylight 容器技术结合 容器operator_python_22

Java 应用程序

配置 Admission Webhook

Open daylight 容器技术结合 容器operator_linux_02

Admission Webhook 是一种用于接收准入请求并对其进行处理的 HTTP 回调机制。Admission Webhook 有两种类型:validating 和 mutating 。

Validating webhook 可用于执行超出 OpenAPI 架构验证功能的验证,例如确保字段在常见后是不可变的,或者对向 API Server 发出请求的用户进行更高级别的权限检查。

通过 Validating admission webhook,我们可以拒绝自定义准入策略的请求。

Mutating webhook 常用于默认设置,在创建时往在资源中添加未设置字段的默认值。

Mutating webhook 是 Istio 将 Sidecar proxy 自动注入用户 Pod 的方法。

Open daylight 容器技术结合 容器operator_kubernetes_24

Mutating and Validating Webhook

为了使 Webhook 正常工作,我们需要在 Kubernetes 上安装 Cert Manager,并在 Operator 的 Dockerfile 中设置环境属性 ENABLE_WEBHOOKS = true,以便 controller 启用 Webhook 逻辑。

Cert-manager 是 Kubernetes 的附加组件,用于自动管理和颁发各种发行来源的 TLS 证书。它可以确保证书有效并定期更新,在到期前的适当时间还会更新证书。

安装 Cert Manager:

Open daylight 容器技术结合 容器operator_java_25

运行上述命令后,将在 cert-manager 命名空间(cert-manager、ca-injector 和 webhook)中创建具有 3 个 deployment 的新命名空间。

Open daylight 容器技术结合 容器operator_linux_26

cert-manager 对象

总结

Open daylight 容器技术结合 容器operator_linux_02

希望这篇文章对大家了解 Operator 有帮助。Kubernetes 上的几乎所有内容都依赖于控制器(controller),掌握它可以减少我们了解 Kubernetes 生态系统中其他项目的时间。