12.4. 生成 ClusterServiceVersion (CSV)
ClusterServiceVersion (CSV) 是一个利用 Operator 元数据创建的 YAML 清单,可辅助 Operator Lifecycle Manager (OLM) 在集群中运行 Operator。它是 Operator 容器镜像附带的元数据,用于在用户界面填充徽标、描述和版本等信息。此外,CSV 还是运行 Operator 所需的技术信息来源,类似于其需要的 RBAC 规则及其管理或依赖的自定义资源 (CR)。
Operator SDK 中包含 olm-catalog gen-csv
子命令,用于通过手动定义的 YAML 清单和 Operator 源文件中包含的信息为自定义的当前 Operator 项目生成 ClusterServiceVersion (CSV)。
借助生成 CSV 的命令,Operator 作者便无需深入掌握为了让其 Operator 与 OLM 交互或向 Catalog Registry 发布元数据所需的 OLM 知识。此外,因为实现了新的 Kubernetes 和 OLM 功能,CSV spec 可能会随着时间的推移而有所变化,而 Operator SDK 可轻松扩展其更新系统,以应对 CSV 的未来新功能。
CSV 版本与 Operator 的版本相同,在升级 Operator 版本的同时会生成新 CSV。Operator 作者可使用 --csv-version
标记将其 Operator 状态与所提供的语义版本一起封装至 CSV 中:
$ operator-sdk olm-catalog gen-csv --csv-version <version>
此操作采用等幂方式,仅会在提供新版本或更改 YAML 清单或源文件时才会更新 CSV 文件。Operator 作者不必直接修改 CSV 清单中的大部分字段。本指南中已经明确了需要修改的字段。例如:metadata.name
中必须包含 CSV 版本信息。
12.4.1. CSV 生成的工作方式
Operator 项目的 deploy/
目录是部署 Operator 需要的所有清单的标准位置。Operator SDK 可使用 deploy/
中的清单数据来编写 CSV。以下命令:
$ operator-sdk olm-catalog gen-csv --csv-version <version>
默认将 CSV YAML 文件写入 deploy/olm-catalog/
目录中。
生成 CSV 只需三类清单:
-
operator.yaml
-
*_{crd,cr}.yaml
-
RBAC 角色文件,如
role.yaml
Operator 作者对这些文件可能有不同的版本要求,并且可配置 deploy/olm-catalog/csv-config.yaml
中要包含哪些特定文件。
工作流
根据是否检测到了现有 CSV,并假设使用所有配置默认值,olm-catalog gen-csv
子命令将:
使用 YAML 清单和源文件中的可用数据新建一个 CSV,其位置和命名约定与当前存在的信息相同。
-
该更新机制会检查
deploy/
中是否存在现有 CSV。如果未找到,便会创建一个 ClusterServiceVersion 对象,这里称为 cache,并填充容易从 Operator 元数据派生的字段,如 Kubernetes APIObjectMeta
。 -
更新机制在
deploy/
中搜索包含 CSV 所用数据(如 Deployment 资源)的清单,并使用该数据设置 cache 中的适当 CSV 字段。 - 搜索完成后,每个填充的 cache 字段都会写回到 CSV YAML 文件中。
-
该更新机制会检查
或:
使用 YAML 清单和源文件中的可用数据更新当前预定义位置的现有 CSV。
-
该更新机制会检查
deploy/
中是否存在现有 CSV。找到后,CSV YAML 文件内容会被封送至 ClusterServiceVersion cache 中。 -
更新机制在
deploy/
中搜索包含 CSV 所用数据(如 Deployment 资源)的清单,并使用该数据设置 cache 中的适当 CSV 字段。 - 搜索完成后,每个填充的 cache 字段都会写回到 CSV YAML 文件中。
-
该更新机制会检查
单个 YAML 字段(而非整个文件)会被覆盖,因为 CSV 的描述和其他未生成的部分将被保留。
12.4.2. CSV 组成配置
Operator 作者可通过填充 deploy/olm-catalog/csv-config.yaml
文件中的几个字段来配置 CSV 组成:
字段 | 描述 |
---|---|
|
Operator 资源清单文件路径。默认为 |
|
CRD 和 CR 清单文件路径列表。默认为 |
|
RBAC 角色清单文件路径列表。默认为 |
12.4.3. 手动定义的 CSV 字段
很多 CSV 字段无法使用生成的非 SDK 特定清单进行填充。这些字段大多由人工编写,是一些有关 Operator 和各种自定义资源定义 (CRD) 的英文元数据。
Operator 作者必须直接修改其 CSV YAML 文件,将个性化数据添加至以下必填字段。当检测到任何必填字段中缺少数据时,Operator SDK 就会发出一个 CSV 生成警告。
字段 | 描述 |
---|---|
|
该 CSV 的唯一名称。Operator 版本应包含在名称中,以保证唯一性,如 |
|
根据 Operator 成熟度模型划分的 Operator 能力水平。选项包括 |
| 用于标识 Operator 的公共名称。 |
| 简单描述 Operator 的功能。 |
| 描述 Operator 的关键词。 |
|
维护 Operator 的个人或组织实体,含 |
|
Operator 供应商(通常为一个组织),含 |
| 供 Operator 内部使用的键值对。 |
|
Operator 的语义版本,如 |
|
Operator 使用的任何 CRD。如果
|
字段 | 描述 |
---|---|
| 被该 CSV 替换的 CSV 名称。 |
|
与被管理的 Operator 或应用程序相关的 URL(如网站和文档),各自含 |
| Operator 可用于配对群集中资源的选择器。 |
|
Operator 独有的 base64 编码图标,通过 |
|
软件在这个版本中达到的成熟度。选项包括 |
有关以上每个字段应包含哪些数据的更多详情,请参见 CSV spec。
当前需要用户干预的多个 YAML 字段可能会从 Operator 代码中解析出来;这种 Operator SDK 功能将在未来的设计文件中阐述。
其他资源
12.4.4. 生成 CSV
先决条件
- 使用 Operator SDK 生成一个 Operator 项目
流程
-
在 Operator 项目中,通过修改
deploy/olm-catalog/csv-config.yaml
文件来配置您的 CSV 组成(如果需要)。 生成 CSV:
$ operator-sdk olm-catalog gen-csv --csv-version <version>
-
在
deploy/olm-catalog/
目录中生成的新 CSV 中,确保正确设置所有必填的手动定义字段。
12.4.5. 为受限网络环境启用 Operator
作为 Operator 作者,您的 CSV 必须满足以下额外要求才能让 Operator 在受限网络环境中正常运行:
- 列出 Operator 执行其功能可能需要的任何 相关镜像或其他容器镜像。
- 通过摘要 (SHA) 而不是标签来引用所有指定的镜像。
您必须在 Operator 的 CSV 的两个位置中使用 SHA 引用相关镜像:
在
spec.relatedImages
中:... spec: relatedImages: 1 - name: etcd-operator 2 image: quay.io/etcd-operator/operator@sha256:d134a9865524c29fcf75bbc4469013bc38d8a15cb5f41acfddb6b9e492f556e4 3 - name: etcd-image image: quay.io/etcd-operator/etcd@sha256:13348c15263bd8838ec1d5fc4550ede9860fcbb0f843e48cbccec07810eebb68 ...
在 Operators Deployment 的
env
部分中,声明环境变量,以注入 Operator 应使用的镜像:spec: install: spec: deployments: - name: etcd-operator-v3.1.1 spec: replicas: 1 selector: matchLabels: name: etcd-operator strategy: type: Recreate template: metadata: labels: name: etcd-operator spec: containers: - args: - /opt/etcd/bin/etcd_operator_run.sh env: - name: WATCH_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.annotations['olm.targetNamespaces'] - name: ETCD_OPERATOR_DEFAULT_ETCD_IMAGE 1 value: quay.io/etcd-operator/etcd@sha256:13348c15263bd8838ec1d5fc4550ede9860fcbb0f843e48cbccec07810eebb68 2 - name: ETCD_LOG_LEVEL value: INFO image: quay.io/etcd-operator/operator@sha256:d134a9865524c29fcf75bbc4469013bc38d8a15cb5f41acfddb6b9e492f556e4 3 imagePullPolicy: IfNotPresent livenessProbe: httpGet: path: /healthy port: 8080 initialDelaySeconds: 10 periodSeconds: 30 name: etcd-operator readinessProbe: httpGet: path: /ready port: 8080 initialDelaySeconds: 10 periodSeconds: 30 resources: {} serviceAccountName: etcd-operator strategy: deployment
12.4.6. 为多个架构和操作系统启用您的 Operator
Operator Lifecycle Manager (OLM) 假设所有 Operator 都在 Linux 主机中运行。但是,作为 Operator 的开发者,如果 OpenShift Container Platform 集群中有 worker 节点,您可以指定您的 Operator 是否支持管理其他架构上的工作负载。
如果 Operator 支持 AMD64 和 Linux 以外的变体,您可以向 CSV 添加标签,从而提供 Operator 列出支持的变体。标注支持的架构和操作系统的标签定义如下:
labels: operatorframework.io/arch.<arch>: supported 1 operatorframework.io/os.<os>: supported 2
只有默认频道的频道头的标签才会在根据标签进行过滤时考虑 PackageManifests。例如,这表示有可能在非默认频道中为 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)而不是标签(tag)来指定引用的镜像。
流程
在 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 2
其他资源
- 如需有关清单列表的更多信息 ,请参阅Image Manifest V 2, Schema 2 说明。
12.4.6.1. Operator 的架构和操作系统支持
在标记或过滤支持多个架构和操作系统的 Operator 时,OpenShift Container Platform 上的 Operator Lifecycle Manager (OLM) 支持以下字符串:
架构 | 字符串 |
---|---|
AMD64 |
|
64-bit PowerPC little-endian |
|
IBM Z |
|
操作系统 | 字符串 |
---|---|
Linux |
|
z/OS |
|
OpenShift Container Platform 的不同版本和其他基于 Kubernetes 的发行版本可能支持不同的架构和操作系统集合。
12.4.7. 了解您的自定义资源定义 (CRD)
您的 Operator 可能会使用两类自定义资源定义 (CRD):一类归 Operator 拥有,另一类为 Operator 依赖的必要 CRD。
12.4.7.1. 拥有的 CRD
Operator 拥有的 CRD 是 CSV 最重要的组成部分。这类 CRD 会在您的 Operator 与所需 RBAC 规则、依赖项管理和其他 Kubernetes 概念之间建立联系。
Operator 通常会使用多个 CRD 将各个概念链接在一起,例如一个对象中的顶级数据库配置和另一对象中的 ReplicaSets 表示形式。这在 CSV 文件中应逐一列出。
字段 | 描述 | 必填/选填 |
---|---|---|
| CRD 的全名。 | 必填 |
| 该对象 API 的版本。 | 必填 |
| CRD 的机器可读名称。 | 必填 |
|
CRD 名称的人类可读版本,如 | 必填 |
| 有关 Operator 如何使用该 CRD 的简短描述,或有关 CRD 所提供功能的描述。 | 必填 |
|
该 CRD 所属的 API 组,如 | 选填 |
| 您的 CRD 可能拥有一类或多类 Kubernetes 对象。它们将在资源部分列出,用于告知用户他们可能需要排除故障的对象或如何连接至应用程序,如公开数据库的 Service 或 Ingress 规则。 建议仅列出对人重要的对象,而不必列出您编排的所有对象。例如,存储不应由用户修改的内部状态的 ConfigMaps 不应出现在此处。 | 选填 |
| 这些描述符是通过对终端用户来说最重要的 Operator 的某些输入或输出提示 UI 的一种方式。如果您的 CRD 包含用户必须提供的 Secret 或 ConfigMap 的名称,您可在此处指定。这些项目在兼容的 UI 中链接并突出显示。 共有以下三类描述符:
所有描述符均接受以下字段:
有关描述符的更多一般信息,请参见 openshift/console 项目。 | 选填 |
以下示例描述了一个 MongoDB Standalone
CRD,要求某些用户以 Secret 和 ConfigMap 的形式输入,并编排 Service、StatefulSet、Pod 和 ConfigMap:
拥有的 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.
12.4.7.2. 必需的 CRD
是否依赖其他必需 CRD 完全可以自由选择,它们存在的目的只是为了缩小单个 Operator 的范围,并提供一种将多个 Operator 组合到一起来解决端到端用例的办法。
例如,一个 Operator 可设置一个应用程序并(从 etcd Operator)安装一个 etcd 集群以用于分布式锁定,以及一个 Postgres 数据库(来自 Postgres Operator)以用于数据存储。
Operator Lifecycle Manager (OLM) 对照集群中可用的 CRD 和 Operator 进行检查,以满足这些要求。如果找到合适的版本,Operator 将在所需命名空间中启动,并为每个 Operator 创建一个服务账户,以创建、监视和修改所需的 Kubernetes 资源。
字段 | 描述 | 必填/选填 |
---|---|---|
| 所需 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.
12.4.7.3. CRD 模板
Operator 用户需要了解哪个选项必填,哪个选项选填。您可为您的每个 CRD 提供模板,并以最小配置集作为名为 alm-examples
的注解。兼容 UI 会预先填充该模板,供用户进一步自定义。
该注解由一个 kind
列表组成,如 CRD 名称和对应的 Kubernetes 对象的 metadata
和 spec
。
以下完整示例提供了 EtcdCluster
、EtcdBackup
和 EtcdRestore
模板:
metadata: annotations: alm-examples: >- [{"apiVersion":"etcd.database.coreos.com/v1beta2","kind":"EtcdCluster","metadata":{"name":"example","namespace":"default"},"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>"}}}]
12.4.7.4. 隐藏内部对象
Operator 在内部使用自定义资源定义 (CRD) 来完成任务是常见的。这些对象并不是供用户操作的,且可能会让 Operator 用户混淆。例如,数据库 Operator 可能会有一个 Replication CRD,当用户创建带有 replication:true
的数据库对象时就会创建它。
如果 CRD 不是供用户操作的,则可以在 Operator 的 ClusterServiceVersion (CSV) 中使用 operators.operatorframework.io/internal-objects
注解以使它们在用户界面中被隐藏:
内部对象注解
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 设置为字符串数组。
在将一个 CRD 标记为 internal 之前,请确保所有管理应用程序所需的调试信息或配置都会反映在 CR 的状态或 spec
块中(如果适用于您的 Operator)。
12.4.8. 了解您的 API 服务
与 CRD 一样,您的 Operator 可使用两类 APIService:拥有的和必需的。
12.4.8.1. 拥有的 APIService
如果 CSV 拥有 APIService,它将负责描述为其提供支持的扩展 api-server
的部署及其提供的 group-version-kinds
。
APIService 由其提供的 group-version
唯一标识,且可多次列出,以表示其期望提供的不同类型。
字段 | 描述 | 必填/选填 |
---|---|---|
|
由 APIService 提供的组,如 | 必填 |
|
APIService 的版本,如 | 必填 |
| 预期由 APIService 提供的类型。 | 必填 |
| 所提供的 APIService 的复数名称 | 必填 |
| 由您的 CSV 定义的部署名称,对应您的 APIService(对于拥有的 APIService 来说必填)。在 CSV 待定阶段,OLM Operator 会在您的 CSV InstallStrategy 中搜索具有匹配名称的部署 spec,如果未找到,则不会将 CSV 转换至安装就绪阶段。 | 必填 |
|
APIService 名称的人类可读版本,如 | 必填 |
| 有关 Operator 如何使用该 APIService 的简短描述,或有关 APIService 所提供功能的描述。 | 必填 |
| 您的 APIService 可能拥有一类或多类 Kubernetes 对象。它们将在资源部分列出,用于告知用户他们可能需要排除故障的对象或如何连接至应用程序,如公开数据库的 Service 或 Ingress 规则。 建议仅列出对人重要的对象,而不必列出您编排的所有对象。例如,存储不应由用户修改的内部状态的 ConfigMaps 不应出现在此处。 | 选填 |
| 与拥有的 CRD 基本相同。 | 选填 |
12.4.8.1.1. APIService 资源创建
Operator Lifecycle Manager (OLM) 负责为每个唯一拥有的 APIService 创建或替换 Service 及 APIService 资源:
-
Service Pod 选择器从与 APIServiceDescription 的
DeploymentName
相匹配的 CSV 部署中复制。 - 每次安装都会生成一个新的 CA 密钥/证书对,且 base64 编码的 CA 捆绑包会嵌入到相应 APIService 资源中。
12.4.8.1.2. APIService 服务证书
每当安装拥有的 APIService 时,OLM 均会处理服务密钥/证书对的生成。服务证书有一个包含所生成 Service 资源的主机名的 CN,并由嵌入至对应 APIService 资源中的 CA 捆绑包的私钥签名。
该证书作为类型 kubernetes.io/tls
Secret 存储在部署命名空间中,一个名为 apiservice-cert
的卷会自动附加至 CSV 中与 APIServiceDescription 的 DeploymentName
字段相匹配的部署的 Volumes 部分中。
如果尚不存在,则具有匹配名称的 VolumeMount 也会附加至该部署的所有容器中。这样用户便可使用预期名称来定义 VolumeMount,以适应任何自定义路径要求。所生成的 VolumeMount 的默认路径为 /apiserver.local.config/certificates
,具有相同路径的任何现有 VolumeMount 均会被替换掉。
12.4.8.2. 必需的 APIService
OLM 可保证所有必需的 CSV 均有可用 APIService,且所有预期的 group-version-kinds
在试图安装前均可发现。这样 CSV 便可依赖由 APIService 提供的、并非它拥有的特定类别。
字段 | 描述 | 必填/选填 |
---|---|---|
|
由 APIService 提供的组,如 | 必填 |
|
APIService 的版本,如 | 必填 |
| 预期由 APIService 提供的类型。 | 必填 |
|
APIService 名称的人类可读版本,如 | 必填 |
| 有关 Operator 如何使用该 APIService 的简短描述,或有关 APIService 所提供功能的描述。 | 必填 |