etcd
├── manifests
│ ├── etcdcluster.crd.yaml
│ └── etcdoperator.clusterserviceversion.yaml
│ └── secret.yaml
│ └── configmap.yaml
└── metadata
└── annotations.yaml
└── dependencies.yaml
Operator的Bundle格式是由Operator Framework引入的一种打包格式。为了提高可扩展性并更好地支持上游用户托管自己的目录,Bundle格式规范简化了Operator元数据的分发。
一个Operator Bundle代表Operator的单个版本。磁盘上的Bundle清单文件被容器化并作为Bundle镜像交付,这是一个不可运行的容器镜像,用于存储Kubernetes清单文件和Operator元数据。然后,使用现有的容器工具(如podman
和docker
)和容器注册表(如Quay)来管理Bundle镜像的存储和分发。
Operator元数据可以包含:
标识Operator的信息,例如其名称和版本。
驱动UI的附加信息,例如其图标和一些示例自定义资源 (CR)。
必需和提供的API。
相关的镜像。
将清单文件加载到Operator注册表数据库时,将验证以下要求:
Bundle必须在注释中至少定义一个通道。
每个Bundle都只有一个集群服务版本 (CSV)。
如果CSV拥有自定义资源定义 (CRD),则该CRD必须存在于Bundle中。
Bundle清单文件指的是一组Kubernetes清单文件,这些文件定义了Operator的部署和RBAC模型。
一个Bundle在其/manifests
目录中包含每个目录一个CSV,以及通常定义CSV拥有API的CRD。
etcd
├── manifests
│ ├── etcdcluster.crd.yaml
│ └── etcdoperator.clusterserviceversion.yaml
│ └── secret.yaml
│ └── configmap.yaml
└── metadata
└── annotations.yaml
└── dependencies.yaml
以下对象类型也可以可选地包含在Bundle的/manifests
目录中:
ClusterRole
ClusterRoleBinding
ConfigMap
ConsoleCLIDownload
ConsoleLink
ConsoleQuickStart
ConsoleYamlSample
PodDisruptionBudget
PriorityClass
PrometheusRule
Role
RoleBinding
Secret
Service
ServiceAccount
ServiceMonitor
VerticalPodAutoscaler
当这些可选对象包含在Bundle中时,Operator Lifecycle Manager (OLM)可以从Bundle中创建它们,并与CSV一起管理它们的生存周期。
删除CSV时,OLM会删除可选对象。
升级CSV时:
如果可选对象的名称相同,OLM会就地更新它。
如果可选对象的名称在版本之间发生了更改,OLM会删除并重新创建它。
Bundle还在其/metadata
目录中包含一个annotations.yaml
文件。此文件定义更高级别的聚合数据,有助于描述Bundle的格式和包信息,以及如何将Bundle添加到Bundle索引中。
annotations.yaml
示例annotations:
operators.operatorframework.io.bundle.mediatype.v1: "registry+v1" (1)
operators.operatorframework.io.bundle.manifests.v1: "manifests/" (2)
operators.operatorframework.io.bundle.metadata.v1: "metadata/" (3)
operators.operatorframework.io.bundle.package.v1: "test-operator" (4)
operators.operatorframework.io.bundle.channels.v1: "beta,stable" (5)
operators.operatorframework.io.bundle.channel.default.v1: "stable" (6)
1 | Operator Bundle的媒体类型或格式。registry+v1 格式表示它包含CSV及其关联的Kubernetes对象。 |
2 | 镜像中包含Operator清单文件的目录的路径。此标签保留供将来使用,目前默认为manifests/ 。值manifests.v1 意味着Bundle包含Operator清单文件。 |
3 | 镜像中包含有关Bundle的元数据文件的目录的路径。此标签保留供将来使用,目前默认为metadata/ 。值metadata.v1 意味着此Bundle具有Operator元数据。 |
4 | Bundle的包名称。 |
5 | 添加到Operator注册表时,Bundle订阅的通道列表。 |
6 | 从注册表安装时,Operator应该订阅的默认通道。 |
如果出现不匹配, |
Operator 的依赖项列在 bundle 的 `metadata/` 文件夹中的 `dependencies.yaml` 文件中。此文件是可选的,目前仅用于指定明确的 Operator 版本依赖关系。
依赖项列表中的每个项目都包含一个 `type` 字段,用于指定依赖项的类型。支持以下类型的 Operator 依赖项:
olm.package
此类型表示对特定 Operator 版本的依赖。依赖信息必须包含包名和包的语义版本 (semver) 格式的版本。例如,您可以指定确切的版本,例如 `0.5.2`,或版本范围,例如 `>0.5.1`。
olm.gvk
使用此类型,作者可以指定具有组/版本/种类 (GVK) 信息的依赖项,类似于 CSV 中现有的基于 CRD 和 API 的用法。这是一种路径,使 Operator 作者能够将所有依赖项(API 或显式版本)整合到同一个位置。
olm.constraint
此类型声明对任意 Operator 属性的通用约束。
在以下示例中,为 Prometheus Operator 和 etcd CRD 指定了依赖项。
dependencies.yaml
文件示例dependencies:
- type: olm.package
value:
packageName: prometheus
version: ">0.27.0"
- type: olm.gvk
value:
group: etcd.database.coreos.com
kind: EtcdCluster
version: v1beta2
Operator Framework 提供了 `opm` CLI 工具,用于 Operator bundle 格式。此工具允许您从类似于软件存储库的 Operator bundle 列表创建和维护 Operator 目录。结果是一个容器镜像,可以存储在容器注册表中,然后安装在集群上。
目录包含指向 Operator 清单内容的指针数据库,可以通过运行容器镜像时提供的包含的 API 进行查询。在 Red Hat OpenShift Service on AWS 上,Operator 生命周期管理器 (OLM) 可以引用目录源中的镜像(由 `CatalogSource` 对象定义),该对象定期轮询镜像,以便能够频繁更新集群上已安装的 Operator。
有关安装 `opm` CLI 的步骤,请参阅 CLI 工具。
基于文件的目录 是 Operator 生命周期管理器 (OLM) 中目录格式的最新迭代。它是早期 SQLite 数据库格式的基于纯文本(JSON 或 YAML)的声明性配置演变,并且完全向后兼容。此格式的目标是启用 Operator 目录编辑、组合和可扩展性。
使用基于文件的目录,与目录内容交互的用户能够直接更改格式并验证其更改是否有效。由于此格式是纯文本 JSON 或 YAML,因此目录维护者可以轻松地手动或使用广泛已知和支持的 JSON 或 YAML 工具(例如 `jq` CLI)来操作目录元数据。
此可编辑性支持以下功能和用户定义的扩展:
将现有 bundle 推广到新通道
更改包的默认通道
用于添加、更新和删除升级边的自定义算法
基于文件的目录存储在任意目录层次结构中,这使得目录组合成为可能。例如,考虑两个单独的基于文件的目录:`catalogA` 和 `catalogB`。目录维护者可以通过创建一个新目录 `catalogC` 并将 `catalogA` 和 `catalogB` 复制到其中来创建一个新的组合目录。
这种组合性支持分散式目录。此格式允许 Operator 作者维护特定于 Operator 的目录,并且允许维护者轻松构建由单个 Operator 目录组成的目录。可以通过组合多个其他目录、提取一个目录的子集或这两种方法的组合来组合基于文件的目录。
不允许重复的包和包内的重复 bundle。如果发现任何重复项,`opm validate` 命令将返回错误。 |
由于 Operator 作者最熟悉他们的 Operator、其依赖项及其升级兼容性,因此他们能够维护他们自己的特定于 Operator 的目录并直接控制其内容。使用基于文件的目录,Operator 作者拥有在目录中构建和维护其包的任务。但是,组合目录维护者只拥有管理其目录中的包并将目录发布给用户这一任务。
基于文件的目录规范是目录的低级表示。虽然可以直接以其低级形式维护它,但目录维护者可以在其之上构建有趣的扩展,这些扩展可以被他们自己的自定义工具用来进行任意数量的更改。
例如,一个工具可以将高级 API(例如 `(mode=semver)`)转换为低级基于文件的目录格式的升级边。或者,目录维护者可能需要通过向满足特定条件的 bundle 添加新属性来自定义所有 bundle 元数据。
虽然这种可扩展性允许在低级 API 之上开发用于未来 Red Hat OpenShift Service on AWS 版本的额外官方工具,但主要好处是目录维护者也具有此功能。
从 Red Hat OpenShift Service on AWS 4.11 开始,默认的 Red Hat 提供的 Operator 目录以基于文件的目录格式发布。Red Hat OpenShift Service on AWS 4.6 到 4.10 的默认 Red Hat 提供的 Operator 目录以已弃用的 SQLite 数据库格式发布。 与 SQLite 数据库格式相关的 `opm` 子命令、标志和功能也已弃用,并将在此版本的未来版本中删除。这些功能仍然受支持,并且必须用于使用已弃用的 SQLite 数据库格式的目录。 许多用于处理 SQLite 数据库格式的 `opm` 子命令和标志(例如 `opm index prune`)不适用于基于文件的目录格式。有关使用基于文件的目录的更多信息,请参阅 管理自定义目录。 |
基于文件的目录可以存储和加载自基于目录的文件系统。`opm` CLI 通过遍历根目录并递归进入子目录来加载目录。CLI 会尝试加载它找到的每个文件,如果发生任何错误则会失败。
可以使用 `.indexignore` 文件忽略非目录文件,其模式和优先级规则与 `.gitignore` 文件相同。
# Ignore everything except non-object .json and .yaml files
**/*
!*.json
!*.yaml
**/objects/*.json
**/objects/*.yaml
目录维护者可以灵活地选择他们想要的布局,但建议将每个包的基于文件的目录 blob 存储在单独的子目录中。每个单独的文件可以是 JSON 或 YAML;目录中的每个文件都不需要使用相同的格式。
catalog
├── packageA
│ └── index.yaml
├── packageB
│ ├── .indexignore
│ ├── index.yaml
│ └── objects
│ └── packageB.v0.1.0.clusterserviceversion.yaml
└── packageC
└── index.json
└── deprecations.yaml
此推荐结构具有目录层次结构中的每个子目录都是一个自包含的目录的属性,这使得目录组合、发现和导航成为简单易行的文件系统操作。该目录也可以通过将其复制到父目录的根目录来包含在父目录中。
基于文件的目录使用一种基于CUE 语言规范的格式,可以扩展任意模式。以下_Meta
CUE 模式定义了所有基于文件的目录 Blob 必须遵守的格式。
_Meta
模式_Meta: {
// schema is required and must be a non-empty string
schema: string & !=""
// package is optional, but if it's defined, it must be a non-empty string
package?: string & !=""
// properties is optional, but if it's defined, it must be a list of 0 or more properties
properties?: [... #Property]
}
#Property: {
// type is required
type: string & !=""
// value is required, and it must not be null
value: !=null
}
本规范中列出的 CUE 模式不应被认为是详尽无遗的。 |
运营商生命周期管理器 (OLM) 目录当前使用三种模式 (olm.package
、olm.channel
和 olm.bundle
),它们对应于 OLM 现有的包和捆绑包概念。
目录中的每个运营商包都需要恰好一个 olm.package
Blob,至少一个 olm.channel
Blob 和一个或多个 olm.bundle
Blob。
所有 |
olm.package
模式定义运营商的包级元数据。这包括其名称、描述、默认通道和图标。
olm.package
模式#Package: {
schema: "olm.package"
// Package name
name: string & !=""
// A description of the package
description?: string
// The package's default channel
defaultChannel: string & !=""
// An optional icon
icon?: {
base64data: string
mediatype: string
}
}
olm.channel
模式定义包中的通道、作为通道成员的捆绑包条目以及这些捆绑包的升级边缘。
如果捆绑包条目在多个 olm.channel
Blob 中表示边缘,则它每个通道只能出现一次。
条目的 replaces
值引用在此目录或其他目录中找不到的另一个捆绑包名称是有效的。但是,所有其他通道不变式必须成立,例如通道不能有多个头部。
olm.channel
模式#Channel: {
schema: "olm.channel"
package: string & !=""
name: string & !=""
entries: [...#ChannelEntry]
}
#ChannelEntry: {
// name is required. It is the name of an `olm.bundle` that
// is present in the channel.
name: string & !=""
// replaces is optional. It is the name of bundle that is replaced
// by this entry. It does not have to be present in the entry list.
replaces?: string & !=""
// skips is optional. It is a list of bundle names that are skipped by
// this entry. The skipped bundles do not have to be present in the
// entry list.
skips?: [...string & !=""]
// skipRange is optional. It is the semver range of bundle versions
// that are skipped by this entry.
skipRange?: string & !=""
}
使用 您可以通过同时使用 |
olm.bundle
模式#Bundle: {
schema: "olm.bundle"
package: string & !=""
name: string & !=""
image: string & !=""
properties: [...#Property]
relatedImages?: [...#RelatedImage]
}
#Property: {
// type is required
type: string & !=""
// value is required, and it must not be null
value: !=null
}
#RelatedImage: {
// image is the image reference
image: string & !=""
// name is an optional descriptive name for an image that
// helps identify its purpose in the context of the bundle
name?: string & !=""
}
可选的 olm.deprecations
模式定义目录中包、捆绑包和通道的弃用信息。运营商作者可以使用此模式向从目录运行这些运营商的用户提供有关其运营商的相关消息,例如支持状态和推荐的升级路径。
定义此模式后,AWS 上的 Red Hat OpenShift 服务 Web 控制台将在运营商的预安装和后安装页面上显示受影响的运营商元素的警告徽章,包括任何自定义弃用消息。
olm.deprecations
模式条目包含以下一个或多个 reference
类型,指示弃用范围。安装运营商后,任何指定的邮件都可以在相关的 Subscription
对象上显示为状态条件。
类型 | 范围 | 状态条件 |
---|---|---|
|
表示整个包 |
|
|
表示一个通道 |
|
|
表示一个捆绑包版本 |
|
每个 reference
类型都有其自身的要求,详情请参见以下示例。
reference
类型的示例 olm.deprecations
模式schema: olm.deprecations
package: my-operator (1)
entries:
- reference:
schema: olm.package (2)
message: | (3)
The 'my-operator' package is end of life. Please use the
'my-operator-new' package for support.
- reference:
schema: olm.channel
name: alpha (4)
message: |
The 'alpha' channel is no longer supported. Please switch to the
'stable' channel.
- reference:
schema: olm.bundle
name: my-operator.v1.68.0 (5)
message: |
my-operator.v1.68.0 is deprecated. Uninstall my-operator.v1.68.0 and
install my-operator.v1.72.0 for support.
1 | 每个弃用模式都必须具有 package 值,并且该包引用在整个目录中必须唯一。不能有相关的 name 字段。 |
2 | olm.package 模式不得包含 name 字段,因为它由模式前面定义的 package 字段确定。 |
3 | 任何 reference 类型的 message 字段都必须是非零长度的,并表示为不透明文本 Blob。 |
4 | olm.channel 模式的 name 字段是必需的。 |
5 | olm.bundle 模式的 name 字段是必需的。 |
弃用功能不考虑重叠的弃用,例如包与通道与捆绑包。 |
运营商作者可以将 olm.deprecations
模式条目保存为包的 index.yaml
文件所在目录中的 deprecations.yaml
文件。
my-catalog
└── my-operator
├── index.yaml
└── deprecations.yaml
属性是可以附加到基于文件的目录模式的任意元数据片段。type
字段是一个字符串,有效地指定了 value
字段的语义和语法含义。该值可以是任何任意 JSON 或 YAML。
OLM 定义了一些属性类型,同样使用保留的 olm.*
前缀。
olm.package
属性定义包名称和版本。这是捆绑包上的必需属性,并且必须只有一个此类属性。packageName
字段必须与捆绑包的第一类 package
字段匹配,version
字段必须是有效的语义版本。
olm.package
属性#PropertyPackage: {
type: "olm.package"
value: {
packageName: string & !=""
version: string & !=""
}
}
olm.gvk
属性定义此捆绑包提供的 Kubernetes API 的组/版本/种类 (GVK)。OLM 使用此属性来解析具有此属性的捆绑包,作为将相同 GVK 列为所需 API 的其他捆绑包的依赖项。GVK 必须遵守 Kubernetes GVK 验证。
olm.gvk
属性#PropertyGVK: {
type: "olm.gvk"
value: {
group: string & !=""
version: string & !=""
kind: string & !=""
}
}
使用基于文件的目录,目录维护者可以专注于运营商管理和兼容性。由于运营商作者已经为其运营商生成了运营商特定的目录,因此目录维护者可以通过将每个运营商目录呈现到目录根目录的子目录来构建其目录。
构建基于文件的目录有很多方法;以下步骤概述了一种简单的方法。
为目录维护单个配置文件,其中包含目录中每个运营商的镜像引用。
name: community-operators
repo: quay.io/community-operators/catalog
tag: latest
references:
- name: etcd-operator
image: quay.io/etcd-operator/index@sha256:5891b5b522d5df086d0ff0b110fbd9d21bb4fc7163af34d08286a2e846f6be03
- name: prometheus-operator
image: quay.io/prometheus-operator/index@sha256:e258d248fda94c63753607f7c4494ee0fcbe92f1a76bfdac795c9d84101eb317
运行一个解析配置文件并根据其引用创建新目录的脚本。
name=$(yq eval '.name' catalog.yaml)
mkdir "$name"
yq eval '.name + "/" + .references[].name' catalog.yaml | xargs mkdir
for l in $(yq e '.name as $catalog | .references[] | .image + "|" + $catalog + "/" + .name + "/index.yaml"' catalog.yaml); do
image=$(echo $l | cut -d'|' -f1)
file=$(echo $l | cut -d'|' -f2)
opm render "$image" > "$file"
done
opm generate dockerfile "$name"
indexImage=$(yq eval '.repo + ":" + .tag' catalog.yaml)
docker build -t "$indexImage" -f "$name.Dockerfile" .
docker push "$indexImage"
维护基于文件的目录时,请考虑以下指南。
运营商生命周期管理器 (OLM) 的一般建议是,捆绑包镜像及其元数据应视为不变的。
如果已将损坏的 Bundle 推送到目录中,则必须假设至少有一名用户已升级到该 Bundle。基于此假设,必须发布另一个 Bundle,其中包含从损坏的 Bundle 到新 Bundle 的升级路径,以确保安装了损坏 Bundle 的用户能够收到升级。如果目录中 Bundle 的内容已更新,OLM 不会重新安装已安装的 Bundle。
但是,在某些情况下,更改目录元数据更可取。
渠道推广:如果您已经发布了一个 Bundle,后来决定将其添加到另一个渠道,则可以在另一个olm.channel
Blob 中添加您的 Bundle 条目。
新的升级路径:例如,如果您发布了新的1.2.z
Bundle 版本,例如1.2.4
,但1.3.0
已经发布,则可以更新1.3.0
的目录元数据以跳过1.2.4
。