5.6. 基于 Helm 的 Operator
5.6.1. 开始使用基于 Helm 的 Operator 的 Operator SDK
Operator SDK 包括生成一个 Operator 项目的选项,它利用现有 Helm chart 将 Kubernetes 资源部署为统一应用程序,而无需编写任何 Go 代码。
如需演示使用 Operator SDK 提供的工具和库来设置并运行基于 Helm 的 Operator 的基本知识,Operator 开发人员可以为 Nginx 构建一个基于 Helm 的 Operator 示例,并将它部署到集群中。
5.6.1.1. 先决条件
- 已安装 operator SDK CLI
-
已安装 OpenShift CLI(
oc
)v4.10+ -
使用具有
cluster-admin
权限的oc
登录到 OpenShift Container Platform 4.10 集群 - 要允许集群拉取镜像,推送镜像的存储库必须设置为公共的存储库,或必须配置一个镜像 pull secret
5.6.1.2. 创建并部署基于 Helm 的 Operator
您可以使用 Operator SDK 为 Nginx 构建和部署简单基于 Helm 的 Operator。
流程
创建一个项目。
创建您的项目目录:
$ mkdir nginx-operator
切换到项目所在的目录:
$ cd nginx-operator
使用
helm
插件运行operator-sdk init
命令以初始化项目:$ operator-sdk init \ --plugins=helm
创建 API。
创建简单的 Nginx API:
$ operator-sdk create api \ --group demo \ --version v1 \ --kind Nginx
此 API 使用
helm create
命令的内置 Helm Chart 网卡。构建并推送 Operator 镜像。
使用默认的
Makefile
目标来构建和推送 Operator。使用镜像的 pull spec 设置IMG
,该 spec 使用您可推送到的 registry:$ make docker-build docker-push IMG=<registry>/<user>/<image_name>:<tag>
运行 Operator。
安装 CRD:
$ make install
将项目部署到集群中。将
IMG
设置为您推送的镜像:$ make deploy IMG=<registry>/<user>/<image_name>:<tag>
添加安全性上下文约束(SCC)。
Nginx 服务帐户需要特权访问权限才能在 OpenShift Container Platform 中运行。将以下 SCC 添加到
nginx-sample
pod 的服务帐户中:$ oc adm policy add-scc-to-user \ anyuid system:serviceaccount:nginx-operator-system:nginx-sample
创建示例自定义资源(CR)。
创建一个示例 CR:
$ oc apply -f config/samples/demo_v1_nginx.yaml \ -n nginx-operator-system
查看 CR 协调 Operator:
$ oc logs deployment.apps/nginx-operator-controller-manager \ -c manager \ -n nginx-operator-system
删除 CR
运行以下命令来删除 CR:
$ oc delete -f config/samples/demo_v1_nginx -n nginx-operator-system
清理。
运行以下命令清理在此流程中创建的资源:
$ make undeploy
5.6.1.3. 后续步骤
- 如需更深入地了解如何构建基于 Helm 的 Operator,请参阅基于 Helm 的 Operator SDK 指南。
5.6.2. 基于 Helm 的 Operator 的 operator SDK 指南
Operator 开发人员可以利用 Operator SDK 中的 Helm 支持来为 Nginx 构建基于 Helm 的 Operator 示例,并管理其生命周期。本教程介绍了以下过程:
- 创建 Nginx 部署
-
确保部署大小与
Nginx
自定义资源(CR)spec 指定的大小相同 -
使用 status writer 带有
nginx
Pod 的名称来更新Nginx
CR 状态
通过以下两个 Operator Framework 核心组件来完成此过程:
- Operator SDK
-
operator-sdk
CLI 工具和controller-runtime
库 API - Operator Lifecycle Manager (OLM)
- 集群中 Operator 的安装、升级和基于角色的访问控制(RBAC)
本教程的内容比基于 Helm 的 Operator 开始使用 Operator SDK的内容更详细。
5.6.2.1. 先决条件
- 已安装 operator SDK CLI
-
已安装 OpenShift CLI(
oc
)v4.10+ -
使用具有
cluster-admin
权限的oc
登录到 OpenShift Container Platform 4.10 集群 - 要允许集群拉取镜像,推送镜像的存储库必须设置为公共的存储库,或必须配置一个镜像 pull secret
5.6.2.2. 创建一个项目
使用 Operator SDK CLI 创建名为 nginx-operator
的项目。
流程
为项目创建一个目录:
$ mkdir -p $HOME/projects/nginx-operator
进入该目录:
$ cd $HOME/projects/nginx-operator
使用
helm
插件运行operator-sdk init
命令以初始化项目:$ operator-sdk init \ --plugins=helm \ --domain=example.com \ --group=demo \ --version=v1 \ --kind=Nginx
注意默认情况下,
helm
插件使用样板 Helm Chart 初始化项目。您可以使用其他标记(如--helm-chart
标志)使用现有 Helm chart 初始化项目。init
命令创建nginx-operator
项目,专门用于监视 API 版本为example.com/v1
和 kindNginx
的资源。-
对于基于 Helm 的项目,
init
命令根据 chart 的默认清单部署的资源,在config/rbac/role.yaml
文件中生成 RBAC 规则。验证此文件生成的规则是否满足 Operator 的权限要求。
5.6.2.2.1. 现有 Helm chart
您可以使用以下标记,而不是使用样板 Helm Chart 创建项目,而是使用现有 chart(可以从本地文件系统或远程 Chart 仓库中)使用现有 chart:
-
--helm-chart
-
--helm-chart-repo
-
--helm-chart-version
如果指定了 --helm-chart
标志,--group
、--version
和 --kind
标志将变为可选。如果保留未设置,则使用以下默认值:
标记 | 值 |
---|---|
|
|
|
|
|
|
| 从指定的 chart 中分离 |
如果 --helm-chart
标志指定本地 chart 归档,如 example-chart-1.2.0.tgz
或目录,则 chart 被验证并解包或复制到项目中。否则,Operator SDK 会尝试从远程存储库中获取 chart。
如果没有通过 --helm-chart-repo
标志指定自定义存储库 URL,则支持以下 chart 引用格式:
格式 | 描述 |
---|---|
|
从名为 |
| 通过指定的 URL 获取 Helm Chart 归档。 |
如果自定义仓库 URL 由 --helm-chart-repo
指定,则支持以下 chart 引用格式:
格式 | 描述 |
---|---|
|
在由 |
如果 --helm-chart-version
标志未设置,Operator SDK 会获取最新可用的 Helm Chart 版本。否则,它会获取指定的版本。当使用 --helm-chart
标记指定一个特定版本(例如一个本地路径或 URL)的 chart 时,--helm-chart-version
标志不会被使用。
如需更多详细信息和示例,请运行:
$ operator-sdk init --plugins helm --help
5.6.2.2.2. PROJECT 文件
operator-sdk init
命令生成的文件中是一个 Kubebuilder PROJECT
文件。从项目 root 运行的后续 operator-sdk
命令以及 help
输出可读取该文件,并注意项目类型是 Helm。例如:
domain: example.com layout: - helm.sdk.operatorframework.io/v1 plugins: manifests.sdk.operatorframework.io/v2: {} scorecard.sdk.operatorframework.io/v2: {} sdk.x-openshift.io/v1: {} projectName: nginx-operator resources: - api: crdVersion: v1 namespaced: true domain: example.com group: demo kind: Nginx version: v1 version: "3"
5.6.2.3. 了解 Operator 逻辑
在本例中,nginx-operator
项目会针对每个 Nginx
自定义资源 (CR) 执行以下协调逻辑:
- 如果尚无 Nginx 部署,请创建一个。
- 如果尚无 Nginx 服务,请创建一个。
- 如果被启用且不存在,请创建一个 Nginx ingress。
-
确保部署、服务和可选入口与
Nginx
CR 指定的配置匹配,如副本数、镜像和服务类型。
默认情况下,nginx-operator
项目会监视 Vginx
资源事件,如 watches.yaml
文件中所示,并使用指定 Chart 执行 Helm 发行版本:
# Use the 'create api' subcommand to add watches to this file. - group: demo version: v1 kind: Nginx chart: helm-charts/nginx # +kubebuilder:scaffold:watch
5.6.2.3.1. Helm chart 示例
创建 Helm Operator 项目后,Operator SDK 会创建一个 Helm Chart 示例,其中包含一组模板,用于简单的 Nginx 发行版本。
本例中,针对部署、服务和 Ingress 资源提供了模板,另外还有 NOTES.txt
模板,Helm Chart 开发人员可利用该模板传达有关发型版本的实用信息。
如果您对 Helm chart 有一定的了解,请参阅 Helm 开发人员文档。
5.6.2.3.2. 修改自定义资源规格
Helm 使用名为 values 的概念来自定义 Helm Chart 的默认配置,该 chart 在 values.yaml
文件中定义。
您可以通过在自定义资源(CR)spec 中设置所需的值来覆盖这些默认值。以副本数量为例。
流程
在默认情况下,
helm-charts/nginx/values.yaml
文件有一个设置为1
的名为replicaCount
的值。要在部署中有两个 Nginx 实例,您的 CR spec 必须包含replicaCount: 2
。编辑
config/samples/demo_v1_nginx.yaml
文件以设置replicaCount: 2
:apiVersion: demo.example.com/v1 kind: Nginx metadata: name: nginx-sample ... spec: ... replicaCount: 2
同样,服务端口默认设置为
80
。要使用8080
,编辑config/samples/demo_v1_nginx.yaml
文件来设置spec.port: 8080
,它会添加服务端口覆盖:apiVersion: demo.example.com/v1 kind: Nginx metadata: name: nginx-sample spec: replicaCount: 2 service: port: 8080
Helm Operator 应用整个 spec,将其视为 values 文件内容,与 helm install -f ./overrides.yaml
命令的工作方式类似。
5.6.2.4. 启用代理支持
Operator 作者可开发支持网络代理的 Operator。集群管理员配置对 Operator Lifecycle Manager (OLM) 处理的环境变量的代理支持。要支持代理集群,Operator 必须检查以下标准代理变量的环境,并将值传递给 Operands:
-
HTTP_PROXY
-
HTTPS_PROXY
-
NO_PROXY
本教程使用 HTTP_PROXY
作为示例环境变量。
先决条件
- 启用了集群范围的出口代理的集群。
流程
通过添加
overrideValues
字段来编辑watches.yaml
文件,使其包含基于环境变量的覆盖:... - group: demo.example.com version: v1alpha1 kind: Nginx chart: helm-charts/nginx overrideValues: proxy.http: $HTTP_PROXY ...
在
helm-charts/nginx/values.yaml
文件中添加proxy.http
值:... proxy: http: "" https: "" no_proxy: ""
要确保 Chart 模板支持使用变量,请编辑
helm-charts/nginx/templates/deployment.yaml
文件中的 chart 模板,使其包含以下内容:containers: - name: {{ .Chart.Name }} securityContext: - toYaml {{ .Values.securityContext | nindent 12 }} image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" imagePullPolicy: {{ .Values.image.pullPolicy }} env: - name: http_proxy value: "{{ .Values.proxy.http }}"
通过在
config/manager/manager.yaml
文件中添加以下内容来设置 Operator 部署上的环境变量:containers: - args: - --leader-elect - --leader-election-id=ansible-proxy-demo image: controller:latest name: manager env: - name: "HTTP_PROXY" value: "http_proxy_test"
5.6.2.5. 运行 Operator
您可以使用 Operator SDK CLI 构建和运行 Operator:
- 作为 Go 程序在集群外本地运行。
- 作为集群的部署运行。
- 捆绑 Operator,并使用 Operator Lifecycle Manager(OLM)在集群中部署。
5.6.2.5.1. 在集群外本地运行
您可以作为集群外的 Go 程序运行您的 Operator 项目。这可以加快部署和测试的速度,对于开发非常有用。
流程
运行以下命令,以在
~/.kube/config
文件中配置的集群中安装自定义资源定义(CRD),并在本地运行 Operator:$ make install run
输出示例
... {"level":"info","ts":1612652419.9289865,"logger":"controller-runtime.metrics","msg":"metrics server is starting to listen","addr":":8080"} {"level":"info","ts":1612652419.9296563,"logger":"helm.controller","msg":"Watching resource","apiVersion":"demo.example.com/v1","kind":"Nginx","namespace":"","reconcilePeriod":"1m0s"} {"level":"info","ts":1612652419.929983,"logger":"controller-runtime.manager","msg":"starting metrics server","path":"/metrics"} {"level":"info","ts":1612652419.930015,"logger":"controller-runtime.manager.controller.nginx-controller","msg":"Starting EventSource","source":"kind source: demo.example.com/v1, Kind=Nginx"} {"level":"info","ts":1612652420.2307851,"logger":"controller-runtime.manager.controller.nginx-controller","msg":"Starting Controller"} {"level":"info","ts":1612652420.2309358,"logger":"controller-runtime.manager.controller.nginx-controller","msg":"Starting workers","worker count":8}
5.6.2.5.2. 作为集群的部署运行
您可以作为一个部署在集群中运行 Operator 项目。
流程
运行以下
make
命令来构建和推送 Operator 镜像。在以下步骤中修改IMG
参数来引用您可访问的库。您可以获取在存储库站点(如 Quay.io)存储容器的帐户。构建镜像:
$ make docker-build IMG=<registry>/<user>/<image_name>:<tag>
注意由 SDK 为 Operator 生成的 Dockerfile 需要为
go build
明确引用GOARCH=amd64
。这可以在非 AMD64 构架中使用GOARCH=$TARGETARCH
。Docker 自动将环境变量设置为-platform
指定的值。对于 Buildah,需要使用-build-arg
来实现这一目的。如需更多信息,请参阅多个架构。将镜像推送到存储库:
$ make docker-push IMG=<registry>/<user>/<image_name>:<tag>
注意镜像的名称和标签,如
IMG=<registry> /<user> /<image_name>:<tag>
,在两个命令中都可在您的 Makefile 中设置。修改IMG ?= controller:latest
值来设置您的默认镜像名称。
运行以下命令来部署 Operator:
$ make deploy IMG=<registry>/<user>/<image_name>:<tag>
默认情况下,这个命令会创建一个带有 Operator 项目名称的命名空间,格式为
<project_name>-system
,用于部署。此命令还从config/rbac
安装 RBAC 清单。验证 Operator 是否正在运行:
$ oc get deployment -n <project_name>-system
输出示例
NAME READY UP-TO-DATE AVAILABLE AGE <project_name>-controller-manager 1/1 1 1 8m
5.6.2.5.3. 捆绑 Operator 并使用 Operator Lifecycle Manager 进行部署
5.6.2.5.3.1. 捆绑 Operator
Operator 捆绑包格式是 Operator SDK 和 Operator Lifecycle Manager(OLM)的默认打包方法。您可以使用 Operator SDK 来构建和推送 Operator 项目作为捆绑包镜像,使 Operator 可供 OLM 使用。
先决条件
- 在开发工作站上安装 operator SDK CLI
-
已安装 OpenShift CLI(
oc
)v4.10+ - 使用 Operator SDK 初始化 operator 项目
流程
在 Operator 项目目录中运行以下
make
命令来构建和推送 Operator 镜像。在以下步骤中修改IMG
参数来引用您可访问的库。您可以获取在存储库站点(如 Quay.io)存储容器的帐户。构建镜像:
$ make docker-build IMG=<registry>/<user>/<operator_image_name>:<tag>
注意由 SDK 为 Operator 生成的 Dockerfile 需要为
go build
明确引用GOARCH=amd64
。这可以在非 AMD64 构架中使用GOARCH=$TARGETARCH
。Docker 自动将环境变量设置为-platform
指定的值。对于 Buildah,需要使用-build-arg
来实现这一目的。如需更多信息,请参阅多个架构。将镜像推送到存储库:
$ make docker-push IMG=<registry>/<user>/<operator_image_name>:<tag>
运行
make bundle
命令创建 Operator 捆绑包清单,该命令调用多个命令,其中包括 Operator SDKgenerate bundle
和bundle validate
子命令:$ make bundle IMG=<registry>/<user>/<operator_image_name>:<tag>
Operator 的捆绑包清单描述了如何显示、创建和管理应用程序。
make bundle
命令在 Operator 项目中创建以下文件和目录:-
包含
ClusterServiceVersion
对象的捆绑包清单目录,名为bundle/manifests
-
名为
bundle/metadata
的捆绑包元数据目录 -
config/crd
目录中的所有自定义资源定义(CRD) -
一个 Dockerfile
bundle.Dockerfile
然后,使用
operator-sdk bundle validate
自动验证这些文件,以确保磁盘上的捆绑包的格式是正确的。-
包含
运行以下命令来构建和推送捆绑包镜像。OLM 使用索引镜像来消耗 Operator 捆绑包,该镜像引用一个或多个捆绑包镜像。
构建捆绑包镜像。使用您要推送镜像的 registry、用户命名空间和镜像标签的详情,设置
BUNDLE_IMG
:$ make bundle-build BUNDLE_IMG=<registry>/<user>/<bundle_image_name>:<tag>
推送捆绑包镜像:
$ docker push <registry>/<user>/<bundle_image_name>:<tag>
5.6.2.5.3.2. 使用 Operator Lifecycle Manager 部署 Operator
Operator Lifecycle Manager(OLM)可帮助您在 Kubernetes 集群中安装、更新和管理 Operator 及其相关服务的生命周期。OLM 在 OpenShift Container Platform 上默认安装,并作为 Kubernetes 扩展运行,以便您可以在没有任何额外工具的情况下将 Web 控制台和 OpenShift CLI(oc
)用于所有 Operator 生命周期管理功能。
Operator Bundle Format 是 Operator SDK 和 OLM 的默认打包方法。您可以使用 Operator SDK 在 OLM 上快速运行捆绑包镜像,以确保它正确运行。
先决条件
- 在开发工作站上安装 operator SDK CLI
- 构建并推送到 registry 的 Operator 捆绑包镜像
-
OLM安装在一个基于 Kubernetes 的集群上(如果使用
apiextensions.k8s.io/v1
CRD,则为 v1.16.0 或更新版本,如 OpenShift Container Platform 4.10) -
使用具有
cluster-admin
权限的账户使用oc
登录到集群
流程
输入以下命令在集群中运行 Operator:
$ operator-sdk run bundle \ [-n <namespace>] \1 <registry>/<user>/<bundle_image_name>:<tag>
- 1
- 默认情况下,命令会在
~/.kube/config
文件中当前活跃的项目中安装 Operator。您可以添加-n
标志来为安装设置不同的命名空间范围。
这个命令执行以下操作:
- 创建引用捆绑包镜像的索引镜像。索引镜像不透明且具有临时性,但准确反映了如何将捆绑包添加到生产中的目录中。
- 创建指向新索引镜像的目录源,以便 OperatorHub 能够发现 Operator。
-
通过创建一个
OperatorGroup
、Subscription
、InstallPlan
和所有其他必要的对象(包括 RBAC),将 Operator 部署到集群中。
5.6.2.6. 创建自定义资源
安装 Operator 后,您可以通过创建一个由 Operator 在集群中提供的自定义资源(CR)来测试它。
先决条件
-
Nginx Operator 示例,它提供了
Nginx
CR,在集群中安装
流程
切换到安装 Operator 的命名空间。例如,如果使用
make deploy
命令部署 Operator:$ oc project nginx-operator-system
编辑
config/samples/demo_v1_nginx.yaml
中的Nginx
CR 清单示例,使其包含以下规格:apiVersion: demo.example.com/v1 kind: Nginx metadata: name: nginx-sample ... spec: ... replicaCount: 3
Nginx 服务帐户需要特权访问权限才能在 OpenShift Container Platform 中运行。将以下安全性上下文约束 (SCC) 添加到
nginx-sample
pod 的服务帐户中:$ oc adm policy add-scc-to-user \ anyuid system:serviceaccount:nginx-operator-system:nginx-sample
创建 CR:
$ oc apply -f config/samples/demo_v1_nginx.yaml
确保
Nginx
Operator 为示例 CR 创建部署,其大小正确:$ oc get deployments
输出示例
NAME READY UP-TO-DATE AVAILABLE AGE nginx-operator-controller-manager 1/1 1 1 8m nginx-sample 3/3 3 3 1m
检查 pod 和 CR 状态,以确认其状态是否使用 Nginx pod 名称更新。
检查 pod:
$ oc get pods
输出示例
NAME READY STATUS RESTARTS AGE nginx-sample-6fd7c98d8-7dqdr 1/1 Running 0 1m nginx-sample-6fd7c98d8-g5k7v 1/1 Running 0 1m nginx-sample-6fd7c98d8-m7vn7 1/1 Running 0 1m
检查 CR 状态:
$ oc get nginx/nginx-sample -o yaml
输出示例
apiVersion: demo.example.com/v1 kind: Nginx metadata: ... name: nginx-sample ... spec: replicaCount: 3 status: nodes: - nginx-sample-6fd7c98d8-7dqdr - nginx-sample-6fd7c98d8-g5k7v - nginx-sample-6fd7c98d8-m7vn7
更新部署大小。
更新
config/samples/demo_v1_nginx.yaml
文件,将Nginx
CR 中的spec.size
字段从3
改为5
:$ oc patch nginx nginx-sample \ -p '{"spec":{"replicaCount": 5}}' \ --type=merge
确认 Operator 已更改部署大小:
$ oc get deployments
输出示例
NAME READY UP-TO-DATE AVAILABLE AGE nginx-operator-controller-manager 1/1 1 1 10m nginx-sample 5/5 5 5 3m
运行以下命令来删除 CR:
$ oc delete -f config/samples/demo_v1_nginx.yaml
清理本教程中创建的资源。
如果使用
make deploy
命令来测试 Operator,请运行以下命令:$ make undeploy
如果使用
operator-sdk run bundle
命令来测试 Operator,请运行以下命令:$ operator-sdk cleanup <project_name>
5.6.2.7. 其他资源
- 请参阅基于 Helm 的 Operator 的项目布局,以了解 Operator SDK 创建的目录结构。
- 如果配置了集群范围的出口代理,集群管理员可以覆盖代理设置,或为 Operator Lifecycle Manager(OLM)上运行的特定 Operator 注入自定义 CA 证书。
5.6.3. 基于 Helm 的 Operator 的项目布局
operator-sdk
CLI 可为每个 Operator 项目生成或 scaffold 多个 软件包和文件。
5.6.3.1. 基于 Helm 的项目布局
使用 operator-sdk init --plugins helm
命令生成的基于 Helm 的 Operator 项目包含以下目录和文件:
文件/文件夹 | 目的 |
---|---|
| kustomize 清单,用于在 Kubernetes 集群上部署 Operator。 |
|
Helm Chart 使用 |
|
用于使用 |
| Group/version/kind(GVK)和 Helm Chart 的位置。 |
| 用于管理项目的目标。 |
| 包含 Operator 元数据信息的 YAML 文件。 |
5.6.4. Operator SDK 中的 Helm 支持
5.6.4.1. Helm chart
通过 Operator SDK 生成 Operator 项目的其中一种方案是利用现有 Helm Chart 来部署 Kubernetes 资源作为统一应用程序,而无需编写任何 Go 代码。这种基于 Helm 的 Operator 非常适合于推出时所需逻辑极少的无状态应用程序,因为更改应该应用于作为 Chart 一部分生成的 Kubernetes 对象。这听起来似乎很有局限性,但就 Kubernetes 社区构建的 Helm Chart 的增长而言,这足以满足它们的大量用例需要。
Operator 的主要功能是从代表应用程序实例的自定义对象中读取数据,并使其所需状态与正在运行的状态相匹配。对于基于 Helm 的 Operator,对象的 spec
字段是一个配置选项列表,通常在 Helm values.yaml
文件中描述。您可以不使用 Helm CLI(如 helm install -f values.yaml
)来通过标志设置这些值,而是在自定义资源 (CR) 中表达这些值,因为 CR 作为原生 Kubernetes 对象能够实现应用的 RBAC 以及审核跟踪所带来的好处。
举一个名为 Tomcat
的简单 CR 示例:
apiVersion: apache.org/v1alpha1 kind: Tomcat metadata: name: example-app spec: replicaCount: 2
replicaCount
值(本例中为 2
)会被传播到使用以下内容的 Chart 模板中:
{{ .Values.replicaCount }}
构建并部署完 Operator 后,您可通过新建一个 CR 实例来部署新的应用实例,或使用 oc
命令列出所有环境中运行的不同实例:
$ oc get Tomcats --all-namespaces
不要求使用 Helm CLI 或安装 Tiller;基于 Helm 的 Operator 会从 Helm 项目中导入代码。您要做的只是运行一个 Operator 实例,并使用自定义资源定义 (CRD) 注册 CR。因其遵循 RBAC,所以可以更容易防止生产环境改变。
5.6.5. Hybrid Helm Operators Operator SDK 教程
与基于 Go 和基于 Ansible 的 Operator 相比(它们已实现 Operator maturity model 中的 Auto Pilot capability (level V)),Operator SDK 中对标准的基于 Helm 的 Operator 支持有一定限制。
Hybrid Helm Operator 通过 Go API 增强了基于 Helm 的现有支持能力。借助此混合的 Helm 和 Go 方法,Operator SDK 可让 Operator 作者使用以下流程:
- 在与 Helm 相同的项目中为 Go API生成一个默认的结构或(scaffold)。
-
通过 Hybrid Helm Operator 提供的库,在项目的
main.go
文件中配置 Helm reconciler。
Hybrid Helm Operator 只是一个技术预览功能。技术预览功能不受红帽产品服务等级协议(SLA)支持,且功能可能并不完整。红帽不推荐在生产环境中使用它们。这些技术预览功能可以使用户提早试用新的功能,并有机会在开发阶段提供反馈意见。
有关红帽技术预览功能支持范围的更多信息,请参阅技术预览功能支持范围。
本教程介绍了使用 Hybrid Helm Operator 的以下过程:
-
如果不存在,使用 Helm chart 创建一个
Memcached
-
确保部署大小与
Memcached
自定义资源(CR)spec 指定的大小相同 -
使用 Go API 创建
MemcachedBackup
部署
5.6.5.1. 先决条件
- 已安装 operator SDK CLI
-
已安装 OpenShift CLI(
oc
)v4.10+ -
使用具有
cluster-admin
权限的oc
登录到 OpenShift Container Platform 4.10 集群 - 要允许集群拉取镜像,推送镜像的存储库必须设置为公共的存储库,或必须配置一个镜像 pull secret
5.6.5.2. 创建一个项目
使用 Operator SDK CLI 创建名为 memcached-operator 的
项目。
流程
为项目创建一个目录:
$ mkdir -p $HOME/github.com/example/memcached-operator
进入该目录:
$ cd $HOME/github.com/example/memcached-operator
运行
operator-sdk init
命令以初始化项目。使用域example.com
,所有 API 组都为<group>.example.com
:$ operator-sdk init \ --plugins=hybrid.helm.sdk.operatorframework.io \ --project-version="3" \ --domain example.com \ --repo=github.com/example/memcached-operator
init
命令根据 chart 的默认清单部署的资源,在config/rbac/role.yaml
文件中生成 RBAC 规则。验证config/rbac/role.yaml
文件中生成的规则是否满足您的 Operator 的权限要求。
其他资源
- 此流程会创建一个与 Helm 和 Go API 兼容的项目结构。要了解更多有关项目目录结构的信息,请参阅项目布局。
5.6.5.3. 创建 Helm API
使用 Operator SDK CLI 创建 Memcached API。
流程
运行以下命令创建带有组
cache
、版本v1
和种类Memcached
的 Helm API:$ operator-sdk create api \ --plugins helm.sdk.operatorframework.io/v1 \ --group cache \ --version v1 \ --kind Memcached
此流程还将您的 Operator 项目配置为监视 API 版本 v1
的 Memcached
资源,并构建 boilerplate Helm Chart。除了通过由 Operator SDK 构建的 boilerplate Helm chart 创建项目,也可以使用一个您的本地文件系统或远程 chart 仓库中的现有的 chart 进行创建。
有关基于现有或新 chart 创建 Helm API 的详情和示例,请运行以下命令:
$ operator-sdk create api --plugins helm.sdk.operatorframework.io/v1 --help
其他资源
5.6.5.3.1. Helm API 的 Operator 逻辑
默认情况下,您的构建 Operator 项目会监视 Memcached
资源事件,如 watches.yaml
文件中所示,并使用指定 Chart 执行 Helm 发行版本。
例 5.2. watches.yaml
文件示例
# Use the 'create api' subcommand to add watches to this file. - group: cache.my.domain version: v1 kind: Memcached chart: helm-charts/memcached #+kubebuilder:scaffold:watch
其他资源
- 有关通过 chart 自定义 Helm Operator 逻辑的详细文档,请参阅了解 Operator 逻辑。
5.6.5.3.2. 使用所提供的库 API 的自定义 Helm reconciler 配置
现有基于 Helm 的 Operator 的缺点是无法配置 Helm reconciler,因为它是从用户中提取的。对于基于 Helm 的 Operator 可访问 Seam 无升级功能(级别 II 及更新的版本),它重复使用已存在的 Helm Chart,在 Go 和 Helm Operator 类型间的混合会添加值。
helm-operator-plugins
库中提供的 API 允许 Operator 作者进行以下配置:
- 根据集群状态自定义值映射
- 通过配置协调器的事件记录程序在特定事件中执行代码
- 自定义协调器的日志记录器
-
设置
Install
,Upgrade
, 和Uninstall
注解,以便根据协调器监视的自定义资源中的注解启用 Helm 的操作 -
配置协调器以使用
Pre
和Post
hook 运行
以上对协调器的配置可在 main.go
文件中完成:
main.go
文件示例
// Operator's main.go // With the help of helpers provided in the library, the reconciler can be // configured here before starting the controller with this reconciler. reconciler := reconciler.New( reconciler.WithChart(*chart), reconciler.WithGroupVersionKind(gvk), ) if err := reconciler.SetupWithManager(mgr); err != nil { panic(fmt.Sprintf("unable to create reconciler: %s", err)) }
5.6.5.4. 创建 Go API
使用 Operator SDK CLI 创建 Go API。
流程
运行以下命令,使用组
cache
、版本v1
和 kindMemcachedBackup
创建 Go API:$ operator-sdk create api \ --group=cache \ --version v1 \ --kind MemcachedBackup \ --resource \ --controller \ --plugins=go/v3
提示时,输入
y
来创建资源和控制器:$ Create Resource [y/n] y Create Controller [y/n] y
此流程在 api/v1/memcachedbackup_types.go
和 controllers/memcachedbackup_controller.go
中生成 MemcachedBackup
资源 API。
5.6.5.4.1. 定义 API
定义 MemcachedBackup
自定义资源(CR)的 API。
通过定义 MemcachedBackup
类型来表示此 Go API,它具有 MemcachedBackupSpec.Size
字段,用于设置要部署的 Memcached 备份实例(CR)数量,以及用于存储 CR 的 pod 名称的 MemcachedBackupStatus.Nodes
字段。
Node
字段用于说明 Status
字段的一个示例。
流程
通过修改
api/v1/memcachedbackup_types.go
文件中的 Go 类型定义来定义MemcachedBackup
CR 的 API,使其具有以下spec
和status
:例 5.3.
api/v1/memcachedbackup_types.go
文件示例// MemcachedBackupSpec defines the desired state of MemcachedBackup type MemcachedBackupSpec struct { // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster // Important: Run "make" to regenerate code after modifying this file //+kubebuilder:validation:Minimum=0 // Size is the size of the memcached deployment Size int32 `json:"size"` } // MemcachedBackupStatus defines the observed state of MemcachedBackup type MemcachedBackupStatus struct { // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster // Important: Run "make" to regenerate code after modifying this file // Nodes are the names of the memcached pods Nodes []string `json:"nodes"` }
为资源类型更新生成的代码:
$ make generate
提示在修改了
*_types.go
文件后,您必须运行make generate
命令来更新该资源类型生成的代码。使用
spec
和status
字段和 CRD 验证标记定义 API 后,生成和更新 CRD 清单:$ make manifests
此 Makefile 目标调用 controller-gen
实用程序在 config/crd/bases/cache.my.domain_memcachedbackups.yaml
文件中生成 CRD 清单。
5.6.5.4.2. 控制器实现
本教程中的控制器执行以下操作:
-
如果尚无
Memcached
部署,请创建一个。 -
确保部署大小与
Memcached
CR spec 指定的大小相同。 -
使用
memcached
Pod 的名称更新Memcached
CR 状态。
有关如何配置控制器来执行上述操作的详情,请参考使用基于 Go 的 Operator 在 Operator SDK 指南中的实施控制器。
5.6.5.4.3. main.go 的不同
对于基于 Go 的标准 Operator 和混合 Helm Operator,main.go
文件处理构建 Go API 的 Manager
程序初始化和运行。但是,对于 Hybrid Helm Operator,main.go
文件也会公开加载 watches.yaml
文件和配置 Helm reconciler 的逻辑。
例 5.4. main.go
文件示例
... for _, w := range ws { // Register controller with the factory reconcilePeriod := defaultReconcilePeriod if w.ReconcilePeriod != nil { reconcilePeriod = w.ReconcilePeriod.Duration } maxConcurrentReconciles := defaultMaxConcurrentReconciles if w.MaxConcurrentReconciles != nil { maxConcurrentReconciles = *w.MaxConcurrentReconciles } r, err := reconciler.New( reconciler.WithChart(*w.Chart), reconciler.WithGroupVersionKind(w.GroupVersionKind), reconciler.WithOverrideValues(w.OverrideValues), reconciler.SkipDependentWatches(w.WatchDependentResources != nil && !*w.WatchDependentResources), reconciler.WithMaxConcurrentReconciles(maxConcurrentReconciles), reconciler.WithReconcilePeriod(reconcilePeriod), reconciler.WithInstallAnnotations(annotation.DefaultInstallAnnotations...), reconciler.WithUpgradeAnnotations(annotation.DefaultUpgradeAnnotations...), reconciler.WithUninstallAnnotations(annotation.DefaultUninstallAnnotations...), ) ...
管理器使用 Helm
和 Go
协调器初始化:
例 5.5. Helm
和 Go
reconcilers 示例
... // Setup manager with Go API if err = (&controllers.MemcachedBackupReconciler{ Client: mgr.GetClient(), Scheme: mgr.GetScheme(), }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "MemcachedBackup") os.Exit(1) } ... // Setup manager with Helm API for _, w := range ws { ... if err := r.SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "Helm") os.Exit(1) } setupLog.Info("configured watch", "gvk", w.GroupVersionKind, "chartPath", w.ChartPath, "maxConcurrentReconciles", maxConcurrentReconciles, "reconcilePeriod", reconcilePeriod) } // Start the manager if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil { setupLog.Error(err, "problem running manager") os.Exit(1) }
5.6.5.4.4. 权限和 RBAC 清单
控制器需要特定的基于角色的访问控制(RBAC)权限与它管理的资源交互。对于 Go API,它们通过 RBAC 标记来指定,如基于 Go 的标准 Operator 的 Operator SDK 教程所示。
对于 Helm API,在 roles.yaml
中默认构建权限。目前,由于在构建 Go API 时存在一个已知问题,Helm API 的权限会被覆盖。因此,请确保 roles.yaml
中定义的权限与您的要求匹配。
以下是 Memcached Operator 的 role.yaml
示例:
例 5.6. Helm
和 Go
reconcilers 示例
--- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: manager-role rules: - apiGroups: - "" resources: - namespaces verbs: - get - apiGroups: - apps resources: - deployments - daemonsets - replicasets - statefulsets verbs: - create - delete - get - list - patch - update - watch - apiGroups: - cache.my.domain resources: - memcachedbackups verbs: - create - delete - get - list - patch - update - watch - apiGroups: - cache.my.domain resources: - memcachedbackups/finalizers verbs: - create - delete - get - list - patch - update - watch - apiGroups: - "" resources: - pods - services - services/finalizers - endpoints - persistentvolumeclaims - events - configmaps - secrets - serviceaccounts verbs: - create - delete - get - list - patch - update - watch - apiGroups: - cache.my.domain resources: - memcachedbackups/status verbs: - get - patch - update - apiGroups: - policy resources: - events - poddisruptionbudgets verbs: - create - delete - get - list - patch - update - watch - apiGroups: - cache.my.domain resources: - memcacheds - memcacheds/status - memcacheds/finalizers verbs: - create - delete - get - list - patch - update - watch
5.6.5.5. 在集群外本地运行
您可以作为集群外的 Go 程序运行您的 Operator 项目。这可以加快部署和测试的速度,对于开发非常有用。
流程
运行以下命令,以在
~/.kube/config
文件中配置的集群中安装自定义资源定义(CRD),并在本地运行 Operator:$ make install run
5.6.5.6. 作为集群的部署运行
您可以作为一个部署在集群中运行 Operator 项目。
流程
运行以下
make
命令来构建和推送 Operator 镜像。在以下步骤中修改IMG
参数来引用您可访问的库。您可以获取在存储库站点(如 Quay.io)存储容器的帐户。构建镜像:
$ make docker-build IMG=<registry>/<user>/<image_name>:<tag>
注意由 SDK 为 Operator 生成的 Dockerfile 需要为
go build
明确引用GOARCH=amd64
。这可以在非 AMD64 构架中使用GOARCH=$TARGETARCH
。Docker 自动将环境变量设置为-platform
指定的值。对于 Buildah,需要使用-build-arg
来实现这一目的。如需更多信息,请参阅多个架构。将镜像推送到存储库:
$ make docker-push IMG=<registry>/<user>/<image_name>:<tag>
注意镜像的名称和标签,如
IMG=<registry> /<user> /<image_name>:<tag>
,在两个命令中都可在您的 Makefile 中设置。修改IMG ?= controller:latest
值来设置您的默认镜像名称。
运行以下命令来部署 Operator:
$ make deploy IMG=<registry>/<user>/<image_name>:<tag>
默认情况下,这个命令会创建一个带有 Operator 项目名称的命名空间,格式为
<project_name>-system
,用于部署。此命令还从config/rbac
安装 RBAC 清单。验证 Operator 是否正在运行:
$ oc get deployment -n <project_name>-system
输出示例
NAME READY UP-TO-DATE AVAILABLE AGE <project_name>-controller-manager 1/1 1 1 8m
5.6.5.7. 创建自定义资源
安装 Operator 后,您可以通过创建由 Operator 在集群中提供的自定义资源(CR)来测试它。
流程
切换到安装 Operator 的命名空间:
$ oc project <project_name>-system
通过将
replicaCount
字段更新为3
,更新config/samples/cache_v1_memcached.yaml
文件中的Memcached
CR 清单示例:例 5.7.
config/samples/cache_v1_memcached.yaml
文件示例apiVersion: cache.my.domain/v1 kind: Memcached metadata: name: memcached-sample spec: # Default values copied from <project_dir>/helm-charts/memcached/values.yaml affinity: {} autoscaling: enabled: false maxReplicas: 100 minReplicas: 1 targetCPUUtilizationPercentage: 80 fullnameOverride: "" image: pullPolicy: IfNotPresent repository: nginx tag: "" imagePullSecrets: [] ingress: annotations: {} className: "" enabled: false hosts: - host: chart-example.local paths: - path: / pathType: ImplementationSpecific tls: [] nameOverride: "" nodeSelector: {} podAnnotations: {} podSecurityContext: {} replicaCount: 3 resources: {} securityContext: {} service: port: 80 type: ClusterIP serviceAccount: annotations: {} create: true name: "" tolerations: []
创建
Memcached
CR:$ oc apply -f config/samples/cache_v1_memcached.yaml
确保 Memcached Operator 为示例 CR 创建部署,其大小正确:
$ oc get pods
输出示例
NAME READY STATUS RESTARTS AGE memcached-sample-6fd7c98d8-7dqdr 1/1 Running 0 18m memcached-sample-6fd7c98d8-g5k7v 1/1 Running 0 18m memcached-sample-6fd7c98d8-m7vn7 1/1 Running 0 18m
通过将
size
更新至2
,更新config/samples/cache_v1_memcachedbackup.yaml
文件中的MemcachedBackup
CR 清单示例:例 5.8.
config/samples/cache_v1_memcachedbackup.yaml
文件示例apiVersion: cache.my.domain/v1 kind: MemcachedBackup metadata: name: memcachedbackup-sample spec: size: 2
创建
MemcachedBackup
CR:$ oc apply -f config/samples/cache_v1_memcachedbackup.yaml
确保
memcachedbackup
pod 的数量与 CR 中指定的相同:$ oc get pods
输出示例
NAME READY STATUS RESTARTS AGE memcachedbackup-sample-8649699989-4bbzg 1/1 Running 0 22m memcachedbackup-sample-8649699989-mq6mx 1/1 Running 0 22m
-
您可以更新以上每个 CR 中的
spec
,然后再次应用它们。控制器再次进行协调,并确保按照相应 CR 的spec
中指定 pod 的大小。 清理本教程中创建的资源:
删除
Memcached
资源:$ oc delete -f config/samples/cache_v1_memcached.yaml
删除
MemcachedBackup
资源:$ oc delete -f config/samples/cache_v1_memcachedbackup.yaml
如果使用
make deploy
命令来测试 Operator,请运行以下命令:$ make undeploy
5.6.5.8. 项目布局
混合 Helm Operator 的构建是自定义的,以匹配 Helm 和 Go API。
文件/文件夹 | 目的 |
---|---|
|
容器引擎使用 |
| 构建包含帮助程序目标的文件,以帮助您操作项目。 |
| 包含 Operator 元数据信息的 YAML 文件。代表项目的配置,用于跟踪 CLI 和插件的有用信息。 |
|
包含有用的二进制文件,如管理器( |
| 包含配置文件,其中包括所有 Kustomize 清单,以便在集群上启动 Operator 项目。插件可能会使用它来提供功能。例如,对于 Operator SDK 可以帮助创建 Operator 捆绑包,CLI 会查找在这个目录中构建的 CRD 和 CR。
|
| 包含 Go API 定义。 |
| 包含 Go API 的控制器。 |
| 包含实用程序文件,如用于构建项目文件的许可证标头的文件。 |
|
Operator 的主要程序。实例化一个新管理器,它会在 |
|
包含 Helm chart,可以使用带有 Helm 插件的 |
| 包含 group/version/kind(GVK)和 Helm Chart 位置。用于配置 Helm 监视。 |