共计 4875 个字符,预计需要花费 13 分钟才能阅读完成。
客座文章最后由红帽服务可靠性工程师 Alexandre Menezes 在 CloudOps 博客上发表
大多数应用程序都须要来自其运行环境的资源:内存、CPU、存储器、网络等等。这些资源中的大多数能够很容易地通明地应用,有些可能不依赖于应用程序。大多数应用程序在部署之前都须要一些后面的配置步骤,并且须要一些(或者很多)非凡的保护工作,这些工作可能与备份、复原、文件压缩、高可用性查看、日志保护、数据库增长和健全例程等相干。例如,在降级时可能须要将它们置于某种非凡状态,以确保它们不会删除用户。
咱们方才形容的所有这些货色,都是应用程序之上的实用技术常识。在软件和服务软件的生命周期中,所有这些操作工作都要反复屡次。当然,很多时候他们有一些脚本来自动化这些工作。然而,如果应用程序在容器中运行,在一个由 Kubernetes 或 OpenShift 编排的 Pod 中呢?有没有更好的办法,来实现自动化呢?能够“容错性好、易于治理和便于察看的松耦合零碎。联合牢靠的自动化伎俩,云原生技术使工程师可能轻松地对系统作出频繁和可预测的重大变更。”(来自云原生定义)
这个问题的答案就是操作器模式(operator pattern)。又称为 Kubernetes Operators。那么,它们是什么呢?如何开发一个?它们能够向咱们的应用程序增加什么?通过将它们公布到操作器核心,它们是如何增加到咱们的软件作为一种服务体验的?
我集体喜爱给出的最好定义是,操作器是 Kubernetes API 的扩大,以自定义资源的模式,由部署后运行在 Pod 中的规范控制器协调 / 治理。仿佛很简单,对吧?让咱们看一下这些局部。
扩大 Kubernetes API
首先,让咱们略微后退一步,试着一点一点地了解它。我想问的第一个问题是,咱们如何与 Kubernetes 互动?咱们应用 kubectl 来从独立治理的角度部署和保护咱们的应用程序,咱们应用 client-go 和其余库来自动化与 Kubernetes API 的通信。好酷。API 给了咱们什么?
让咱们看看 Kubernetes API 给咱们什么:
所有这些个性在原生 Kubernetes 对象之间共享。许多设计良好的操作,如创立、读取、更新和删除、监督端点的性能、身份验证和受权等等。
咱们晓得 Kubernetes 资源构建在定义之上,这些定义来自于这个存储库中的 Kubernetes API:
https://github.com/kubernetes…
在那里咱们能够找到这些资源的组、版本和品种,对吧?这是间接进入名为 TypeMeta 字段的信息。让咱们看一看!
如果咱们失去一个资源,例如 DaemonSet 和运行:
$ kubectl get DaemonSet myDS -o yaml
在一开始,咱们会看到如下内容:
apiVersion: apps/v1
kind: DaemonSet
这通知咱们 DaemonSet 在 apps 组下,版本是 v1,是一种 DaemonSet。咱们在哪里能够找到对应的 golang 类型呢?咱们只须要到存储库并找到 types.go 文档。像下图:
$ tree -L 2
...
├── apps
│ ├── OWNERS
│ ├── v1
│ ├── v1beta1
│ └── v1beta2
...
在 v1 文件夹中,咱们有 types.go,咱们能够寻找 DaemonSet 类型如下:
type DaemonSet struct {
metav1.TypeMeta `json:",inline"`
// Standard object's metadata.
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
// +optional
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// The desired behavior of this daemon set.
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
// +optional
Spec DaemonSetSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`
// The current status of this daemon set. This data may be
// out of date by some window of time.
// Populated by the system.
// Read-only.
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
// +optional
Status DaemonSetStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
}
如果咱们能够以这种形式开发咱们的应用程序,使其成为 Kubernetes 的原生局部,或者至多利用所有这些个性,只需输出 kubectl get myapplication,并依据我的特定需要接管回信息,会怎么样呢?更进一步,如果咱们能创立本人的更新例程和函数呢?如果咱们能够利用嵌入的指标规范,并从 Kubernetes 构建粗浅的见解,就像咱们应用原始资源一样,会怎么样呢?
共享 Kubernetes 提供的所有好货色的很酷的性能是自定义资源(Custom Resources)和自定义资源定义(Custom Resource Definitions)。它们的行为与咱们之前看到的原生 Daemonsets 十分类似。它们是 Kubernetes API 的扩大,容许咱们创立本人的字段,构建完满的数据结构来示意咱们的应用程序需要。它们容许咱们有本人的 API 组、版本和类型。
这里你能够查看无关 CRD 和 API 扩大的更多信息。但咱们曾经实现了一半。咱们还须要什么来实现这些定制资源?控制器(controller)。让咱们检查一下!
控制器:使它成为 Kubernetes 原生
控制器只不过是一个循环。其思维是一个管制循环,在每次迭代中查看某些资源的状态。通过读取所需资源来查看其状态之后,管制循环将运行咱们称为 reconcile 的函数,该函数将活动状态与给定对象的预期状态进行比拟。这是 Kubernetes 的规范工作形式。
如果咱们定义了代表应用程序的自定义对象,包含所有字段和必须的数据结构,那么前面的局部就是这个控制器及其 reconcile 函数。通过运行嵌入咱们之前探讨过的操作常识的自定义逻辑,它的确让咱们可能控制应用程序的状态。
如果你想理解更多对于控制器,可到这里。
Operator SDK:疏导和构建
了解 Kubernetes API 的外部工作原理(合乎 OpenAPI 规范)并不是一项容易的工作。咱们也能够用 API machinery SIG 和控制器运行时库提供的所有工具,来创立与原生控制器运行时完全相同的控制器,以不便操作器框架的创立。在操作器框架提供的工具中,有 operator-sdk 命令行工具。让咱们来看看它是如何帮忙咱们疾速搭建所有必要的工具,以便只关注运算符逻辑的。
初始化一个新的操作器我的项目:
$ mkdir myproject
$ cd myproject
$ operator-sdk init --domain mydomain.com --group myapp --kind MyApp --version v1alpha1
运行后产生一个 go 我的项目,文件夹将包含最小的元素以开发和构建操作器。
.
├── Dockerfile
├── Makefile
├── PROJECT
├── bin
├── config
├── go.mod
├── go.sum
├── hack
└── main.go
咱们有用于构建操作器的根本 Dockerfile,一个具备测试和构建所需的所有自动化的 Makefile,还有一个配置文件夹,其中所有 yaml 工件都将在 Kustomize 和 main.go 的反对下运行,从运行控制器的管理器开始。要为咱们的自定义应用程序增加一个带有控制器的新的 API/CRD 端点,咱们运行上面的例子:
$ operator-sdk create api
--group=myapp
--version=v1alpha1
--kind=MyApp
--resource
--controller
当初咱们有两个新的文件夹:
.
├── Dockerfile
├── Makefile
├── PROJECT
├── api
├── bin
├── config
├── controllers
├── go.mod
├── go.sum
├── hack
└── main.go
文件夹 api 和 controllers。咱们能找到所有主动生成的代码来开始过程。
在 api 中咱们发现:
$ tree -L 2 api
api
└── v1alpha1
├── groupversion_info.go
├── myapp_types.go
└── zz_generated.deepcopy.go
最初在控制器端,咱们有:
$ tree -L 2 controllers
controllers
├── myapp_controller.go
└── suite_test.go
myapp_controller.go 会为咱们提供所有控制器逻辑。
也为你筹备好 reconcile 函数插入你的代码:
func (r *MyAppReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {_ = context.Background()
_ = r.Log.WithValues("myapp", req.NamespacedName)
// your logic here
return ctrl.Result{}, nil}
为了更好地了解这个过程,我强烈推荐两个教程:
kubebuilder 手册。Kubebuilder 刚刚合并到 operator-sdk 中,其中很好的一部分逻辑来自 kubebuilder 我的项目。因而,要更深刻地了解 Kubernetes API 和控制器逻辑,这里可能是最好的终点。
最初,我非常倡议你查看一下 operatoror-sdk 网站,在那里你也能够找到大量的资源和示例。
操作器生命周期管理器:公布操作器
操作器框架中的另一个要害我的项目是 Operator Lifecycle Manager(操作器生命周期管理器),它充当你的软件目录,向 kubernetes 提供一个作为服务应用程序的软件,所有公开公布的操作器都能够从该应用程序中装置。理解我的项目和更多相干信息。
总结
咱们探讨了 Kubernetes 操作器是什么,以及它们是如何由 Kubernetes 自定义资源和控制器这两个根本但弱小的局部组成的。咱们稍微波及了 operator-sdk,它帮忙咱们搭建所有代码,以便轻松开始开发 Kubernetes 原生应用程序,该应用程序将与 api 通信,并管制示意集群内应用程序的自定义资源。咱们倡议在网站上查看 Kubebuilder 手册和 operator-sdk 文档。最初,咱们指出操作器生命周期管理器是所有公共操作器都能够在其中找到的官网目录。
点击浏览网站原文。
CNCF (Cloud Native Computing Foundation) 成立于 2015 年 12 月,隶属于 Linux Foundation,是非营利性组织。
CNCF(云原生计算基金会)致力于培养和保护一个厂商中立的开源生态系统,来推广云原生技术。咱们通过将最前沿的模式民主化,让这些翻新为公众所用。扫描二维码关注 CNCF 微信公众号。