×

与已达到自动驾驶能力(V 级)的基于 Go 和 Ansible 的运算符支持相比,Operator SDK 中基于 Helm 的运算符标准支持的功能有限,如运算符成熟度模型所示。

Red Hat 支持的 Operator SDK CLI 工具版本(包括相关的脚手架和运算符项目的测试工具)已弃用,并计划在未来版本的 OpenShift Container Platform 中删除。Red Hat 将在当前发行周期内为此功能提供错误修复和支持,但此功能将不再接收增强功能,并将从未来的 OpenShift Container Platform 版本中删除。

不建议使用 Red Hat 支持的 Operator SDK 版本创建新的运算符项目。拥有现有运算符项目的运算符作者可以使用 OpenShift Container Platform 4.17 版本中发布的 Operator SDK CLI 工具版本来维护其项目并创建针对较新版本的 OpenShift Container Platform 的运算符版本。

以下与运算符项目相关的基础镜像被弃用。这些基础镜像的运行时功能和配置 API 仍受支持,用于错误修复和解决 CVE。

  • 基于 Ansible 的运算符项目的基镜像

  • 基于 Helm 的运算符项目的基镜像

有关 OpenShift Container Platform 中已弃用或删除的主要功能的最新列表,请参阅 OpenShift Container Platform 发行说明中的已弃用和已删除的功能部分。

有关不受支持的社区维护的 Operator SDK 版本的信息,请参阅Operator SDK (Operator Framework)

混合 Helm 运算符通过 Go API 增强了现有基于 Helm 的支持的能力。通过这种 Helm 和 Go 的混合方法,Operator SDK 使运算符作者能够使用以下流程

  • 为 Go API 生成默认结构,或构建与 Helm 项目相同的项目。

  • 通过混合 Helm 运算符提供的库,在项目的main.go文件中配置 Helm 调解器。

混合 Helm 运算符仅为技术预览功能。技术预览功能不受 Red Hat 生产服务级别协议 (SLA) 的支持,并且可能功能不完整。Red Hat 不建议在生产环境中使用它们。这些功能可让您抢先体验即将推出的产品功能,从而能够在开发过程中测试功能并提供反馈。

有关 Red Hat 技术预览功能支持范围的更多信息,请参阅技术预览功能支持范围

本教程将引导您完成使用混合 Helm 运算符的以下流程

  • 如果不存在,则通过 Helm chart 创建Memcached部署

  • 确保部署大小与Memcached自定义资源 (CR) 规范中指定的大小相同

  • 使用 Go API 创建MemcachedBackup部署

先决条件

  • 已安装 Operator SDK CLI

  • 已安装 OpenShift CLI (oc) 4.17+

  • 使用具有cluster-admin权限的帐户通过oc登录到 OpenShift Container Platform 4.17 集群

  • 要允许集群拉取镜像,您推送镜像的仓库必须设置为公共仓库,或者您必须配置镜像拉取密钥

创建项目

使用 Operator SDK CLI 创建名为memcached-operator的项目。

步骤
  1. 为项目创建一个目录

    $ mkdir -p $HOME/github.com/example/memcached-operator
  2. 更改到该目录

    $ cd $HOME/github.com/example/memcached-operator
  3. 运行operator-sdk init命令来初始化项目。此示例使用my.domain域,以便所有 API 组都是<group>.my.domain

    $ operator-sdk init \
        --plugins=hybrid.helm.sdk.operatorframework.io \
        --project-version="3" \
        --domain my.domain \
        --repo=github.com/example/memcached-operator

    init命令根据 chart 的默认清单将部署的资源在config/rbac/role.yaml文件中生成 RBAC 规则。请验证config/rbac/role.yaml文件中生成的规则是否符合您的 Operator 的权限要求。

其他资源
  • 此步骤创建与 Helm 和 Go API 都兼容的项目结构。要了解有关项目目录结构的更多信息,请参阅项目布局

创建 Helm API

使用 Operator SDK CLI 创建 Helm 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资源,并构建一个样板 Helm chart。您可以使用 Operator SDK 构建的样板 Helm chart 创建项目,也可以使用本地文件系统或远程 chart 存储库中的现有 chart。

有关根据现有或新 chart 创建 Helm API 的更多详细信息和示例,请运行以下命令

$ operator-sdk create api --plugins helm.sdk.operatorframework.io/v1 --help
其他资源

Helm API 的运算符逻辑

默认情况下,您构建的 Operator 项目会监视watches.yaml文件中显示的Memcached资源事件,并使用指定的 chart 执行 Helm 发布。

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
其他资源

使用提供的库 API 自定义 Helm 调解器配置

现有基于 Helm 的运算符的一个缺点是无法配置 Helm 调解器,因为它对用户是抽象的。对于要达到无缝升级能力(II 级及更高)并重用现有 Helm chart 的基于 Helm 的运算符,Go 和 Helm 运算符类型的混合具有附加值。

helm-operator-plugins 库中提供的 API 允许 Operator 作者进行以下配置:

  • 基于集群状态自定义值映射

  • 通过配置协调器的事件记录器来在特定事件中执行代码

  • 自定义协调器的日志记录器

  • 设置 InstallUpgradeUninstall 注解,以便根据协调器监视的自定义资源中找到的注解来配置 Helm 的操作

  • 配置协调器以使用 PrePost 钩子运行

上述协调器配置可以在 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))
}

创建 Go API

使用 Operator SDK CLI 创建 Go API。

步骤
  1. 运行以下命令以创建具有组 cache、版本 v1 和种类 MemcachedBackup 的 Go API:

    $ operator-sdk create api \
        --group=cache \
        --version v1 \
        --kind MemcachedBackup \
        --resource \
        --controller \
        --plugins=go/v4
  2. 出现提示时,输入 y 以创建资源和控制器

    $ Create Resource [y/n]
    y
    Create Controller [y/n]
    y

此过程会在 api/v1/memcachedbackup_types.go 中生成 MemcachedBackup 资源 API,并在 controllers/memcachedbackup_controller.go 中生成控制器。

定义 API

定义 MemcachedBackup 自定义资源 (CR) 的 API。

通过定义 MemcachedBackup 类型来表示此 Go API,该类型将具有 MemcachedBackupSpec.Size 字段来设置要部署的 Memcached 备份实例 (CR) 的数量,以及 MemcachedBackupStatus.Nodes 字段来存储 CR 的 Pod 名称。

Node 字段用于说明 Status 字段的示例。

步骤
  1. 通过修改 api/v1/memcachedbackup_types.go 文件中的 Go 类型定义来定义 MemcachedBackup CR 的 API,使其具有以下 specstatus

    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"`
    }
  2. 更新资源类型的生成的代码

    $ make generate

    修改 *_types.go 文件后,必须运行 make generate 命令来更新该资源类型的生成的代码。

  3. 定义了带有 specstatus 字段以及 CRD 验证标记的 API 后,生成并更新 CRD 清单

    $ make manifests

此 Makefile 目标调用 controller-gen 实用程序以在 config/crd/bases/cache.my.domain_memcachedbackups.yaml 文件中生成 CRD 清单。

控制器实现

本教程中的控制器执行以下操作:

  • 如果不存在,则创建 Memcached 部署。

  • 确保部署大小与 Memcached CR spec 中指定的大小相同。

  • 使用 memcached Pod 的名称更新 Memcached CR 状态。

有关如何配置控制器以执行上述操作的详细说明,请参阅 Operator SDK 标准基于 Go 的 Operator 教程中的 实现控制器

main.go 的差异

对于标准基于 Go 的 Operator 和混合 Helm Operator,main.go 文件处理 Go API 的 Manager 程序的脚手架初始化和运行。但是,对于混合 Helm Operator,main.go 文件还公开了加载 watches.yaml 文件和配置 Helm 协调器的逻辑。

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...),
		)
...

管理器使用 HelmGo 协调器进行初始化

HelmGo 协调器示例
...
// 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)
	}

权限和 RBAC 清单

控制器需要一定的基于角色的访问控制 (RBAC) 权限才能与它管理的资源进行交互。对于 Go API,这些权限使用 RBAC 标记指定,如 Operator SDK 标准基于 Go 的 Operator 教程中所示。

对于 Helm API,权限默认情况下在 roles.yaml 中进行脚手架构建。但是,目前由于在构建 Go API 时已知问题,Helm API 的权限被覆盖。由于此问题,请确保 roles.yaml 中定义的权限符合您的要求。

以下是 Memcached Operator 的 role.yaml 示例:

HelmGo 协调器示例
---
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

在集群外部本地运行

您可以将 Operator 项目作为 Go 程序在集群外部运行。这对于开发目的很有用,可以加快部署和测试速度。

步骤
  • 运行以下命令以在 ~/.kube/config 文件中配置的集群中安装自定义资源定义 (CRD) 并本地运行 Operator:

    $ make install run

作为集群上的部署运行

您可以将 Operator 项目作为部署在集群上运行。

步骤
  1. 运行以下 make 命令以构建和推送 Operator 镜像。修改以下步骤中的 IMG 参数以引用您有权访问的存储库。您可以在 Quay.io 等存储库站点获取用于存储容器的帐户。

    1. 构建镜像

      $ make docker-build IMG=<registry>/<user>/<image_name>:<tag>

      SDK 为 Operator 生成的 Dockerfile 明确引用 GOARCH=amd64 用于 go build。这可以针对非 AMD64 架构修改为 GOARCH=$TARGETARCH。Docker 将自动将环境变量设置为 –platform 指定的值。对于 Buildah,需要使用 –build-arg。有关更多信息,请参阅 多架构

    2. 将镜像推送到存储库

      $ make docker-push IMG=<registry>/<user>/<image_name>:<tag>

      镜像的名称和标签(例如 IMG=<registry>/<user>/<image_name>:<tag>)也可以在您的 Makefile 中设置。修改 IMG ?= controller:latest 值以设置您的默认镜像名称。

  2. 运行以下命令以部署 Operator:

    $ make deploy IMG=<registry>/<user>/<image_name>:<tag>

    默认情况下,此命令创建一个名称为 Operator 项目名称的命名空间,格式为 <project_name>-system,并用于部署。此命令还安装 config/rbac 中的 RBAC 清单。

  3. 运行以下命令以验证 Operator 是否正在运行:

    $ oc get deployment -n <project_name>-system
    示例输出
    NAME                                    READY   UP-TO-DATE   AVAILABLE   AGE
    <project_name>-controller-manager       1/1     1            1           8m

创建自定义资源

安装 Operator 后,您可以通过创建现在由 Operator 在集群上提供的自定义资源 (CR) 来对其进行测试。

步骤
  1. 更改到安装 Operator 的命名空间

    $ oc project <project_name>-system
  2. 通过将 config/samples/cache_v1_memcached.yaml 文件中的 replicaCount 字段更新为 3 来更新示例 Memcached CR 清单

    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: []
  3. 创建 Memcached CR

    $ oc apply -f config/samples/cache_v1_memcached.yaml
  4. 确保 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
  5. 通过将 config/samples/cache_v1_memcachedbackup.yaml 文件中的 size 更新为 2 来更新示例 MemcachedBackup CR 清单

    config/samples/cache_v1_memcachedbackup.yaml 文件示例
    apiVersion: cache.my.domain/v1
    kind: MemcachedBackup
    metadata:
      name: memcachedbackup-sample
    spec:
      size: 2
  6. 创建 MemcachedBackup CR

    $ oc apply -f config/samples/cache_v1_memcachedbackup.yaml
  7. 确保 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
  8. 您可以更新上述每个 CR 中的spec,然后再次应用它们。控制器会再次协调,并确保 Pod 的大小与各个 CR 的spec中指定的大小一致。

  9. 清理本教程中创建的资源

    1. 删除Memcached资源

      $ oc delete -f config/samples/cache_v1_memcached.yaml
    2. 删除MemcachedBackup资源

      $ oc delete -f config/samples/cache_v1_memcachedbackup.yaml
    3. 如果您使用make deploy命令测试了 Operator,请运行以下命令

      $ make undeploy

项目布局

混合 Helm Operator 脚手架经过定制,使其与 Helm 和 Go API 都兼容。

文件/文件夹 用途

Dockerfile

容器引擎用于使用make docker-build命令构建您的 Operator 镜像的指令。

Makefile

包含辅助目标的构建文件,可帮助您使用项目。

PROJECT

包含 Operator 元数据信息的 YAML 文件。代表项目的配置,并用于跟踪 CLI 和插件的有用信息。

bin/

包含有用的二进制文件,例如用于在本地运行项目的manager和用于项目配置的kustomize实用程序。

config/

包含配置文件,包括所有Kustomize清单,用于在集群上启动您的 Operator 项目。插件可能会使用它来提供功能。例如,对于 Operator SDK 帮助创建您的 Operator 包,CLI 会查找在此目录中搭建的 CRD 和 CR。

config/crd/

包含自定义资源定义 (CRD)。

config/default/

包含用于以标准配置启动控制器的 Kustomize 基础。

config/manager/

包含将您的 Operator 项目作为 Pod 在集群上启动的清单。

config/manifests/

包含在bundle/目录中生成您的 OLM 清单的基础。

config/prometheus/

包含启用项目向 Prometheus 提供指标(例如ServiceMonitor资源)所需的清单。

config/scorecard/

包含允许您使用 scorecard 工具测试项目的清单。

config/rbac/

包含运行项目所需的 RBAC 权限。

config/samples/

包含自定义资源的示例。

api/

包含 Go API 定义。

internal/controllers/

包含 Go API 的控制器。

hack/

包含实用程序文件,例如用于为项目文件搭建许可证头的文件。

main.go

Operator 的主程序。实例化一个新的管理器,该管理器注册apis/目录中的所有自定义资源定义 (CRD),并启动controllers/目录中的所有控制器。

helm-charts/

包含可以使用create api命令和 Helm 插件指定的 Helm 图表。

watches.yaml

包含组/版本/种类 (GVK) 和 Helm 图表位置。用于配置 Helm 监视。