使用 Operator SDK 在 10 分钟内构建 Kubernetes Operator

使用 Operator SDK 创建和部署自定义 Operator 和自定义 Kubernetes 类型非常简单。以下是方法。
137 位读者喜欢这篇文章。
Ships at sea on the web

Kubernetes 中,对象 类似于现实世界中的一项工作或已完成的任务。您可以使用它们来定义常见任务,将它们存储在版本控制系统中,并使用 kubectl apply 应用它们。Kubernetes 确保触发所有必要的步骤,通过创建依赖资源(如 Pod)来运行您的软件,从而将您的声明性描述变为现实。Kubernetes 包含许多内置对象类型,可以使用此工作流程创建,例如 Deployments 和 Services。

借助 Operators,Kubernetes 允许集群维护者或软件提供商定义他们自己的 Kubernetes 对象类型,称为自定义资源定义 (CRD)。这些对象可以像内置对象类型一样由 Kubernetes API 处理。在 Operator 代码内部,作者可以定义如何处理这些自定义对象。

Operator 用户可以使用 kubectl apply 创建此自定义类型的对象,该对象称为自定义资源 (CR)。

CR 有许多不同的用途,从部署少量 Pod 到更复杂的应用程序。想象一下运行 kubectl -f postgres.yml 并获得可供使用的高可用性 PostgreSQL 集群。

本文将使用 Kubernetes Operator 部署一个简单的应用程序,该应用程序由一个 ConfigMap 和一个 Pod 组成。在 CR 中,您可以指定一个 Markdown 字符串,该字符串将转换为基于 HTML5 的演示文稿。(毕竟,谁不想使用 kubectl edit presentation my-presentation 来准备下一次演讲的幻灯片呢?您将在本教程中做到这一点。)

如果您还不熟悉运行 Kubernetes 集群,请阅读 Minikube 入门:笔记本电脑上的 Kubernetes,以便更容易地跟随本操作指南。

安装 Operator SDK

在开始之前,我假设您已经登录到要使用的 Kubernetes 集群。您还必须安装 Golang 1.13 或更高版本。

从 GitHub 上的 Operator SDK 发布页面为您的计算机安装最新版本的 Operator SDK,然后使其可执行并将其放入您的 PATH 中,命名为 operator-sdk

$ wget https://github.com/operator-framework/operator-sdk/releases/download/v0.15.2/operator-sdk-v0.15.2-x86_64-linux-gnu
$ sudo mv operator-sdk-v0.15.2-x86_64-linux-gnu /usr/local/bin/operator-sdk
$ sudo chmod +x /usr/local/bin/operator-sdk

引导新的 Kubernetes Operator

现在您已准备好开始 Operator 开发!operator-sdk 二进制文件可用于生成许多不同 Operator 通用的样板代码。这使每个 Operator 作者都可以专注于开发自己的逻辑,使其与其他 Operator 区分开来,而不是一遍又一遍地重复发明 Operator 逻辑。要生成样板代码,请在要创建 Operator 的文件夹中运行以下命令。Operator SDK 将生成一个以您指定的 Operator 名称命名的文件夹

$ cd ~/operators
$ operator-sdk new presentation-example-operator --type go --repo github.com/NautiluX/presentation-example-operator

将 repo 参数指向您要用于 Go 模块的存储库。此命令将下载一些依赖项,创建文件夹 presentation-example-operator,并创建基本项目设置。接下来,生成一些 Go 代码来表示您的自定义资源定义(Operator 的“API”)

$ cd presentation-example-operator
$ operator-sdk add api --kind Presentation --api-version presentation.example.com/v1alpha1

此命令指定 CRD 将被称为 Presentation,并创建文件 pkg/apis/presentation/v1alpha1/presentation_types.go,您可以修改该文件以指定 CRD 的输入参数。对于此示例应用程序,您只需要一个参数,名为 Markdown

...
type PresentationSpec struct {
	// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
	// Important: Run "operator-sdk generate k8s" to regenerate code after modifying this file
	// Add custom validation using kubebuilder tags: https://book-v1.book.kubebuilder.io/beyond_basics/generating_crd.html

	// This field can be used to define your presentation in markdown. Use --- to separate slides.
	Markdown string `json:"markdown,omitempty"`
}
...

请注意,这里唯一不同的是字段的注释和 Markdown 字段的声明。文件的其余部分由 Operator SDK 生成,可以根据您的需要进行调整。

现在,从此定义和一些 Go 代码生成实际的 CRD。为此,请运行以下命令

$ operator-sdk generate crds
$ operator-sdk generate k8s

deploy/crds/presentation.example.com_presentations_crd.yaml 中,您将找到 CRD,您可以使用以下命令将其安装在您的集群上

$ kubectl apply -f deploy/crds/presentation.example.com_presentations_crd.yaml

Operator 将运行一个所谓的 reconcile-loop,它确保每次创建 Operator CRD 中的 CR 时都会执行一段代码。这段代码存在于控制器中。Operator 要操作的每个 CRD 都将在 Operator 中有一个相应的控制器。在本例中,您只需要一个控制器,因为您只有一个 CRD。但是,通常在一个 Operator 中打包多个 CRD 和多个控制器。要为新创建的 CRD 创建控制器,请运行以下命令

$ operator-sdk add controller --kind Presentation --api-version presentation.example.com/v1alpha1

现在,您可以将您自己的逻辑添加到生成的文件 pkg/controller/add_presentation.go 中的 Reconcile 函数中。每次创建、更改或删除 Presentation CR 时,都会调用此函数。每当它返回错误时,相同的请求将再次运行该函数。

生成后,它包含创建 Pod 的示例代码,您可以对其进行调整以满足您的需求。您可以在此 示例 Operator 的 Git 存储库中找到调用函数的完整实现。此代码显示了 Reconcile 函数中的工作流程

...
	configMapChanged, err := r.ensureLatestConfigMap(instance)
	if err != nil {
		return reconcile.Result{}, err
	}
	err = r.ensureLatestPod(instance, configMapChanged)
	if err != nil {
		return reconcile.Result{}, err
	}
	return reconcile.Result{}, nil
...

首先,它确保存在包含当前 Markdown 的 ConfigMap。然后,它确保创建一个 Pod,其中挂载了最新版本的 ConfigMap。

快速迭代:在集群外部运行 Operator

Operator 可以像任何其他应用程序一样部署到集群。但是,为了在开发期间进行快速迭代,在本地计算机上运行它很方便。这样,您可以立即看到输出,并且可以通过简单地按 Ctrl+C 来停止它。要启动 Operator,请运行以下命令

$ operator-sdk run --local

现在,您可以从单独的终端创建您的第一个演示文稿,并观看 Operator 的工作

$ kubectl apply -f <(echo "
apiVersion: presentation.example.com/v1alpha1
kind: Presentation
metadata:
  name: example-presentation
spec:
  markdown: |
    # My First Presentation
    ---
    ## Test slide

    * Test
    ---
")

这将启动一个 Pod 并创建一个 ConfigMap,正如您在上面的 Go 代码中定义的那样

$ kubectl get pods
NAME                       READY   STATUS    RESTARTS   AGE
example-presentation-pod   1/1     Running   0          103s

$ kubectl get configmaps
NAME                          DATA   AGE
example-presentation-config   1      104s

要访问这个小程序并查看您的幻灯片,您需要从 Pod 内部端口转发端口 80。在实际应用程序中,您可以从 Operator 代码创建服务资源

$ kubectl port-forward example-presentation-pod 8080:80

现在,您可以通过在浏览器中导航到 http://localhost:8080 来查看您的演示文稿。每当您更新 Markdown(例如,使用 kubectl edit presentation example-presentation)时,页面将在 Pod 重新部署后更新(并且您需要再次重新启动端口转发)。

部署 Operator

要部署 Operator,您需要创建一个 Kubernetes 集群可以访问的容器镜像。幸运的是,Operator SDK 包含用于创建此镜像的工具。构建完成后,您可以使用 Docker CLI 推送镜像

$ operator-sdk build manueldewald/presentation-example-operator
$ docker push manueldewald/presentation-example-operator

现在,您需要调整先前由 Operator SDK 在 deploy/operator.yaml 中生成的部署配置

$ sed -i 's|REPLACE_IMAGE|manueldewald/presentation-example-operator|g' deploy/operator.yaml

最后,您可以使用 kubectl apply -f deploy/operator.yml 部署 Operator,它将在集群内部开始运行。现在您可以尝试更改您的演示文稿或部署新的演示文稿。

结论

使用 Operator SDK 创建和部署自定义 Operator 和自定义 Kubernetes 类型非常简单。

如果您喜欢使用 Markdown 创建幻灯片的想法,请查看 Remark.js,它在本示例 Operator 中使用。您不需要运行 Kubernetes 集群即可使用它;打开一个简单的 HTML 文件就足够了。但是,如果您想出于任何原因从 Kubernetes 集群进行演示,现在您知道该怎么做了。

接下来阅读什么
标签
User profile image.
Manuel 于 2013 年在德国海德堡完成应用计算机科学硕士学位,并在此后不久开始担任软件开发人员。他有兴趣使用和结合各种技术来构建新的酷炫的东西,努力使生活(包括他自己的生活)更轻松。

4 条评论

实现起来相当复杂,但肯定会在下周的某个时候尝试一下。感谢分享 :)

我完全同意

嘿 Manuel,感谢您如此精彩的关于 Operators 的演示。我们可以在 OpenShift 环境中尝试这个 Operator 吗?

Creative Commons License本作品根据 Creative Commons Attribution-Share Alike 4.0 International License 获得许可。
© . All rights reserved.