metadata.name
集群服务版本 (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 项目的测试工具)已弃用,并计划在未来的 OpenShift Dedicated 版本中删除。Red Hat 将在此版本的生命周期内为此功能提供错误修复和支持,但此功能将不再接收增强功能,并将从未来的 OpenShift Dedicated 版本中删除。 不推荐使用 Red Hat 支持的 Operator SDK 版本创建新的 Operator 项目。拥有现有 Operator 项目的 Operator 作者可以使用 OpenShift Dedicated 发布的 Operator SDK CLI 工具版本来维护他们的项目并创建针对较新版本的 OpenShift Dedicated 的 Operator 版本。 以下与 Operator 项目相关的基础镜像未被弃用。这些基础镜像的运行时功能和配置 API 仍受支持,用于错误修复和解决 CVE。
有关不受支持的社区维护的 Operator SDK 版本的信息,请参见Operator SDK (Operator Framework)。 |
CSV 生成命令消除了 Operator 作者需要深入了解 OLM 才能使其 Operator 与 OLM 交互或将元数据发布到 Catalog Registry 的责任。此外,由于随着新的 Kubernetes 和 OLM 功能的实现,CSV 规范可能会随着时间的推移而发生变化,因此 Operator SDK 能够轻松扩展其更新系统以处理未来的新 CSV 功能。
操作符捆绑清单,包括集群服务版本 (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
命令,它自动化了多个任务,包括按顺序运行以下子命令:
generate kustomize manifests
generate bundle
bundle validate
请参阅捆绑 Operator,了解包含生成捆绑包和 CSV 的完整流程。
make bundle
命令会在您的 Operator 项目中创建以下文件和目录:
一个名为bundle/manifests
的捆绑清单目录,其中包含一个ClusterServiceVersion
(CSV) 对象。
一个名为bundle/metadata
的捆绑元数据目录。
config/crd
目录中的所有自定义资源定义 (CRD)。
一个 Dockerfile bundle.Dockerfile
。
CSV 中通常包含以下资源:
定义 Operator 在命名空间内的权限。
定义集群范围的 Operator 权限。
定义如何在 Pod 中运行 Operator 的操作对象。
定义您的 Operator 调和的自定义资源。
符合特定 CRD 规范的资源示例。
许多 CSV 字段无法使用非 Operator SDK 特定的生成的通用清单来填充。这些字段大多是关于 Operator 和各种自定义资源定义 (CRD) 的人工编写的元数据。
Operator 作者必须直接修改其集群服务版本 (CSV) YAML 文件,向以下必需字段添加个性化数据。当检测到任何必需字段中缺少数据时,Operator SDK 会在 CSV 生成期间发出警告。
下表详细说明了哪些 CSV 字段是必需的,哪些是可选的。
字段 | 描述 |
---|---|
|
此 CSV 的唯一名称。应在名称中包含 Operator 版本以确保唯一性,例如 |
|
根据 Operator 成熟度模型的能力级别。选项包括 |
|
用于标识 Operator 的公共名称。 |
|
对 Operator 功能的简短描述。 |
|
描述 Operator 的关键字。 |
|
维护 Operator 的个人或组织实体,包含 |
|
Operator 的提供者(通常是组织),包含 |
|
Operator 内部使用的键值对。 |
|
Operator 的语义版本,例如 |
|
Operator 使用的任何 CRD。如果
|
字段 | 描述 |
---|---|
|
此 CSV 替换的 CSV 名称。 |
|
与 Operator 或正在管理的应用程序相关的 URL(例如,网站和文档),每个 URL 都包含 |
|
Operator 可以用来配对集群中资源的选择器。 |
|
Operator 独有的 base64 编码图标,设置在 |
|
此版本软件已达到的成熟度级别。选项包括 |
有关上述每个字段应包含哪些数据的更多详细信息,请参阅CSV 规范。
目前需要用户干预的几个 YAML 字段可以从 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 Dedicated 4.10 及更高版本中受支持。
|
注解 | 描述 | 有效值[1] |
---|---|---|
|
指定 Operator 是否支持被镜像到断开的目录中,包括所有依赖项,并且不需要互联网访问。Operator 利用 |
|
|
指定操作符是否接受底层平台的 FIPS-140 配置并在引导到 FIPS 模式的节点上运行。在此模式下,操作符及其管理的任何工作负载(操作数)仅调用已提交 FIPS-140 验证的 Red Hat Enterprise Linux (RHEL) 加密库。 |
|
|
指定操作符是否支持在代理后面的集群上运行,方法是接受标准的 |
|
|
指定操作符是否实现众所周知的可调参数来修改操作符及其管理的任何工作负载(操作数)使用的 TLS 密码套件。 |
|
|
指定操作符是否支持通过使用云凭证操作符 (CCO) 使用 AWS 安全令牌服务 (STS) 对 AWS API 进行令牌化身份验证的配置。 |
|
|
指定操作符是否支持通过使用云凭证操作符 (CCO) 使用 Azure 托管标识对 Azure API 进行令牌化身份验证的配置。 |
|
|
指定操作符是否支持通过使用云凭证操作符 (CCO) 使用 GCP 工作负载身份基础架构 (WIF) 对 Google Cloud API 进行令牌化身份验证的配置。 |
|
|
指定操作符是否提供云原生网络功能 (CNF) Kubernetes 插件。 |
|
|
指定操作符是否提供容器网络接口 (CNI) Kubernetes 插件。 |
|
|
指定操作符是否提供容器存储接口 (CSI) Kubernetes 插件。 |
|
有效值故意用双引号显示,因为 Kubernetes 注解必须是字符串。
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 Dedicated 4.14 开始,operators.openshift.io/infrastructure-features
组的注解已被 features.operators.openshift.io
命名空间的注解组弃用。虽然我们鼓励您使用较新的注解,但目前同时使用这两组注解都是可以接受的。
这些注解详细说明了操作符支持的基础设施特性。用户可以通过 Web 控制台或 Red Hat 生态系统目录 中的 OperatorHub 查看和筛选这些特性来发现操作符。
有效的注解值 | 描述 | ||
---|---|---|---|
|
操作符支持镜像到脱机目录中,包括所有依赖项,并且不需要互联网访问。操作符列出了镜像所需的所有相关镜像。 |
||
|
操作符提供云原生网络功能 (CNF) Kubernetes 插件。 |
||
|
操作符提供容器网络接口 (CNI) Kubernetes 插件。 |
||
|
操作符提供容器存储接口 (CSI) Kubernetes 插件。 |
||
|
操作符接受底层平台的 FIPS 模式并在引导到 FIPS 模式的节点上运行。
|
||
|
操作符支持在代理后面的集群上运行。操作符接受标准的代理环境变量 |
disconnected
和 proxy-aware
支持的示例 CSVapiVersion: operators.coreos.com/v1alpha1
kind: ClusterServiceVersion
metadata:
annotations:
operators.openshift.io/infrastructure-features: '["disconnected", "proxy-aware"]'
以下操作符注解是可选的。
注解 | 描述 |
---|---|
|
提供具有最小配置集的自定义资源定义 (CRD) 模板。兼容的 UI 为用户预填充此模板以进一步自定义。 |
|
通过在操作符安装期间将 |
|
设置建议的操作符部署命名空间。 |
|
为 |
|
用于列出使用操作符所需的任何特定订阅的自由格式数组。例如, |
|
隐藏 UI 中并非用于用户操作的 CRD。 |
apiVersion: operators.coreos.com/v1alpha1
kind: ClusterServiceVersion
metadata:
annotations:
operators.openshift.io/valid-subscription: '["OpenShift Container Platform"]'
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 的项目的示例。
为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 。 |
在您的 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 函数调用<相关镜像环境变量> 。 |
如果未设置变量,则 |
对于基于 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 字段。 |
将overrideValues
字段的值添加到helm-charts/memchached/values.yaml
文件中,如下例所示。
helm-charts/memchached/values.yaml
文件示例...
relatedImage: ""
修改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 | 定义环境变量的值。 |
将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 | 将上面的行替换为此行。 |
要更新您的 Operator 镜像以使用摘要 (SHA) 而不是标签,请运行make bundle
命令并将USE_IMAGE_DIGESTS
设置为true
。
$ make bundle USE_IMAGE_DIGESTS=true
添加disconnected
注释,这表示 Operator 在断开连接的环境中工作。
metadata:
annotations:
operators.openshift.io/infrastructure-features: '["disconnected"]'
OperatorHub 可以通过此基础架构功能过滤 Operator。
Operator Lifecycle Manager (OLM) 假设所有 Operator 都运行在 Linux 主机上。但是,作为 Operator 作者,您可以指定您的 Operator 是否支持在其他架构上管理工作负载,如果在 OpenShift Dedicated 集群中提供了工作节点。
如果您的 Operator 支持除 AMD64 和 Linux 之外的其他变体,您可以向提供 Operator 的集群服务版本 (CSV) 添加标签,以列出支持的变体。指示支持的架构和操作系统的标签由以下内容定义:
labels:
operatorframework.io/arch.<arch>: supported (1)
operatorframework.io/os.<os>: supported (2)
1 | 将<arch> 设置为支持的字符串。 |
2 | 将<os> 设置为支持的字符串。 |
只有默认通道的通道头上的标签才被考虑用于按标签过滤包清单。这意味着,例如,可以在非默认通道中为 Operator 提供其他架构,但是该架构不可用于在 |
如果 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 变体。 |
有关清单列表的更多信息,请参阅镜像清单 V 2,模式 2规范。
在 OpenShift Dedicated 上的 Operator Lifecycle Manager (OLM) 中,当标记或过滤支持多种架构和操作系统的 Operator 时,支持以下字符串。
架构 | 字符串 |
---|---|
AMD64 |
|
ARM64 |
|
IBM Power® |
|
IBM Z® |
|
操作系统 | 字符串 |
---|---|
Linux |
|
z/OS |
|
不同版本的 OpenShift Dedicated 和其他基于 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 默认节点选择器的示例 `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 Lifecycle Manager (OLM) 为 Operators 提供了一个渠道,用于沟通影响 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 中 `Get` 和 `Set` `conditionType`:
获取
为了获取特定条件,该库使用 `controller-runtime` 中的 `client.Get` 函数,这需要 `conditionAccessor` 中存在的 `types.NamespacedName` 类型的 `ObjectKey`。
设置
为了更新特定条件的状态,该库使用 `controller-runtime` 中的 `client.Update` 函数。如果 CRD 中不存在 `conditionType`,则会发生错误。
Operator 只允许修改 CR 的 `status` 子资源。Operators 可以删除或更新 `status.conditions` 数组以包含该条件。有关条件中字段的格式和描述的更多详细信息,请参阅上游 Condition GoDocs。
Operator SDK 1.36.1 支持 `operator-lib` v0.11.0。 |
使用 Operator SDK 生成的 Operator 项目。
要在您的 Operator 项目中启用 Operator 条件:
在您的 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
)
在您的 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` 构造函数被进一步用于创建一个 `cond` 变量,其类型为 `Condition`。`cond` 变量将反过来具有 `Get` 和 `Set` 方法,这些方法可用于处理 OLM `Upgradeable` 条件。
Webhook 允许 Operator 作者在资源保存到对象存储并由 Operator 控制器处理之前拦截、修改和接受或拒绝资源。Operator Lifecycle Manager (OLM) 在将这些 Webhook 与您的 Operator 一起交付时,可以管理这些 Webhook 的生命周期。
Operator 的集群服务版本 (CSV) 资源可以包含一个 `webhookdefinitions` 部分来定义以下类型的 Webhook:
准入 Webhook(验证和变异)
转换 Webhook
向 Operator 的 CSV 的 `spec` 部分添加一个 `webhookdefinitions` 部分,并使用 `ValidatingAdmissionWebhook`、`MutatingAdmissionWebhook` 或 `ConversionWebhook` 的 `type` 包含任何 Webhook 定义。以下示例包含所有三种类型的 Webhook:
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` 属性必须设置为 `false` 或 `nil`。 |
Kubernetes 文档
使用 Operator Lifecycle Manager (OLM) 部署带有 Webhook 的 Operator 时,必须定义以下内容:
`type` 字段必须设置为 `ValidatingAdmissionWebhook`、`MutatingAdmissionWebhook` 或 `ConversionWebhook`,否则 CSV 将处于失败阶段。
CSV 必须包含一个名称等效于 `webhookdefinition` 的 `deploymentName` 字段中提供的值的部署。
创建 Webhook 时,OLM 确保 Webhook 只对与部署 Operator 的 Operator 组匹配的 namespace 起作用。
OLM 配置为为每个部署提供单个证书颁发机构 (CA)。生成并将 CA 装入部署的逻辑最初由 API 服务生命周期逻辑使用。因此:
TLS 证书文件安装到部署的 `/apiserver.local.config/certificates/apiserver.crt` 位置。
TLS 密钥文件安装到部署的 `/apiserver.local.config/certificates/apiserver.key` 位置。
为了防止 Operator 将集群配置为不可恢复的状态,如果准入 Webhook 中定义的规则拦截任何以下请求,OLM 将 CSV 置于失败阶段:
目标为所有组的请求
目标为 `operators.coreos.com` 组的请求
目标为 `ValidatingWebhookConfigurations` 或 `MutatingWebhookConfigurations` 资源的请求
如果转换 Webhook 定义不符合以下约束,OLM 将 CSV 置于失败阶段:
具有转换 Webhook 的 CSV 只能支持 `AllNamespaces` 安装模式。
转换 Webhook 针对的 CRD 必须将其 `spec.preserveUnknownFields` 字段设置为 `false` 或 `nil`。
CSV 中定义的转换 Webhook 必须针对拥有的 CRD。
对于给定的 CRD,整个集群中只能有一个转换 Webhook。
您的 Operator 可以使用两种类型的自定义资源定义 (CRD):它拥有的 CRD 和它依赖的、必需的 CRD。
您的 Operator 拥有的自定义资源定义 (CRD) 是 CSV 中最重要的部分。这建立了您的 Operator 与所需的 RBAC 规则、依赖项管理和其他 Kubernetes 概念之间的链接。
您的 Operator 通常使用多个 CRD 来链接概念,例如在一个对象中进行顶级数据库配置,而在另一个对象中表示副本集。每个 CRD 都应在 CSV 文件中列出。
字段 | 描述 | 必需/可选 |
---|---|---|
|
您的 CRD 的完整名称。 |
必需 |
|
该对象 API 的版本。 |
必需 |
|
您的 CRD 的机器可读名称。 |
必需 |
|
您的 CRD 名称的可读版本,例如 |
必需 |
|
简要描述此 CRD 如何被 Operator 使用,或描述 CRD 提供的功能。 |
必需 |
|
此 CRD 所属的 API 组,例如 |
可选 |
|
您的 CRD 拥有一个或多个类型的 Kubernetes 对象。这些列在 建议仅列出对人类重要的对象,而不是您编排的所有内容的详尽列表。例如,不要列出存储内部状态且不应由用户修改的配置映射。 |
可选 |
|
这些描述符是一种方法,可以通过提示 UI 显示 Operator 对最终用户最重要的某些输入或输出。如果您的 CRD 包含用户必须提供的密钥或配置映射的名称,则可以在此处指定。这些项目在兼容的 UI 中被链接和突出显示。 有三种类型的描述符
所有描述符都接受以下字段
有关 |
可选 |
以下示例描述了一个MongoDB Standalone
CRD,它需要以密钥和配置映射的形式提供一些用户输入,并编排服务、状态集、Pod 和配置映射。
- 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 完全是可选的,它仅仅是为了减少单个 Operator 的范围,并提供一种方法来组合多个 Operator 以解决端到端的用例。
一个示例是:一个 Operator 可以设置一个应用程序并安装一个 etcd 集群(来自 etcd Operator)用于分布式锁定,以及一个 Postgres 数据库(来自 Postgres Operator)用于数据存储。
Operator 生命周期管理器 (OLM) 会检查集群中可用的 CRD 和 Operator 以满足这些要求。如果找到合适的版本,则会在所需的命名空间中启动 Operator,并为每个 Operator 创建一个服务帐户,以创建、监视和修改所需的 Kubernetes 资源。
字段 | 描述 | 必需/可选 |
---|---|---|
|
您所需的 CRD 的完整名称。 |
必需 |
|
该对象 API 的版本。 |
必需 |
|
Kubernetes 对象种类。 |
必需 |
|
CRD 的可读版本。 |
必需 |
|
组件如何融入您更大架构的摘要。 |
必需 |
required:
- name: etcdclusters.etcd.database.coreos.com
version: v1beta2
kind: EtcdCluster
displayName: etcd Cluster
description: Represents a cluster of etcd nodes.
如果单个集群服务版本 (CSV) 拥有自定义资源定义 (CRD),则 OLM 会立即升级该 CRD。如果多个 CSV 拥有 CRD,则只有在满足以下所有向后兼容条件后,才会升级 CRD
当前 CRD 中的所有现有服务版本都存在于新 CRD 中。
与 CRD 的服务版本关联的所有现有实例或自定义资源在针对新 CRD 的验证模式进行验证时都是有效的。
要向您的 Operator 添加新版本的 CRD
在 CSV 的versions
部分下,在 CRD 资源中添加一个新条目。
例如,如果当前 CRD 的版本为v1alpha1
,并且您想添加一个新版本v1beta1
并将其标记为新的存储版本,请为v1beta1
添加一个新条目。
versions:
- name: v1alpha1
served: true
storage: false
- name: v1beta1 (1)
served: true
storage: true
1 | 新条目。 |
如果 CSV 想要使用新版本,请确保更新 CSV 的owned
部分中 CRD 的引用版本。
customresourcedefinitions:
owned:
- name: cluster.example.com
version: v1beta1 (1)
kind: cluster
displayName: Cluster
1 | 更新version 。 |
将更新的 CRD 和 CSV 推送到您的包中。
Operator 生命周期管理器 (OLM) 不允许立即删除自定义资源定义 (CRD) 的服务版本。相反,必须首先通过将 CRD 中的served
字段设置为false
来禁用 CRD 的已弃用版本。然后,可以在后续 CRD 升级中删除非服务版本。
要弃用和删除 CRD 的特定版本
将已弃用的版本标记为非服务版本,以指示此版本不再使用,并且可能在后续升级中被删除。例如
versions:
- name: v1alpha1
served: false (1)
storage: true
1 | 设置为false 。 |
如果要弃用的版本当前是storage
版本,则将storage
版本切换到服务版本。例如
versions:
- name: v1alpha1
served: false
storage: false (1)
- name: v1beta1
served: true
storage: true (1)
1 | 相应地更新storage 字段。 |
要从 CRD 中删除作为或曾经是 |
使用上述更改升级 CRD。
在后续升级周期中,可以从 CRD 中完全删除非服务版本。例如
versions:
- name: v1beta1
served: true
storage: true
如果该版本从 CRD 中删除,请确保相应地更新 CSV 的owned
部分中引用的 CRD 版本。
必须让您的 Operator 用户了解哪些选项是必需的,哪些是可选的。您可以为每个自定义资源定义 (CRD) 提供模板,其中包含最小的一组配置,作为名为alm-examples
的注释。兼容的 UI 将预先填充此模板,供用户进一步自定义。
注释包含种类列表,例如 CRD 名称以及 Kubernetes 对象的相应metadata
和spec
。
以下完整示例为EtcdCluster
、EtcdBackup
和EtcdRestore
提供了模板。
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,每当用户创建具有replication: true
的数据库对象时都会创建该 CRD。
作为运营商作者,您可以通过向运营商的集群服务版本 (CSV) 添加operators.operatorframework.io/internal-objects
批注,隐藏用户界面中不适合用户操作的任何 CRD。
在将某个 CRD 标记为内部对象之前,请确保任何调试信息或可能需要管理应用程序的配置都反映在 CR 的状态或spec
块中(如果适用于您的运营商)。
将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 设置为字符串数组。 |
运营商可能需要用户在运营商完全发挥功能之前实例化自定义资源。但是,用户很难确定需要什么或如何定义资源。
作为运营商开发者,您可以通过在运营商安装期间向集群服务版本 (CSV) 添加operatorframework.io/initialization-resource
来指定单个所需的自定义资源。然后,系统会提示您通过 CSV 中提供的模板创建自定义资源。此批注必须包含一个模板,其中包含在安装期间初始化资源所需的完整 YAML 定义。
如果定义了此批注,则在从 OpenShift Dedicated 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": {}
}
]
}
}
...
与 CRD 一样,您的运营商可以使用两种类型的 API 服务:已拥有和所需。
当 CSV 拥有 API 服务时,它负责描述支持它的扩展api-server
的部署以及它提供的组/版本/种类 (GVK)。
API 服务由它提供的组/版本唯一标识,并且可以列出多次以表示它预期提供的不同种类。
字段 | 描述 | 必需/可选 |
---|---|---|
|
API 服务提供的组,例如 |
必需 |
|
API 服务的版本,例如 |
必需 |
|
API 服务预期提供的种类。 |
必需 |
|
提供的 API 服务的复数名称。 |
必需 |
|
CSV 定义的与 API 服务相对应的部署的名称(对于已拥有的 API 服务是必需的)。在 CSV 等待阶段,OLM 运营商会在您的 CSV 的 |
必需 |
|
API 服务名称的可读版本,例如 |
必需 |
|
运营商如何使用此 API 服务的简短说明,或 API 服务提供的功能的说明。 |
必需 |
|
您的 API 服务拥有 Kubernetes 对象的一种或多种类型。这些列在资源部分中,以告知您的用户他们可能需要排除故障的对象或如何连接到应用程序,例如公开数据库的服务或入口规则。 建议仅列出对人类重要的对象,而不是您编排的所有内容的详尽列表。例如,不要列出存储内部状态且不应由用户修改的配置映射。 |
可选 |
|
与已拥有的 CRD 基本相同。 |
可选 |
运营商生命周期管理器 (OLM) 负责为每个唯一的已拥有 API 服务创建或替换服务和 API 服务资源。
服务 Pod 选择器从与 API 服务说明的DeploymentName
字段匹配的 CSV 部署中复制。
为每次安装生成一个新的 CA 密钥/证书对,并将 base64 编码的 CA 捆绑包嵌入相应的 API 服务资源中。
每当安装已拥有的 API 服务时,OLM 都会处理生成服务密钥/证书对。服务证书具有一个公共名称 (CN),其中包含生成的Service
资源的主机名,并由嵌入相应 API 服务资源中的 CA 捆绑包的私钥签名。
证书存储为部署命名空间中的类型kubernetes.io/tls
密钥,并且名称为apiservice-cert
的卷会自动附加到 CSV 中与 API 服务说明的DeploymentName
字段匹配的部署的卷部分。
如果不存在,则还会将具有匹配名称的卷挂载附加到该部署的所有容器。这允许用户定义具有预期名称的卷挂载以适应任何自定义路径要求。生成的卷挂载的路径默认为/apiserver.local.config/certificates
,并且任何具有相同路径的现有卷挂载都将被替换。
OLM 确保所有必需的 CSV 都具有可用的 API 服务,并且在尝试安装之前所有预期的 GVK 都可以发现。这允许 CSV 依赖于它不拥有的 API 服务提供的特定种类。
字段 | 描述 | 必需/可选 |
---|---|---|
|
API 服务提供的组,例如 |
必需 |
|
API 服务的版本,例如 |
必需 |
|
API 服务预期提供的种类。 |
必需 |
|
API 服务名称的可读版本,例如 |
必需 |
|
运营商如何使用此 API 服务的简短说明,或 API 服务提供的功能的说明。 |
必需 |