×

集群服务版本 (CSV) 由ClusterServiceVersion 对象定义,是从操作符元数据创建的YAML清单,它帮助操作符生命周期管理器 (OLM) 在集群中运行操作符。它是伴随操作符容器镜像的元数据,用于使用其徽标、描述和版本等信息填充用户界面。它也是运行操作符所需的详细信息来源,例如它所需的RBAC规则以及它管理或依赖的自定义资源 (CR)。

Operator SDK包含CSV生成器,用于为当前Operator项目生成CSV,并使用YAML清单和Operator源文件中包含的信息进行自定义。

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

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

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

  • 基于Ansible的Operator项目的基镜像

  • 基于Helm的Operator项目的基镜像

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

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

生成 CSV 的命令消除了 Operator 作者需要深入了解 OLM 才能使其 Operator 与 OLM 交互或向 Catalog Registry 发布元数据的责任。此外,由于 CSV 规范可能会随着新 Kubernetes 和 OLM 功能的实现而随着时间推移而发生变化,因此 Operator SDK 能够轻松扩展其更新系统以处理未来的新 CSV 功能。

CSV 生成工作原理

Operator 捆绑清单(包括集群服务版本 (CSV))描述了如何使用 Operator Lifecycle Manager (OLM) 来显示、创建和管理应用程序。Operator SDK 中的 CSV 生成器(由generate bundle 子命令调用)是将您的 Operator 发布到目录并使用 OLM 部署它的第一步。该子命令需要某些输入清单来构建 CSV 清单;所有输入都在命令调用时以及 CSV 基准一起读取,以便幂等地生成或重新生成 CSV。

通常,会首先运行generate kustomize manifests 子命令来生成generate bundle 子命令使用的输入Kustomize 基准。但是,Operator SDK 提供了make bundle 命令,该命令可以自动化多个任务,包括按顺序运行以下子命令

  1. generate kustomize manifests

  2. generate bundle

  3. bundle validate

其他资源
  • 有关包含捆绑包和 CSV 生成在内的完整过程,请参阅捆绑 Operator

生成的文 件和资源

make bundle 命令会在您的 Operator 项目中创建以下文件和目录

  • 名为bundle/manifests 的捆绑清单目录,其中包含一个ClusterServiceVersion (CSV) 对象

  • 名为bundle/metadata 的捆绑元数据目录

  • config/crd 目录中的所有自定义资源定义 (CRD)

  • Dockerfile bundle.Dockerfile

CSV 中通常包含以下资源:

角色 (Role)

定义 Operator 在命名空间内的权限。

集群角色 (ClusterRole)

定义集群范围的 Operator 权限。

部署 (Deployment)

定义如何在 Pod 中运行 Operator 的操作对象。

自定义资源定义 (CRD)

定义您的 Operator 调和的自定义资源。

自定义资源示例

符合特定 CRD 规范的资源示例。

版本管理

generate bundle 子命令的--version 标志在首次创建捆绑包和升级现有捆绑包时,为您的捆绑包提供语义版本。

通过在您的Makefile中设置VERSION变量,当make bundle命令运行generate bundle子命令时,将自动使用该值调用--version标志。CSV 版本与 Operator 版本相同,升级 Operator 版本时会生成新的 CSV。

手动定义的 CSV 字段

许多 CSV 字段无法使用与 Operator SDK 无关的生成的通用清单来填充。这些字段大多是关于 Operator 和各种自定义资源定义 (CRD) 的人工编写的元数据。

Operator 作者必须直接修改其集群服务版本 (CSV) YAML 文件,向以下必需字段添加个性化数据。当检测到任何必需字段中缺少数据时,Operator SDK 会在 CSV 生成期间发出警告。

下表详细说明了哪些手动定义的 CSV 字段是必需的,哪些是可选的。

表 1. 必需的 CSV 字段
字段 描述

metadata.name

此 CSV 的唯一名称。应在名称中包含 Operator 版本以确保唯一性,例如app-operator.v0.1.1

metadata.capabilities

根据 Operator 成熟度模型的成熟度级别。选项包括Basic InstallSeamless UpgradesFull LifecycleDeep InsightsAuto Pilot

spec.displayName

用于标识 Operator 的公开名称。

spec.description

对 Operator 功能的简短描述。

spec.keywords

描述 Operator 的关键词。

spec.maintainers

维护 Operator 的个人或组织实体,包含nameemail

spec.provider

Operator 的提供者(通常是组织),包含name

spec.labels

Operator 内部使用的键值对。

spec.version

Operator 的语义版本,例如0.1.1

spec.customresourcedefinitions

Operator 使用的任何 CRD。如果deploy/中存在任何 CRD YAML 文件,则 Operator SDK 会自动填充此字段。但是,CRD 清单规范中缺少一些字段需要用户输入

  • description:CRD 的描述。

  • resources:CRD 利用的任何 Kubernetes 资源,例如PodStatefulSet对象。

  • specDescriptors:Operator 输入和输出的 UI 提示。

表 2. 可选的 CSV 字段
字段 描述

spec.replaces

此 CSV 替换的 CSV 名称。

spec.links

与 Operator 或正在管理的应用程序相关的 URL(例如,网站和文档),每个 URL 都包含nameurl

spec.selector

Operator 可以用来配对集群中资源的选择器。

spec.icon

Operator 独有的 base64 编码图标,设置在包含mediatypebase64data字段中。

spec.maturity

此版本的软件已达到的成熟度级别。选项包括planningpre-alphaalphabetastablematureinactivedeprecated

有关上述每个字段应包含哪些数据的更多详细信息,请参阅CSV 规范

目前需要用户干预的几个 YAML 字段可以从 Operator 代码中解析。

Operator 元数据注释

Operator 开发人员可以在集群服务版本 (CSV) 的元数据中设置某些注释,以启用功能或在用户界面 (UI) 中突出显示功能,例如 OperatorHub 或Red Hat 生态系统目录。通过在 CSV YAML 文件中设置metadata.annotations字段来手动定义 Operator 元数据注释。

基础设施功能注释

features.operators.openshift.io组中的注释详细说明了 Operator 可能支持的基础设施功能,通过设置"true""false"值来指定。用户可以通过 Web 控制台或Red Hat 生态系统目录中的 OperatorHub 发现 Operator 时,查看和按这些功能进行筛选。这些注释在 OpenShift Container Platform 4.10 及更高版本中受支持。

features.operators.openshift.io基础设施功能注释弃用了在早期版本的 OpenShift Container Platform 中使用的operators.openshift.io/infrastructure-features注释。有关更多信息,请参阅“已弃用的基础设施功能注释”。

表 3. 基础设施功能注释
注释 描述 有效值[1]

features.operators.openshift.io/disconnected

指定 Operator 是否支持被镜像到断开的目录中,包括所有依赖项,并且不需要互联网访问。Operator 利用spec.relatedImages CSV 字段通过其摘要来引用任何相关的镜像。

"true""false"

features.operators.openshift.io/fips-compliant

指定操作符是否接受底层平台的 FIPS-140 配置并在引导到 FIPS 模式的节点上工作。在此模式下,操作符及其管理的任何工作负载(操作数)仅调用已提交 FIPS-140 验证的 Red Hat Enterprise Linux (RHEL) 加密库。

"true""false"

features.operators.openshift.io/proxy-aware

指定操作符是否支持在代理后面的集群上运行,方法是接受标准的HTTP_PROXYHTTPS_PROXY代理环境变量。如果适用,操作符会将此信息传递到其管理的工作负载(操作数)。

"true""false"

features.operators.openshift.io/tls-profiles

指定操作符是否实现了众所周知的可调参数来修改操作符以及(如果适用)其管理的任何工作负载(操作数)使用的 TLS 密码套件。

"true""false"

features.operators.openshift.io/token-auth-aws

指定操作符是否支持通过使用云凭据操作符 (CCO) 通过 AWS 安全令牌服务 (STS) 对 AWS API 进行令牌化身份验证的配置。

"true""false"

features.operators.openshift.io/token-auth-azure

指定操作符是否支持通过使用云凭据操作符 (CCO) 通过 Azure 托管标识对 Azure API 进行令牌化身份验证的配置。

"true""false"

features.operators.openshift.io/token-auth-gcp

指定操作符是否支持通过使用云凭据操作符 (CCO) 通过 GCP 工作负载身份基础 (WIF) 对 Google Cloud API 进行令牌化身份验证的配置。

"true""false"

features.operators.openshift.io/cnf

指定操作符是否提供云原生网络功能 (CNF) Kubernetes 插件。

"true""false"

features.operators.openshift.io/cni

指定操作符是否提供容器网络接口 (CNI) Kubernetes 插件。

"true""false"

features.operators.openshift.io/csi

指定操作符是否提供容器存储接口 (CSI) Kubernetes 插件。

"true""false"

  1. 有效值有意使用双引号显示,因为 Kubernetes 注解必须是字符串。

包含基础设施特性注解的示例 CSV
apiVersion: operators.coreos.com/v1alpha1
kind: ClusterServiceVersion
metadata:
  annotations:
    features.operators.openshift.io/disconnected: "true"
    features.operators.openshift.io/fips-compliant: "false"
    features.operators.openshift.io/proxy-aware: "false"
    features.operators.openshift.io/tls-profiles: "false"
    features.operators.openshift.io/token-auth-aws: "false"
    features.operators.openshift.io/token-auth-azure: "false"
    features.operators.openshift.io/token-auth-gcp: "false"

已弃用的基础设施特性注解

从 OpenShift Container Platform 4.14 开始,operators.openshift.io/infrastructure-features 组的注解已被 features.operators.openshift.io 命名空间的注解组弃用。虽然鼓励您使用较新的注解,但目前同时使用这两个组时都会被接受。

这些注解详细说明了操作符支持的基础设施特性。用户可以在通过 Web 控制台或 Red Hat 生态系统目录 中发现操作符时查看并按这些特性进行筛选。

表 4. 已弃用的 operators.openshift.io/infrastructure-features 注解
有效的注解值 描述

disconnected

操作符支持被镜像到脱机目录中,包括所有依赖项,并且不需要互联网访问。操作符列出了镜像所需的所有相关镜像。

cnf

操作符提供云原生网络功能 (CNF) Kubernetes 插件。

cni

操作符提供容器网络接口 (CNI) Kubernetes 插件。

csi

操作符提供容器存储接口 (CSI) Kubernetes 插件。

fips

操作符接受底层平台的 FIPS 模式并在引导到 FIPS 模式的节点上工作。

在运行以 FIPS 模式引导的 Red Hat Enterprise Linux (RHEL) 或 Red Hat Enterprise Linux CoreOS (RHCOS) 时,OpenShift Container Platform 核心组件仅在 x86_64、ppc64le 和 s390x 架构上使用已提交给 NIST 进行 FIPS 140-2/140-3 验证的 RHEL 加密库。

proxy-aware

操作符支持在代理后面的集群上运行。操作符接受标准的代理环境变量HTTP_PROXYHTTPS_PROXY,当集群配置为使用代理时,操作符生命周期管理器 (OLM) 会自动将其提供给操作符。必需的环境变量将传递给受管理工作负载的操作数。

包含disconnectedproxy-aware支持的示例 CSV
apiVersion: operators.coreos.com/v1alpha1
kind: ClusterServiceVersion
metadata:
  annotations:
    operators.openshift.io/infrastructure-features: '["disconnected", "proxy-aware"]'

其他可选注解

以下操作符注解是可选的。

表 5. 其他可选注解
注释 描述

alm-examples

提供具有最小配置集的自定义资源定义 (CRD) 模板。兼容的 UI 为用户预填充此模板以进行进一步自定义。

operatorframework.io/initialization-resource

通过在操作符安装期间将operatorframework.io/initialization-resource注解添加到集群服务版本 (CSV) 来指定单个必需的自定义资源。然后提示用户通过 CSV 中提供的模板创建自定义资源。必须包含包含完整 YAML 定义的模板。

operatorframework.io/suggested-namespace

设置操作符应部署到的建议命名空间。

operatorframework.io/suggested-namespace-template

Namespace对象设置清单,其中包含为指定的命名空间指定的默认节点选择器。

operators.openshift.io/valid-subscription

用于列出使用操作符所需的任何特定订阅的自由格式数组。例如,'["3Scale 商业许可证", "Red Hat 托管集成"]'

operators.operatorframework.io/internal-objects

隐藏 UI 中不适合用户操作的 CRD。

包含 OpenShift Container Platform 许可证要求的示例 CSV
apiVersion: operators.coreos.com/v1alpha1
kind: ClusterServiceVersion
metadata:
  annotations:
    operators.openshift.io/valid-subscription: '["OpenShift Container Platform"]'
包含 3scale 许可证要求的示例 CSV
apiVersion: operators.coreos.com/v1alpha1
kind: ClusterServiceVersion
metadata:
  annotations:
    operators.openshift.io/valid-subscription: '["3Scale Commercial License", "Red Hat Managed Integration"]'

为受限网络环境启用您的操作符

作为操作符作者,您的操作符必须满足其他要求才能在受限网络或脱机环境中正常运行。

支持脱机模式的操作符要求
  • 用环境变量替换硬编码的镜像引用。

  • 在操作符的集群服务版本 (CSV) 中

    • 列出任何相关镜像或操作符可能需要执行其功能的其他容器镜像。

    • 通过摘要 (SHA) 而不是标签来引用所有指定的镜像。

  • 操作符的所有依赖项也必须支持在脱机模式下运行。

  • 您的操作符不得需要任何集群外资源。

先决条件
  • 包含 CSV 的操作符项目。以下过程使用 Memcached 操作符作为 Go、Ansible 和基于 Helm 的项目的示例。

步骤
  1. config/manager/manager.yaml文件中操作符使用的附加镜像引用设置环境变量

    config/manager/manager.yaml文件示例
    ...
    spec:
      ...
        spec:
          ...
          containers:
          - command:
            - /manager
            ...
            env:
            - name: <related_image_environment_variable> (1)
              value: "<related_image_reference_with_tag>" (2)
    1 定义环境变量,例如RELATED_IMAGE_MEMCACHED
    2 设置相关的镜像引用和标签,例如docker.io/memcached:1.4.36-alpine
  2. 在操作符项目类型的相关文件中用环境变量替换硬编码的镜像引用

    • 对于基于 Go 的 Operator 项目,请按以下示例所示,将环境变量添加到 `controllers/memcached_controller.go` 文件中

      示例 `controllers/memcached_controller.go` 文件
        // deploymentForMemcached returns a memcached Deployment object
      
      ...
      
      	Spec: corev1.PodSpec{
              	Containers: []corev1.Container{{
      -			Image:   "memcached:1.4.36-alpine", (1)
      +			Image:   os.Getenv("<related_image_environment_variable>"), (2)
      			Name:    "memcached",
      			Command: []string{"memcached", "-m=64", "-o", "modern", "-v"},
      			Ports: []corev1.ContainerPort{{
      
      ...
      1 删除镜像引用和标签。
      2 使用 `os.Getenv` 函数调用 ``。

      `os.Getenv` 函数在变量未设置时返回空字符串。更改文件之前,请先设置 ``。

    • 对于基于 Ansible 的 Operator 项目,请按以下示例所示,将环境变量添加到 `roles/memcached/tasks/main.yml` 文件中

      示例 `roles/memcached/tasks/main.yml` 文件
      spec:
        containers:
        - name: memcached
          command:
          - memcached
          - -m=64
          - -o
          - modern
          - -v
      -   image: "docker.io/memcached:1.4.36-alpine" (1)
      +   image: "{{ lookup('env', '<related_image_environment_variable>') }}" (2)
          ports:
            - containerPort: 11211
      
      ...
      1 删除镜像引用和标签。
      2 使用 `lookup` 函数调用 ``。
    • 对于基于 Helm 的 Operator 项目,请按以下示例所示,将 `overrideValues` 字段添加到 `watches.yaml` 文件中

      示例 `watches.yaml` 文件
      ...
      - group: demo.example.com
        version: v1alpha1
        kind: Memcached
        chart: helm-charts/memcached
        overrideValues: (1)
          relatedImage: ${<related_image_environment_variable>} (2)
      1 添加 `overrideValues` 字段。
      2 使用 ``(例如 `RELATED_IMAGE_MEMCACHED`)定义 `overrideValues` 字段。
      1. 按以下示例所示,将 `overrideValues` 字段的值添加到 `helm-charts/memchached/values.yaml` 文件中

        示例 `helm-charts/memchached/values.yaml` 文件
        ...
        relatedImage: ""
      2. 按以下示例所示,编辑 `helm-charts/memcached/templates/deployment.yaml` 文件中的图表模板

        示例 `helm-charts/memcached/templates/deployment.yaml` 文件
        containers:
          - name: {{ .Chart.Name }}
            securityContext:
              - toYaml {{ .Values.securityContext | nindent 12 }}
            image: "{{ .Values.image.pullPolicy }}
            env: (1)
              - name: related_image (2)
                value: "{{ .Values.relatedImage }}" (3)
        1 添加 `env` 字段。
        2 命名环境变量。
        3 定义环境变量的值。
  3. 使用以下更改将 `BUNDLE_GEN_FLAGS` 变量定义添加到您的 `Makefile` 中

    示例 `Makefile`
       BUNDLE_GEN_FLAGS ?= -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS)
    
       # USE_IMAGE_DIGESTS defines if images are resolved via tags or digests
       # You can enable this value if you would like to use SHA Based Digests
       # To enable set flag to true
       USE_IMAGE_DIGESTS ?= false
       ifeq ($(USE_IMAGE_DIGESTS), true)
             BUNDLE_GEN_FLAGS += --use-image-digests
       endif
    
    ...
    
    -  $(KUSTOMIZE) build config/manifests | operator-sdk generate bundle -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS) (1)
    +  $(KUSTOMIZE) build config/manifests | operator-sdk generate bundle $(BUNDLE_GEN_FLAGS) (2)
    
    ...
    1 删除 `Makefile` 中的这一行。
    2 将上面的行替换为这一行。
  4. 要更新您的 Operator 镜像以使用摘要 (SHA) 而不是标签,请运行 `make bundle` 命令并将 `USE_IMAGE_DIGESTS` 设置为 `true`

    $ make bundle USE_IMAGE_DIGESTS=true
  5. 添加 `disconnected` 注解,指示 Operator 在断开连接的环境中工作

    metadata:
      annotations:
        operators.openshift.io/infrastructure-features: '["disconnected"]'

    Operator 可以通过此基础架构功能在 OperatorHub 中进行筛选。

启用支持多种架构和操作系统的 Operator

Operator Lifecycle Manager (OLM) 假设所有 Operator 都在 Linux 主机上运行。但是,作为 Operator 作者,您可以指定您的 Operator 是否支持在其他架构上管理工作负载(如果 OpenShift Container Platform 集群中提供工作节点)。

如果您的 Operator 支持除 AMD64 和 Linux 之外的变体,您可以向提供 Operator 的集群服务版本 (CSV) 添加标签,以列出支持的变体。指示支持的架构和操作系统的标签由以下内容定义:

labels:
    operatorframework.io/arch.<arch>: supported (1)
    operatorframework.io/os.<os>: supported (2)
1 将 `` 设置为支持的字符串。
2 将 `` 设置为支持的字符串。

仅考虑默认通道的通道头部上的标签来根据标签过滤包清单。这意味着,例如,可以在非默认通道中为 Operator 提供其他架构,但该架构无法在 `PackageManifest` API 中用于筛选。

如果 CSV 不包含 `os` 标签,则默认情况下将其视为具有以下 Linux 支持标签:

labels:
    operatorframework.io/os.linux: supported

如果 CSV 不包含 `arch` 标签,则默认情况下将其视为具有以下 AMD64 支持标签:

labels:
    operatorframework.io/arch.amd64: supported

如果 Operator 支持多个节点架构或操作系统,您也可以添加多个标签。

先决条件
  • 具有 CSV 的 Operator 项目。

  • 为了支持列出多个架构和操作系统,CSV 中引用的 Operator 镜像必须是清单列表镜像。

  • 为了使 Operator 在受限网络或断开连接的环境中正常工作,还必须使用摘要 (SHA) 而不是标签来指定引用的镜像。

步骤
  • 在 CSV 的 `metadata.labels` 中为 Operator 支持的每个支持的架构和操作系统添加一个标签

    labels:
      operatorframework.io/arch.s390x: supported
      operatorframework.io/os.zos: supported
      operatorframework.io/os.linux: supported (1)
      operatorframework.io/arch.amd64: supported (1)
    1 添加新的架构或操作系统后,现在还必须显式包含默认的 `os.linux` 和 `arch.amd64` 变体。
其他资源

Operator 的架构和操作系统支持

在 OpenShift Container Platform 上的 Operator Lifecycle Manager (OLM) 中,当标记或筛选支持多种架构和操作系统的 Operator 时,支持以下字符串:

表 6. OpenShift Container Platform 上支持的架构
架构 字符串

AMD64

amd64

ARM64

arm64

IBM Power®

ppc64le

IBM Z®

s390x

表 7. OpenShift Container Platform 上支持的操作系统
操作系统 字符串

Linux

linux

z/OS

zos

不同版本的 OpenShift Container Platform 和其他基于 Kubernetes 的发行版可能支持不同的架构和操作系统集。

设置建议的命名空间

某些 Operator 必须部署在特定命名空间中,或者其辅助资源必须位于特定命名空间中才能正常工作。如果从订阅中解析,Operator Lifecycle Manager (OLM) 会将其 Operator 的命名空间资源默认为其订阅的命名空间。

作为 Operator 作者,您可以将所需的目標命名空间表示为集群服务版本 (CSV) 的一部分,以控制为其 Operator 安装的资源的最终命名空间。使用 OperatorHub 将 Operator 添加到集群时,这使 Web 控制台能够在安装过程中为集群管理员自动填充建议的命名空间。

步骤
  • 在您的 CSV 中,将 `operatorframework.io/suggested-namespace` 注解设置为您的建议命名空间

    metadata:
      annotations:
        operatorframework.io/suggested-namespace: <namespace> (1)
    1 设置您的建议命名空间。

设置带有默认节点选择器的建议命名空间

某些 Operator 期望仅在控制平面节点上运行,这可以通过 Operator 本身在 `Pod` 规范中设置 `nodeSelector` 来完成。

为了避免获得重复的且可能冲突的集群范围默认 `nodeSelector`,您可以在 Operator 运行的命名空间上设置默认节点选择器。默认节点选择器将优先于集群默认值,因此集群默认值不会应用于 Operator 命名空间中的 Pod。

使用 OperatorHub 将 Operator 添加到集群时,Web 控制台会在安装过程中为集群管理员自动填充建议的命名空间。建议的命名空间是使用包含在集群服务版本 (CSV) 中的 YAML 中的命名空间清单创建的。

步骤
  • 在您的 CSV 中,使用 `Namespace` 对象的清单设置 `operatorframework.io/suggested-namespace-template`。以下示例是具有指定命名空间默认节点选择器的示例 `Namespace` 的清单:

    metadata:
      annotations:
        operatorframework.io/suggested-namespace-template: (1)
          {
            "apiVersion": "v1",
            "kind": "Namespace",
            "metadata": {
              "name": "vertical-pod-autoscaler-suggested-template",
              "annotations": {
                "openshift.io/node-selector": ""
              }
            }
          }
    1 设置您的建议命名空间。

    如果 CSV 中同时存在 `suggested-namespace` 和 `suggested-namespace-template` 注解,则 `suggested-namespace-template` 应优先。

启用 Operator 条件

Operator Lifecycle Manager (OLM) 为 Operator 提供了一个通道,用于传达影响 OLM 在管理 Operator 时的行为的复杂状态。默认情况下,OLM 在安装 Operator 时会创建一个 `OperatorCondition` 自定义资源定义 (CRD)。根据 `OperatorCondition` 自定义资源 (CR) 中设置的条件,OLM 的行为会相应更改。

为了支持 Operator 条件,Operator 必须能够读取 OLM 创建的 `OperatorCondition` CR,并能够完成以下任务:

  • 获取特定条件。

  • 设置特定条件的状态。

可以使用 operator-lib 库来实现此功能。操作符作者可以在他们的操作符中提供 controller-runtime 客户端,以便库访问集群中操作符拥有的 OperatorCondition CR。

该库提供了一个通用的 Conditions 接口,该接口具有以下方法来在 OperatorCondition CR 中 获取设置 conditionType

获取

为了获取特定条件,该库使用 controller-runtime 中的 client.Get 函数,该函数需要 conditionAccessor 中存在的 types.NamespacedName 类型的 ObjectKey

设置

为了更新特定条件的状态,该库使用 controller-runtime 中的 client.Update 函数。如果 CRD 中不存在 conditionType,则会发生错误。

操作符只能修改 CR 的 status 子资源。操作符可以删除或更新 status.conditions 数组以包含该条件。有关条件中字段的格式和说明的更多详细信息,请参见上游 Condition GoDocs

Operator SDK 1.36.1 支持 operator-lib v0.11.0。

先决条件
  • 使用 Operator SDK 生成的 Operator 项目。

步骤

在您的 Operator 项目中启用 Operator 条件

  1. 在您的 Operator 项目的 go.mod 文件中,添加 operator-framework/operator-lib 作为所需库

    module github.com/example-inc/memcached-operator
    
    go 1.19
    
    require (
      k8s.io/apimachinery v0.26.0
      k8s.io/client-go v0.26.0
      sigs.k8s.io/controller-runtime v0.14.1
      operator-framework/operator-lib v0.11.0
    )
  2. 在您的 Operator 逻辑中编写您自己的构造函数,这将导致以下结果

    • 接受 controller-runtime 客户端。

    • 接受 conditionType

    • 返回一个 Condition 接口来更新或添加条件。

    由于 OLM 目前支持 Upgradeable 条件,您可以创建一个具有访问 Upgradeable 条件的方法的接口。例如

    import (
      ...
      apiv1 "github.com/operator-framework/api/pkg/operators/v1"
    )
    
    func NewUpgradeable(cl client.Client) (Condition, error) {
      return NewCondition(cl, "apiv1.OperatorUpgradeable")
    }
    
    cond, err := NewUpgradeable(cl);

    在此示例中,NewUpgradeable 构造函数进一步用于创建 Condition 类型的变量 condcond 变量将反过来具有 GetSet 方法,这些方法可用于处理 OLM Upgradeable 条件。

其他资源

定义 Webhook

Webhook 允许操作符作者在资源保存到对象存储并由操作符控制器处理之前拦截、修改和接受或拒绝资源。操作符生命周期管理器 (OLM) 在它们与您的操作符一起交付时可以管理这些 Webhook 的生命周期。

操作符的集群服务版本 (CSV) 资源可以包含一个 webhookdefinitions 部分来定义以下类型的 Webhook:

  • 准入 Webhook(验证和变异)

  • 转换 Webhook

步骤
  • 在操作符 CSV 的 spec 部分添加一个 webhookdefinitions 部分,并使用 ValidatingAdmissionWebhookMutatingAdmissionWebhookConversionWebhooktype 包含任何 Webhook 定义。以下示例包含所有三种类型的 Webhook

    包含 Webhook 的 CSV
      apiVersion: operators.coreos.com/v1alpha1
      kind: ClusterServiceVersion
      metadata:
        name: webhook-operator.v0.0.1
      spec:
        customresourcedefinitions:
          owned:
          - kind: WebhookTest
            name: webhooktests.webhook.operators.coreos.io (1)
            version: v1
        install:
          spec:
            deployments:
            - name: webhook-operator-webhook
              ...
              ...
              ...
          strategy: deployment
        installModes:
        - supported: false
          type: OwnNamespace
        - supported: false
          type: SingleNamespace
        - supported: false
          type: MultiNamespace
        - supported: true
          type: AllNamespaces
        webhookdefinitions:
        - type: ValidatingAdmissionWebhook (2)
          admissionReviewVersions:
          - v1beta1
          - v1
          containerPort: 443
          targetPort: 4343
          deploymentName: webhook-operator-webhook
          failurePolicy: Fail
          generateName: vwebhooktest.kb.io
          rules:
          - apiGroups:
            - webhook.operators.coreos.io
            apiVersions:
            - v1
            operations:
            - CREATE
            - UPDATE
            resources:
            - webhooktests
          sideEffects: None
          webhookPath: /validate-webhook-operators-coreos-io-v1-webhooktest
        - type: MutatingAdmissionWebhook (3)
          admissionReviewVersions:
          - v1beta1
          - v1
          containerPort: 443
          targetPort: 4343
          deploymentName: webhook-operator-webhook
          failurePolicy: Fail
          generateName: mwebhooktest.kb.io
          rules:
          - apiGroups:
            - webhook.operators.coreos.io
            apiVersions:
            - v1
            operations:
            - CREATE
            - UPDATE
            resources:
            - webhooktests
          sideEffects: None
          webhookPath: /mutate-webhook-operators-coreos-io-v1-webhooktest
        - type: ConversionWebhook (4)
          admissionReviewVersions:
          - v1beta1
          - v1
          containerPort: 443
          targetPort: 4343
          deploymentName: webhook-operator-webhook
          generateName: cwebhooktest.kb.io
          sideEffects: None
          webhookPath: /convert
          conversionCRDs:
          - webhooktests.webhook.operators.coreos.io (5)
    ...
    1 转换 Webhook 定向的 CRD 必须存在于此处。
    2 验证准入 Webhook。
    3 变异准入 Webhook。
    4 转换 Webhook。
    5 每个 CRD 的 spec.PreserveUnknownFields 属性必须设置为 falsenil

OLM 的 Webhook 注意事项

使用操作符生命周期管理器 (OLM) 部署具有 Webhook 的操作符时,必须定义以下内容:

  • type 字段必须设置为 ValidatingAdmissionWebhookMutatingAdmissionWebhookConversionWebhook,否则 CSV 将处于失败阶段。

  • CSV 必须包含一个其名称等效于 webhookdefinitiondeploymentName 字段中提供的值的部署。

创建 Webhook 时,OLM 确保 Webhook 只对与部署操作符的操作符组匹配的命名空间起作用。

证书颁发机构约束

OLM 配置为为每个部署提供单个证书颁发机构 (CA)。生成并安装 CA 到部署中的逻辑最初由 API 服务生命周期逻辑使用。因此

  • TLS 证书文件安装到部署的 /apiserver.local.config/certificates/apiserver.crt 位置。

  • TLS 密钥文件安装到部署的 /apiserver.local.config/certificates/apiserver.key 位置。

准入 Webhook 规则约束

为防止操作符将集群配置到不可恢复的状态,如果准入 Webhook 中定义的规则拦截任何以下请求,OLM 会将 CSV 置于失败阶段:

  • 目标为所有组的请求

  • 目标为 operators.coreos.com 组的请求

  • 目标为 ValidatingWebhookConfigurationsMutatingWebhookConfigurations 资源的请求

转换 Webhook 约束

如果转换 Webhook 定义不符合以下约束,OLM 会将 CSV 置于失败阶段:

  • 具有转换 Webhook 的 CSV 只能支持 AllNamespaces 安装模式。

  • 转换 Webhook 定向的 CRD 必须将其 spec.preserveUnknownFields 字段设置为 falsenil

  • CSV 中定义的转换 Webhook 必须定向到已拥有的 CRD。

  • 对于给定的 CRD,整个集群中只能有一个转换 Webhook。

了解您的自定义资源定义 (CRD)

您的操作符可以使用两种类型的自定义资源定义 (CRD):它拥有的 CRD 和它依赖的必需的 CRD。

已拥有的 CRD

您的操作符拥有的自定义资源定义 (CRD) 是 CSV 中最重要的部分。这建立了您的操作符与所需的 RBAC 规则、依赖项管理和其他 Kubernetes 概念之间的联系。

您的操作符通常使用多个 CRD 来链接概念,例如在一个对象中进行顶级数据库配置,而在另一个对象中表示副本集。每个 CRD 都应在 CSV 文件中列出。

表 8. 已拥有的 CRD 字段
字段 描述 必需/可选

名称

CRD 的完整名称。

必需

版本

该对象 API 的版本。

必需

种类

CRD 的机器可读名称。

必需

显示名称

CRD名称的可读版本,例如MongoDB Standalone

必需

描述

此CRD如何被Operator使用或CRD提供的功能的简短描述。

必需

此CRD所属的API组,例如database.example.com

可选

资源

您的CRD拥有一个或多个Kubernetes对象类型。这些列在resources部分中,以告知您的用户他们可能需要排查的对象,或如何连接到应用程序,例如公开数据库的服务或入口规则。

建议仅列出对人而言重要的对象,而不是您编排的所有内容的详尽列表。例如,不要列出存储内部状态且不应由用户修改的配置映射。

可选

SpecDescriptorsStatusDescriptorsActionDescriptors

这些描述符是一种方法,可以提示UI显示对最终用户最重要的Operator的某些输入或输出。如果您的CRD包含用户必须提供的密钥或配置映射的名称,您可以在此处指定。这些项目在兼容的UI中链接并突出显示。

有三种类型的描述符

  • SpecDescriptors:对对象spec块中字段的引用。

  • StatusDescriptors:对对象status块中字段的引用。

  • ActionDescriptors:对可以对对象执行的操作的引用。

所有描述符都接受以下字段

  • DisplayNameSpecStatusAction的可读名称。

  • DescriptionSpecStatusAction的简短描述及其如何被Operator使用。

  • Path:此描述符描述的对象上字段的点分隔路径。

  • X-Descriptors:用于确定此描述符具有哪些“功能”以及使用哪个UI组件。有关OpenShift Container Platform的规范React UI X-Descriptors列表,请参阅openshift/console项目。

有关描述符的更多信息,也请参阅openshift/console项目。

可选

以下示例描述了一个MongoDB Standalone CRD,它需要以密钥和配置映射的形式进行一些用户输入,并编排服务、有状态集、Pod和配置映射。

示例自有CRD
      - displayName: MongoDB Standalone
        group: mongodb.com
        kind: MongoDbStandalone
        name: mongodbstandalones.mongodb.com
        resources:
          - kind: Service
            name: ''
            version: v1
          - kind: StatefulSet
            name: ''
            version: v1beta2
          - kind: Pod
            name: ''
            version: v1
          - kind: ConfigMap
            name: ''
            version: v1
        specDescriptors:
          - description: Credentials for Ops Manager or Cloud Manager.
            displayName: Credentials
            path: credentials
            x-descriptors:
              - 'urn:alm:descriptor:com.tectonic.ui:selector:core:v1:Secret'
          - description: Project this deployment belongs to.
            displayName: Project
            path: project
            x-descriptors:
              - 'urn:alm:descriptor:com.tectonic.ui:selector:core:v1:ConfigMap'
          - description: MongoDB version to be installed.
            displayName: Version
            path: version
            x-descriptors:
              - 'urn:alm:descriptor:com.tectonic.ui:label'
        statusDescriptors:
          - description: The status of each of the pods for the MongoDB cluster.
            displayName: Pod Status
            path: pods
            x-descriptors:
              - 'urn:alm:descriptor:com.tectonic.ui:podStatuses'
        version: v1
        description: >-
          MongoDB Deployment consisting of only one host. No replication of
          data.

必需的CRD

依赖其他必需的CRD完全可选,仅用于减少各个Operator的范围,并提供一种方法来组合多个Operator以解决端到端用例。

一个示例是,一个Operator可能会设置一个应用程序并安装一个etcd集群(来自etcd Operator)用于分布式锁定,以及一个Postgres数据库(来自Postgres Operator)用于数据存储。

Operator Lifecycle Manager (OLM) 会检查集群中可用的CRD和Operator以满足这些需求。如果找到合适的版本,则会在所需的命名空间中启动Operator,并为每个Operator创建一个服务帐户,以创建、监视和修改所需的Kubernetes资源。

表9. 必需的CRD字段
字段 描述 必需/可选

名称

您需要的CRD的全名。

必需

版本

该对象 API 的版本。

必需

种类

Kubernetes对象类型。

必需

显示名称

CRD的可读版本。

必需

描述

组件如何适应您更大架构的摘要。

必需

示例必需CRD
    required:
    - name: etcdclusters.etcd.database.coreos.com
      version: v1beta2
      kind: EtcdCluster
      displayName: etcd Cluster
      description: Represents a cluster of etcd nodes.

CRD升级

如果CRD由单个集群服务版本 (CSV) 拥有,则OLM会立即升级自定义资源定义 (CRD)。如果CRD由多个CSV拥有,则在满足以下所有向后兼容条件后升级CRD。

  • 当前CRD中的所有现有服务版本都存在于新的CRD中。

  • 与CRD的服务版本关联的所有现有实例或自定义资源在针对新CRD的验证模式进行验证时都是有效的。

添加新的CRD版本

步骤

要向您的Operator添加新版本的CRD

  1. 在CSV的versions部分下,在CRD资源中添加一个新条目。

    例如,如果当前CRD具有版本v1alpha1,并且您想添加一个新版本v1beta1并将其标记为新的存储版本,请为v1beta1添加一个新条目。

    versions:
      - name: v1alpha1
        served: true
        storage: false
      - name: v1beta1 (1)
        served: true
        storage: true
    1 新条目。
  2. 如果CSV打算使用新版本,请确保更新CSV的owned部分中引用的CRD版本。

    customresourcedefinitions:
      owned:
      - name: cluster.example.com
        version: v1beta1 (1)
        kind: cluster
        displayName: Cluster
    1 更新version
  3. 将更新的CRD和CSV推送到您的bundle。

弃用或删除CRD版本

Operator Lifecycle Manager (OLM) 不允许立即删除自定义资源定义 (CRD) 的服务版本。相反,必须首先通过将CRD中的served字段设置为false来禁用CRD的已弃用版本。然后,可以在后续CRD升级中删除非服务版本。

步骤

要弃用和删除特定版本的CRD

  1. 将已弃用的版本标记为非服务版本,以指示此版本不再使用,并可能在后续升级中删除。例如

    versions:
      - name: v1alpha1
        served: false (1)
        storage: true
    1 设置为false
  2. 如果要弃用的版本当前是storage版本,请将storage版本切换到服务版本。例如

    versions:
      - name: v1alpha1
        served: false
        storage: false (1)
      - name: v1beta1
        served: true
        storage: true (1)
    1 相应地更新storage字段。

    要从CRD中删除特定版本(是或曾经是storage版本),必须从CRD状态中的storedVersion中删除该版本。如果OLM检测到新的CRD中不再存在存储的版本,它会尝试为您执行此操作。

  3. 使用上述更改升级CRD。

  4. 在后续升级周期中,可以完全从CRD中删除非服务版本。例如

    versions:
      - name: v1beta1
        served: true
        storage: true
  5. 如果从CRD中删除该版本,请确保相应地更新CSV的owned部分中引用的CRD版本。

CRD模板

必须让您的Operator的用户知道哪些选项是必需的,哪些是可选的。您可以为每个自定义资源定义 (CRD) 提供模板,其中包含一组最小的配置,作为名为alm-examples的注释。兼容的UI将预填充此模板,供用户进一步自定义。

此注释包含类型的列表,例如CRD名称以及Kubernetes对象的相应metadataspec

以下完整示例为EtcdClusterEtcdBackupEtcdRestore提供模板。

metadata:
  annotations:
    alm-examples: >-
      [{"apiVersion":"etcd.database.coreos.com/v1beta2","kind":"EtcdCluster","metadata":{"name":"example","namespace":"<operator_namespace>"},"spec":{"size":3,"version":"3.2.13"}},{"apiVersion":"etcd.database.coreos.com/v1beta2","kind":"EtcdRestore","metadata":{"name":"example-etcd-cluster"},"spec":{"etcdCluster":{"name":"example-etcd-cluster"},"backupStorageType":"S3","s3":{"path":"<full-s3-path>","awsSecret":"<aws-secret>"}}},{"apiVersion":"etcd.database.coreos.com/v1beta2","kind":"EtcdBackup","metadata":{"name":"example-etcd-cluster-backup"},"spec":{"etcdEndpoints":["<etcd-cluster-endpoints>"],"storageType":"S3","s3":{"path":"<full-s3-path>","awsSecret":"<aws-secret>"}}}]

隐藏内部对象

运营人员通常会在内部使用自定义资源定义 (CRD) 来完成任务。这些对象并非供用户操作,可能会让运营人员用户感到困惑。例如,数据库运营人员可能拥有一个 `Replication` CRD,该 CRD 会在用户创建具有 `replication: true` 的数据库对象时创建。

作为运营人员作者,您可以通过向运营人员的集群服务版本 (CSV) 添加 `operators.operatorframework.io/internal-objects` 注解,在用户界面中隐藏任何不供用户操作的 CRD。

步骤
  1. 在将某个 CRD 标记为内部对象之前,请确保任何调试信息或可能需要管理应用程序的配置都反映在您的 CR 的状态或 `spec` 块中(如果适用于您的运营人员)。

  2. 将 `operators.operatorframework.io/internal-objects` 注解添加到运营人员的 CSV 中,以指定要在用户界面中隐藏的任何内部对象。

    内部对象注解
    apiVersion: operators.coreos.com/v1alpha1
    kind: ClusterServiceVersion
    metadata:
      name: my-operator-v1.2.3
      annotations:
        operators.operatorframework.io/internal-objects: '["my.internal.crd1.io","my.internal.crd2.io"]' (1)
    ...
    1 将任何内部 CRD 设置为字符串数组。

初始化所需的自定义资源

运营人员可能需要用户在运营人员完全发挥功能之前实例化自定义资源。但是,用户可能难以确定需要什么或如何定义资源。

作为运营人员开发人员,您可以通过在运营人员安装期间将 `operatorframework.io/initialization-resource` 添加到集群服务版本 (CSV) 来指定单个必需的自定义资源。然后,系统会提示您通过 CSV 中提供的模板创建自定义资源。此注解必须包含一个模板,其中包含在安装期间初始化资源所需的完整 YAML 定义。

如果定义了此注解,则在从 OpenShift Container Platform Web 控制台安装运营人员后,系统会提示用户使用 CSV 中提供的模板创建资源。

步骤
  • 将 `operatorframework.io/initialization-resource` 注解添加到运营人员的 CSV 中,以指定所需的自定义资源。例如,以下注解需要创建一个 `StorageCluster` 资源并提供完整的 YAML 定义。

    初始化资源注解
    apiVersion: operators.coreos.com/v1alpha1
    kind: ClusterServiceVersion
    metadata:
      name: my-operator-v1.2.3
      annotations:
        operatorframework.io/initialization-resource: |-
            {
                "apiVersion": "ocs.openshift.io/v1",
                "kind": "StorageCluster",
                "metadata": {
                    "name": "example-storagecluster"
                },
                "spec": {
                    "manageNodes": false,
                    "monPVCTemplate": {
                        "spec": {
                            "accessModes": [
                                "ReadWriteOnce"
                            ],
                            "resources": {
                                "requests": {
                                    "storage": "10Gi"
                                }
                            },
                            "storageClassName": "gp2"
                        }
                    },
                    "storageDeviceSets": [
                        {
                            "count": 3,
                            "dataPVCTemplate": {
                                "spec": {
                                    "accessModes": [
                                        "ReadWriteOnce"
                                    ],
                                    "resources": {
                                        "requests": {
                                            "storage": "1Ti"
                                        }
                                    },
                                    "storageClassName": "gp2",
                                    "volumeMode": "Block"
                                }
                            },
                            "name": "example-deviceset",
                            "placement": {},
                            "portable": true,
                            "resources": {}
                        }
                    ]
                }
            }
    ...

了解您的 API 服务

与 CRD 一样,您的运营人员可以使用两种类型的 API 服务:*拥有* 的和*必需* 的。

拥有的 API 服务

当 CSV 拥有 API 服务时,它负责描述支持它的扩展 `api-server` 的部署及其提供的组/版本/种类 (GVK)。

API 服务由其提供的组/版本唯一标识,并且可以列出多次以表示其预期提供的不同种类。

表 10. 拥有的 API 服务字段
字段 描述 必需/可选

API 服务提供的组,例如 `database.example.com`。

必需

版本

API 服务的版本,例如 `v1alpha1`。

必需

种类

API 服务预期提供的种类。

必需

名称

提供的 API 服务的复数名称。

必需

DeploymentName

CSV 定义的与您的 API 服务相对应的部署的名称(对于拥有的 API 服务是必需的)。在 CSV 等待阶段,OLM 运营人员会在您的 CSV 的 `InstallStrategy` 中搜索具有匹配名称的 `Deployment`规范,如果找不到,则不会将 CSV 转变为“安装就绪”阶段。

必需

显示名称

API 服务名称的可读版本,例如 `MongoDB Standalone`。

必需

描述

关于此 API 服务如何被运营人员使用或 API 服务提供的功能的简短描述。

必需

资源

您的 API 服务拥有 Kubernetes 对象的一种或多种类型。这些列在资源部分中,以告知您的用户他们可能需要排查的对象或如何连接到应用程序,例如公开数据库的服务或入口规则。

建议仅列出对人而言重要的对象,而不是您编排的所有内容的详尽列表。例如,不要列出存储内部状态且不应由用户修改的配置映射。

可选

SpecDescriptorsStatusDescriptorsActionDescriptors

与拥有的 CRD 基本相同。

可选

API 服务资源创建

运营人员生命周期管理器 (OLM) 负责为每个唯一的拥有的 API 服务创建或替换服务和 API 服务资源。

  • 服务 Pod 选择器从与 API 服务描述的 `DeploymentName` 字段匹配的 CSV 部署中复制。

  • 为每个安装生成一个新的 CA 密钥/证书对,并且 base64 编码的 CA 捆绑包嵌入到相应的 API 服务资源中。

API 服务服务证书

每当安装拥有的 API 服务时,OLM 都会处理生成服务密钥/证书对。服务证书具有包含生成的 `Service` 资源的主机名的公用名 (CN),并由嵌入在相应 API 服务资源中的 CA 捆绑包的私钥签名。

证书存储为部署命名空间中的类型 `kubernetes.io/tls` 密钥,并且名为 `apiservice-cert` 的卷会自动附加到 CSV 中与 API 服务描述的 `DeploymentName` 字段匹配的部署的卷部分。

如果不存在,则还会将具有匹配名称的卷挂载附加到该部署的所有容器。这允许用户定义具有预期名称的卷挂载,以适应任何自定义路径要求。生成的卷挂载的路径默认为 `/apiserver.local.config/certificates`,并且任何具有相同路径的现有卷挂载都将被替换。

必需的 API 服务

OLM 确保所有必需的 CSV 都具有可用的 API 服务,并且在尝试安装之前所有预期的 GVK 都是可发现的。这允许 CSV 依赖于它不拥有的 API 服务提供的特定种类。

表 11. 必需的 API 服务字段
字段 描述 必需/可选

API 服务提供的组,例如 `database.example.com`。

必需

版本

API 服务的版本,例如 `v1alpha1`。

必需

种类

API 服务预期提供的种类。

必需

显示名称

API 服务名称的可读版本,例如 `MongoDB Standalone`。

必需

描述

关于此 API 服务如何被运营人员使用或 API 服务提供的功能的简短描述。

必需