×

集群服务版本 (CSV) 由一个ClusterServiceVersion 对象定义,它是由 Operator 元数据创建的 YAML 清单,可帮助 Operator Lifecycle Manager (OLM) 在集群中运行 Operator。它是 Operator 容器镜像附带的元数据,用于填充用户界面中的信息,例如其徽标、描述和版本。它也是运行 Operator 所需的技术信息的来源,例如它需要的 RBAC 规则以及它管理或依赖的自定义资源 (CR)。

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

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

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

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

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

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

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

CSV 生成命令消除了 Operator 作者需要深入了解 OLM 才能使其 Operator 与 OLM 交互或将元数据发布到目录注册表这一责任。此外,由于 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

其他资源
  • 请参见打包 Operator,了解包含生成包和 CSV 的完整过程。

生成的文 件和资源

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

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

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

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

  • Dockerfile bundle.Dockerfile

CSV 通常包含以下资源:

角色

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

集群角色

定义集群范围的 Operator 权限。

部署

定义如何在 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

操作符的语义版本,例如0.1.1

spec.customresourcedefinitions

操作符使用的任何CRD。如果deploy/目录中存在任何CRD YAML文件,则操作符SDK会自动填充此字段。但是,CRD清单规范中未包含的几个字段需要用户输入。

  • description:CRD的描述。

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

  • specDescriptors:操作符输入和输出的UI提示。

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

spec.replaces

此CSV替换的CSV名称。

spec.links

与操作符或正在管理的应用程序相关的URL(例如,网站和文档),每个URL都有一个nameurl

spec.selector

操作符可以在集群中配对资源的选择器。

spec.icon

操作符特有的base64编码图标,设置在具有mediatypebase64data字段中。

spec.maturity

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

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

当前需要用户干预的几个YAML字段可以从操作符代码中解析。

操作符元数据注解

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

基础设施功能注解

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

features.operators.openshift.io基础设施功能注解弃用了在早期版本的Red Hat OpenShift Service on AWS中使用的operators.openshift.io/infrastructure-features注解。有关更多信息,请参见“已弃用的基础设施功能注解”。

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

features.operators.openshift.io/disconnected

指定操作符是否支持镜像到断开连接的目录中,包括所有依赖项,并且不需要互联网访问。操作符利用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

指定操作符是否支持通过AWS Secure Token Service (STS) 使用Cloud Credential Operator (CCO) 对AWS API进行令牌化身份验证的配置。

"true""false"

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

指定操作符是否支持通过Azure Managed Identity使用Cloud Credential Operator (CCO) 对Azure API进行令牌化身份验证的配置。

"true""false"

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

指定操作符是否支持通过GCP Workload Identity Foundation (WIF) 使用Cloud Credential Operator (CCO) 对Google Cloud API进行令牌化身份验证的配置。

"true""false"

features.operators.openshift.io/cnf

指定操作符是否提供Cloud-Native Network Function (CNF) Kubernetes插件。

"true""false"

features.operators.openshift.io/cni

指定操作符是否提供Container Network Interface (CNI) Kubernetes插件。

"true""false"

features.operators.openshift.io/csi

指定操作符是否提供Container Storage Interface (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"
其他资源

已弃用的基础设施功能注解

从Red Hat OpenShift Service on AWS 4.14开始,operators.openshift.io/infrastructure-features注解组已被features.operators.openshift.io命名空间的注解组弃用。虽然建议您使用较新的注解,但在并行使用时,这两个组目前都被接受。

这些注解详细说明了操作符支持的基础设施功能。用户可以通过Web控制台或Red Hat 生态系统目录中的OperatorHub发现操作符时,可以查看和过滤这些功能。

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

disconnected

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

cnf

操作符提供Cloud-native Network Functions (CNF) Kubernetes插件。

cni

操作符提供Container Network Interface (CNI) Kubernetes插件。

csi

操作符提供Container Storage Interface (CSI) Kubernetes插件。

fips

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

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

proxy-aware

操作符支持在代理后面运行的集群。操作符接受标准代理环境变量HTTP_PROXYHTTPS_PROXY,当集群配置为使用代理时,Operator Lifecycle Manager (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

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

operatorframework.io/suggested-namespace

设置建议的 Operator 部署命名空间。

operatorframework.io/suggested-namespace-template

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

operators.openshift.io/valid-subscription

自由格式数组,用于列出使用 Operator 所需的任何特定订阅。例如,'["3Scale Commercial License", "Red Hat Managed Integration"]'

operators.operatorframework.io/internal-objects

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

包含 Red Hat OpenShift Service on AWS 许可证要求的 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"]'

为受限网络环境启用您的 Operator

作为 Operator 作者,您的 Operator 必须满足其他要求才能在受限网络或断开连接的环境中正常运行。

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

  • 在您的 Operator 的集群服务版本 (CSV) 中

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

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

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

  • 您的 Operator 不应需要任何集群外资源。

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

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

    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. 在您的 Operator 项目类型的相关文件中,将硬编码的镜像引用替换为环境变量

    • 对于基于 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函数调用<related_image_environment_variable>

      如果未设置变量,则os.Getenv函数将返回空字符串。在更改文件之前,请设置<related_image_environment_variable>

    • 对于基于 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函数调用<related_image_environment_variable>
    • 对于基于 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_environment_variable>定义overrideValues字段,例如RELATED_IMAGE_MEMCACHED
      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"]'

    OperatorHub 可以通过此基础设施功能过滤 Operator。

为多种架构和操作系统启用您的 Operator

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

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

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

仅考虑默认通道的通道头上的标签才能通过标签过滤包清单。这意味着,例如,可以在非默认通道中为 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) 而不是标签来指定引用的镜像。

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

    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.linuxarch.amd64变体。
其他资源

Operator 的架构和操作系统支持

在 Red Hat OpenShift Service on AWS 上的 Operator Lifecycle Manager (OLM) 中,在标记或过滤支持多种架构和操作系统的 Operator 时,支持以下字符串

表 6. Red Hat OpenShift Service on AWS 上支持的架构
架构 字符串

AMD64

amd64

ARM64

arm64

IBM Power®

ppc64le

IBM Z®

s390x

表 7. AWS 上 Red Hat OpenShift Service 支持的操作系统
操作系统 字符串

Linux

linux

z/OS

zos

不同版本的 AWS 上 Red Hat OpenShift Service 和其他基于 Kubernetes 的发行版可能支持不同的架构和操作系统。

设置建议的命名空间

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

作为 Operator 作者,您可以将所需的 target 命名空间表达为集群服务版本 (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 控制台会在安装过程中自动填充安装程序的建议命名空间。建议的命名空间是使用 YAML 中的命名空间清单创建的,该清单包含在集群服务版本 (CSV) 中。

步骤
  • 在您的 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-namespacesuggested-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 库来实现。Operator 作者可以在其 Operator 中提供controller-runtime 客户端,以便库访问集群中 Operator 拥有的OperatorCondition CR。

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

获取

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

设置

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

Operator 只允许修改 CR 的status 子资源。Operator 可以删除或更新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 允许 Operator 作者在资源保存到对象存储并由 Operator 控制器处理之前拦截、修改和接受或拒绝资源。Operator Lifecycle Manager (OLM) 可以管理这些 Webhook 的生命周期,前提是它们与您的 Operator 一起交付。

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

  • 准入 Webhook(验证和变异)

  • 转换 Webhook

步骤
  • 向 Operator 的 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 注意事项

使用 Operator Lifecycle Manager (OLM) 部署带有 Webhook 的 Operator 时,必须定义以下内容:

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

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

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

证书颁发机构约束

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)

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

拥有的 CRD

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

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

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

名称

CRD 的全名。

必需

版本

该对象 API 的版本。

必需

种类

CRD 的机器可读名称。

必需

显示名称

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

必需

描述

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

必需

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

可选

资源

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

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

可选

SpecDescriptorsStatusDescriptorsActionDescriptors

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

共有三种类型的描述符

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

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

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

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

  • DisplayNameSpecStatusAction的人类可读名称。

  • DescriptionSpecStatusAction的简短描述及其在 Operator 中的用法。

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

  • X-Descriptors:用于确定此描述符具有哪些“功能”以及要使用哪个 UI 组件。有关 Red Hat OpenShift Service on AWS 的规范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 升级

如果单个集群服务版本 (CSV) 拥有自定义资源定义 (CRD),则 OLM 会立即升级该 CRD。如果多个 CSV 拥有 CRD,则在满足以下所有向后兼容条件后,才会升级 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>"}}}]

隐藏内部对象

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

作为 Operator 作者,您可以通过向 Operator 的集群服务版本 (CSV) 添加 operators.operatorframework.io/internal-objects 注释,来隐藏 UI 中不适合用户操作的任何 CRD。

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

  2. operators.operatorframework.io/internal-objects 注释添加到 Operator 的 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 设置为字符串数组。

初始化必需的自定义资源

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

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

如果定义了此注释,则在从 AWS 网络控制台上的 Red Hat OpenShift Service 安装 Operator 后,系统会提示用户使用 CSV 中提供的模板创建资源。

步骤
  • operatorframework.io/initialization-resource 注释添加到 Operator 的 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 一样,您的 Operator 可能使用两种类型的 API 服务:已拥有必需

已拥有的 API 服务

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

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

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

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

必需

版本

API 服务的版本,例如 v1alpha1

必需

种类

API 服务预期提供的种类。

必需

名称

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

必需

DeploymentName

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

必需

显示名称

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

必需

描述

关于 API 服务如何由 Operator 使用的简短描述,或对 API 服务提供的功能的描述。

必需

资源

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

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

可选

SpecDescriptorsStatusDescriptorsActionDescriptors

与已拥有的 CRD 基本相同。

可选

API 服务资源创建

Operator Lifecycle Manager (OLM) 负责为每个唯一的已拥有 API 服务创建或替换服务和 API 服务资源。

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

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

API 服务服务证书

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

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

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

必需的API服务

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

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

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

必需

版本

API 服务的版本,例如 v1alpha1

必需

种类

API 服务预期提供的种类。

必需

显示名称

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

必需

描述

关于 API 服务如何由 Operator 使用的简短描述,或对 API 服务提供的功能的描述。

必需