Operator

OpenShift Container Platform 4.5

在 OpenShift Container Platform 中使用 Operator

Red Hat OpenShift Documentation Team

摘要

本文档提供有关在 OpenShift Container Platform 中使用 Operator 的信息。文中为集群管理员提供了 Operator 的安装和管理说明,为开发人员提供了如何通过所安装的 Operator 创建应用程序的信息。另外还提供了一些使用 Operator SDK 构建自用 Operator 的指南。

第 1 章 了解 Operator

1.1. 什么是 Operator?

从概念上讲,Operator 会收集人类操作知识,并将其编码成更容易分享给消费者的软件。

Operator 是一组软件,可用于降低运行其他软件的操作复杂程度。它可以被看作是软件厂商的工程团队的扩展,可以在 Kubernetes 环境中(如 OpenShift Container Platform)监控软件的运行情况,并根据软件的当前状态实时做出决策。Advanced Operator 被设计为用来无缝地处理升级过程,并对出现的错误自动进行响应,而且不会采取“捷径”(如跳过软件备份过程来节省时间)。

从技术上讲,Operator 是一种打包、部署和管理 Kubernetes 应用程序的方法。

Kubernetes 应用程序是一款 app,可在 Kubernetes 上部署,也可使用 Kubernetes API 和 kubectloc 工具进行管理。要想充分利用 Kubernetes,您需要一组统一的 API 进行扩展,以便服务和管理 Kubernetes 上运行的应用程序。可将 Operator 看成管理 Kubernetes 中这类应用程序的运行时。

1.1.1. 为什么要使用 Operator?

Operator 可以:

  • 重复安装和升级。
  • 持续对每个系统组件执行运行状况检查。
  • 无线 (OTA) 更新 OpenShift 组件和 ISV 内容。
  • 汇总现场工程师了解的情况并将其传输给所有用户,而非一两个用户。
为什么在 Kubernetes 上部署?
Kubernetes(扩展至 OpenShift Container Platform)包含构建复杂分布式系统(可在本地和云提供商之间工作)需要的所有原语,包括 secret 处理、负载均衡、服务发现、自动扩展。
为什么使用 Kubernetes API 和 kubectl 工具来管理您的应用程序?
这些 API 功能丰富,所有平台均有对应的客户端,并可插入到集群的访问控制/审核中。Operator 会使用 Kubernetes 的扩展机制“自定义资源定义 (CRD)”支持您的自定义对象,MongoDB,它类似于内置的原生 Kubernetes 对象。
Operator 与 Service Broker 的比较?
服务代理(service broker)是实现应用程序的编程发现和部署的一个步骤。但它并非一个长时间运行的进程,所以无法执行第 2 天操作,如升级、故障转移或扩展。它在安装时提供对可调参数的自定义和参数化,而 Operator 则可持续监控集群的当前状态。非集群服务仍非常适合于 Service Broker,但也存在合适于这些服务的 Operator。

1.1.2. Operator Framework

Operator Framework 是基于上述客户体验提供的一系列工具和功能。不仅仅是编写代码;测试、交付和更新 Operator 也同样重要。Operator Framework 组件包含用于解决这些问题的开源工具:

Operator SDK
Operator SDK 辅助 Operator 作者根据自身专业知识,引导、构建、测试和包装其 Operator,而无需了解 Kubernetes API 的复杂性。
Operator Lifecycle Manager
Operator Lifecycle Manager (OLM) 能够控制集群中 Operator 的安装、升级和基于角色的访问控制 (RBAC)。在 OpenShift Container Platform 4.5 中默认部署。
Operator Registry
Operator Registry 存储 ClusterServiceVersions (CSV) 和自定义资源定义 (CRD) 以便在集群中创建,并存储有关软件包和频道的 Operator 元数据。它运行在 Kubernetes 或 OpenShift 集群中,向 OLM 提供这些 Operator 目录数据。
OperatorHub
OperatorHub 是一个 web 控制台,供集群管理员用来发现并选择要在其集群上安装的 Operator。它在 OpenShift Container Platform 中默认部署。
Operator Metering
Operator Metering 收集集群上有关 Operator 的操作指标(用于第 2 天的管理)和聚集使用指标。

这些工具可组合使用,因此您可自由选择对您有用的工具。

1.1.3. Operator 成熟度模型

Operator 内部封装的管理逻辑的复杂程度各有不同。该逻辑通常还高度依赖于 Operator 所代表的服务类型。

对于大部分 Operator 可能包含的特定功能集来说,可以大致推断出 Operator 封装操作的成熟度等级。就此而言,以下 Operator 成熟度模型针对 Operator 的第 2 天通用操作定义了五个成熟度阶段。

图 1.1. Operator 成熟度模型

Operator 成熟度模型

以上模型还显示了如何通过 Operator SDK 的 Helm、Go 和 Ansible 功能更好地开发这些功能。

1.2. Operator Framework 常用术语表

本主题提供了与 Operator Framework 相关的常用术语表,其中包括 Operator Lifecycle Manager (OLM) 和 Operator SDK,适用于两种打包格式: Package Manifest Format 和 Bundle Format。

1.2.1. 常见 Operator Framework 术语

1.2.1.1. 捆绑包(Bundle)

在 Bundle Format 中,捆绑包是 Operator CSV、清单和元数据的集合。它们一起构成了可在集群中安装的 Operator 的唯一版本。

1.2.1.2. 捆绑包镜像

在 Bundle Format 中, 捆绑包镜像是一个从 Operator 清单中构建的容器镜像,其中包含一个捆绑包。捆绑包镜像由 Open Container Initiative (OCI) spec 容器 registry 存储和发布,如 Quay.io 或 DockerHub。

1.2.1.3. 目录源

目录源(catalog source) 是定义应用程序的 CSV、CRD 和软件包的仓库。

1.2.1.4. 目录镜像

在 Package Manifest Format 中, 目录镜像是一个容器化数据存储,用于描述一组可使用 OLM 在集群中安装的 Operator 元数据和更新元数据。

1.2.1.5. 频道

频道为 Operator 定义更新流,用于为订阅者推出更新。频道头指向该频道的最新版本。例如,stable 频道中会包含 Operator 的所有稳定版本,按由旧到新的顺序排列。

Operator 可以有几个频道,与特定频道绑定的订阅只会在该频道中查找更新。

1.2.1.6. 频道头

频道头是指特定频道中最新已知的更新。

1.2.1.7. 集群服务版本

集群服务版本(cluster service version,简称 CSV 是一个利用 Operator 元数据创建的 YAML 清单,可辅助 OLM 在集群中运行 Operator。它是 Operator 容器镜像附带的元数据,用于在用户界面填充徽标、描述和版本等信息。

此外,CSV 还是运行 Operator 所需的技术信息来源,类似于其需要的 RBAC 规则及其管理或依赖的自定义资源 (CR)。

1.2.1.8. 依赖项

Operator 可能会依赖于集群中存在的另一个 Operator。例如,Vault Operator 依赖于 etcd Operator 的数据持久性层。

OLM 通过确保在安装过程中在集群中安装 Operator 和 CRD 的所有指定版本来解决依赖关系。通过在目录中查找并安装满足所需 CRD API 且与软件包或捆绑包不相关的 Operator,解决这个依赖关系。

1.2.1.9. 索引镜像

在 Bundle Format 中, 索引镜像是一种数据库(数据库快照)镜像,其中包含关于 Operator 捆绑包(包括所有版本的 CSV 和 CRD)的信息。此索引可以托管集群中 Operator 的历史记录,并可使用 opm CLI 工具添加或删除 Operator 来加以维护。

1.2.1.10. 安装计划

安装计划(install plan)是一个列出了为自动安装或升级 CSV 而需创建的资源的计算列表。

1.2.1.11. operator 组

Operator 组将部署在同一命名空间中的所有 Operator 配置为 OperatorGroup 对象,以便在一系列命名空间或集群范围内监视其 CR。

1.2.1.12. 软件包

在 Bundle Format 中,软件包是一个目录,其中包含每个版本的 Operator 的发布历史记录。CSV 清单中描述了发布的 Operator 版本和 CRD。

1.2.1.13. 容器镜像仓库(Registry)

Registry 一个存储了 Operator 捆绑包镜像的数据库,每个都包含所有频道的最新和历史版本。

1.2.1.14. Subscription

订阅(subscription) 通过跟踪软件包中的频道来保持 CSV 最新。

1.2.1.15. 更新图表

更新图表将 CSV 的版本关联到一起,与其他打包软件的更新图表类似。可以依次安装 Operator,也可以跳过某些版本。只有在添加新版本时,更新图表才会在频道头上扩大。

1.3. Operator Framework 打包格式

本指南概述了 OpenShift Container Platform 中 Operator Lifecycle Manager (OLM) 所支持的 Operator 打包格式。

1.3.1. Package Manifest Format

Operator 的 Package Manifest Format 是 Operator Framework 中原先引入的旧版打包格式。虽然 OpenShift Container Platform 4.5 中已弃用此格式,但它仍受支持,红帽提供的 Operator 目前仍使用此方法提供。

在这个格式中,Operator 的版本由单个集群服务版本(CSV)代表,自定义资源定义(CRD)用来定义 CSV 所拥有的 API,另外也可能包含其他对象。

Operator 的所有版本都嵌套到单个目录中:

Package Manifest Format 布局示例

etcd
├── 0.6.1
│   ├── etcdcluster.crd.yaml
│   └── etcdoperator.clusterserviceversion.yaml
├── 0.9.0
│   ├── etcdbackup.crd.yaml
│   ├── etcdcluster.crd.yaml
│   ├── etcdoperator.v0.9.0.clusterserviceversion.yaml
│   └── etcdrestore.crd.yaml
├── 0.9.2
│   ├── etcdbackup.crd.yaml
│   ├── etcdcluster.crd.yaml
│   ├── etcdoperator.v0.9.2.clusterserviceversion.yaml
│   └── etcdrestore.crd.yaml
└── etcd.package.yaml

它还包含一个 <name>.package.yaml 文件,它是定义软件包名称和频道详情的软件包清单

软件包清单示例

packageName: etcd
channels:
- name: alpha
  currentCSV: etcdoperator.v0.9.2
- name: beta
  currentCSV: etcdoperator.v0.9.0
- name: stable
  currentCSV: etcdoperator.v0.9.2
defaultChannel: alpha

将软件包清单加载到 Operator Registry 数据库中时,会验证以下要求:

  • 每个软件包至少有一个频道。
  • 软件包中频道指向的每个 CSV 都存在。
  • Operator 的每个版本都只有一个 CSV。
  • 如果 CSV 拥有 CRD,则该 CRD 必须存在于 Operator 版本的目录中。
  • 如果 CSV 替换了另一个 CSV,则软件包中必须同时存在旧的和新的 CSV。

1.3.2. Bundle Format

Operator 的 Bundle Format 是 Operator Framework 引入的新打包格式。为提高可伸缩性并为自行托管目录的上游用户提供更好地支持,Bundle Format 规格简化了 Operator 元数据的发布。

Operator 捆绑包代表 Operator 的单一版本。磁盘上的捆绑包清单是容器化的,并作为捆绑包镜像提供,该镜像是一个不可运行的容器镜像,其中存储了 Kubernetes 清单和 Operator 元数据。然后,使用现有容器工具(如 podmandocker)和容器 registry(如 Quay)来管理捆绑包镜像的存储和发布。

Operator 元数据可以包括:

  • 标识 Operator 的信息,如名称和版本。
  • 驱动 UI 的额外信息,例如其图标和一些示例自定义资源 (CR)。
  • 所需的和所提供的 API。
  • 相关镜像。

将清单加载到 Operator Registry 数据库中时,会验证以下要求:

  • 该捆绑包必须在注解中至少定义一个频道。
  • 每个捆绑包都只有一个集群服务版本(CSV)。
  • 如果 CSV 拥有自定义资源定义(CRD),则该 CRD 必须存在于捆绑包中。

1.3.2.1. 清单

捆绑包清单指的是一组 Kubernetes 清单,用于定义 Operator 的部署和 RBAC 模型。

捆绑包包括每个目录的一个 CSV,一般情况下,用来定义 CRD 所拥有的 API 的 CRD 位于 /manifest 目录中。

Bundle Format 布局示例

etcd
├── manifests
│   ├── etcdcluster.crd.yaml
│   └── etcdoperator.clusterserviceversion.yaml
│   └── secret.yaml
│   └── configmap.yaml
└── metadata
    └── annotations.yaml
    └── dependencies.yaml

可选对象

以下对象类型也可以包括在捆绑包的 /manifests 目录中:

支持的可选对象

  • Secrets
  • ConfigMaps

当捆绑包中包含这些可选对象时,Operator Lifecycle Manager(OLM)可以从捆绑包创建对象,并随 CSV 一起管理其生命周期:

可选对象的生命周期

  • 删除 CSV 后,OLM 会删除可选对象。
  • 当 CSV 被升级时:

    • 如果可选对象的名称相同,OLM 会更新它。
    • 如果可选对象的名称在版本间有所变化,OLM 会删除并重新创建它。

1.3.2.2. 注解

捆绑包还在其 /metadata 文件夹中包含 annotations.yaml 文件。此文件定义了更高级别的聚合数据,以帮助描述有关如何将捆绑包添加到捆绑包索引中的格式和软件包信息:

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 捆绑包的介质类型或格式。registry+v1 格式表示它包含 CSV 及其关联的 Kubernetes 对象。
2
镜像中的该路径指向含有 Operator 清单的目录。该标签保留给以后使用,当前默认为 manifests/manifests.v1 值表示捆绑包包含 Operator 清单。
3
镜像中的该路径指向包含捆绑包元数据文件的目录。该标签保留给以后使用,当前默认为 metadata/metadata.v1 值表示这个捆绑包包含 Operator 元数据。
4
捆绑包的软件包名称。
5
捆绑包添加到 Operator Registry 时订阅的频道列表。
6
从 registry 安装时,Operator 应该订阅到的默认频道。
注意

如果出现不匹配的情况,则以 annotations.yaml 文件为准,因为依赖这些注解的集群 Operator Registry 只能访问此文件。

1.3.2.3. 依赖项

Operator 的相依项列在捆绑包的 metadata/ 文件夹的 dependencies.yaml 文件中。此文件是可选的,目前仅用于指明 Operator-version 依赖项。

依赖项列表中,每个项目包含一个 type 字段,用于指定这一依赖项的类型。受支持的 Operator 依赖项有两种:

  • olm.package:该软件包类型意味着这是特定 Operator 版本的依赖项。依赖项信息必须包含软件包名称以及软件包的版本,格式为 semver。例如,您可以指定具体版本,如 0.5.2,也可指定一系列版本,如 >0.5.1
  • olm.gvk:通过 GVK 类型,作者可以使用 GVK 信息指定依赖项,类似于 CSV 中现有的 CRD 和基于 API 的使用方法。该路径使 Operator 作者可以合并所有依赖项、API 或显式版本,使它们处于同一位置。

在以下示例中,为 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

1.3.2.4. opm CLI

新的 opm CLI 工具与新的 Bundle Format 一起引入。您可以通过一个名为 index 的捆绑包列表,创建和维护 Operator 目录,它相当于“存储库”。其结果是名为 index image 的容器镜像,它可以存储在容器 registry 中,然后安装到集群中。

索引包含一个指向 Operator 清单内容的指针数据库,可通过在运行容器镜像时提供的已包含 API 进行查询。在 OpenShift Container Platform 中,OLM 可通过引用 CatalogSource 中的索引镜像作为目录(catalog),它会定期轮询镜像,以对集群上安装的 Operator 进行更新。

1.4. Operator Lifecycle Manager (OLM)

1.4.1. Operator Lifecycle Manager 概念

本指南概述了 OpenShift Container Platform 中 Operator Lifecycle Manager (OLM) 背后的概念。

1.4.1.1. Operator Lifecycle Manager 是什么?

Operator Lifecycle Manager(OLM)可帮助用户安装、更新和管理所有 Kubernetes 原生应用程序(Operator)以及在 OpenShift Container Platform 集群中运行的关联服务的生命周期。它是 Operator Framework 的一部分,后者是一个开源工具包,用于以有效、自动化且可扩展的方式管理 Operator。

图 1.2. Operator Lifecycle Manager 工作流

OLM 工作流

OLM 默认在 OpenShift Container Platform 4.5 中运行,辅助集群管理员对集群上运行的 Operator 进行安装、升级和授予访问权。OpenShift Container Platform Web 控制台提供一些管理界面,供集群管理员安装 Operator,以及为特定项目授权以便使用集群上的可用 Operator 目录。

开发人员通过自助服务体验,无需成为相关问题的专家也可自由置备和配置数据库、监控和大数据服务的实例,因为 Operator 已将相关知识融入其中。

1.4.1.2. OLM 资源

以下自定义资源定义 (CRD) 由 Operator Lifecycle Manager (OLM) 定义和管理:

表 1.1. 由 OLM 和 Catalog Operator 管理的 CRD

资源短名称描述

ClusterServiceVersion (CSV)

csv

应用程序元数据。例如:名称、版本、图标、所需资源。

CatalogSource

catsrc

定义应用程序的 CSV、CRD 和软件包存储库。

Subscription

sub

通过跟踪软件包中的频道来保持 CSV 最新

InstallPlan

ip

为自动安装或升级 CSV 而需创建的资源的计算列表。

OperatorGroup

og

将部署在同一命名空间中的所有 Operator 配置为 OperatorGroup 对象,以便在一系列命名空间或集群范围内监视其自定义资源 ( CR)。

1.4.1.2.1. 集群服务版本

集群服务版本 (CSV) 代表 OpenShift Container Platform 集群中运行的 Operator 的特定版本。它是一个利用 Operator 元数据创建的 YAML 清单,可辅助 Operator Lifecycle Manager (OLM) 在集群中运行 Operator。

OLM 需要与 Operator 相关的元数据,以确保它可以在集群中安全运行,并在发布新版 Operator 时提供有关如何应用更新的信息。这和传统的操作系统的打包软件相似;可将 OLM 的打包步骤认为是制作 rpmdebapk 捆绑包的阶段。

CSV 中包含 Operator 容器镜像附带的元数据,用于在用户界面填充名称、版本、描述、标签、存储库链接和徽标等信息。

此外,CSV 还是运行 Operator 所需的技术信息来源,例如其管理或依赖的自定义资源 (CR)、RBAC 规则、集群要求和安装策略。此信息告诉 OLM 如何创建所需资源并将 Operator 设置为部署。

1.4.1.2.2. 目录源

目录源(catalog source)代表 OLM 可查询的元数据存储,以发现和安装 Operator 及其依赖项。CatalogSource 的 spec 指明了如何构造 pod,以及如何与服务于 Operator Registry gRPC API 的服务进行通信。

一个 CatalogSource 有三种主要的 sourceTypes

  • 带有镜像引用的 grpc:OLM 拉取镜像并运行 pod,为兼容的 API 服务。
  • 带有地址字段的 grpc:OLM 会尝试联系给定地址的 gRPC API。在大多数情况下不应该使用这种类型。
  • internalconfigmap:OLM 解析 ConfigMap 数据,并运行一个可以为其提供 gRPC API 的 pod。

以下示例定义了 OperatorHub.io 内容的目录源:

CatalogSource 对象示例

apiVersion: operators.coreos.com/v1alpha1
kind: CatalogSource
metadata:
 name: operatorhubio-catalog
 namespace: olm
spec:
 sourceType: grpc
 image: quay.io/operator-framework/upstream-community-operators:latest
 displayName: Community Operators
 publisher: OperatorHub.io

CatalogSource 对象的name 用作对订阅的输入,用于指示 OLM 在哪里查找所请求的 Operator:

引用目录源的 Subscription 对象示例

apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
 name: my-operator
 namespace: olm
spec:
 channel: stable
 name: my-operator
 source: operatorhubio-catalog

1.4.1.2.3. Subscription

订阅(由 Subscription 对象定义)代表了安装 Operator 的意向。它是将 Operator 与目录源关联的自定义资源。

Subscription 描述了要订阅 Operator 软件包的哪个频道,以及是自动还是手动执行更新。如果设置为自动,订阅可确保 Operator Lifecycle Manager(OLM)自动管理并升级 Operator,以确保集群中始终运行最新版本。

Subscription 对象示例

apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
  name: my-operator
  namespace: operators
spec:
  channel: stable
  name: my-operator
  source: my-catalog
  sourceNamespace: operators

Subscription 对象定义了 Operator 的名称和命名空间,以及从中查找 Operator 数据的目录。频道(如 alphabetastable )可帮助确定应从目录源安装哪些 Operator 流。

订阅中的频道名称可能会因 Operator 而异,但应遵守给定 Operator 中的常规约定。例如,频道名称可能会遵循 Operator 提供的应用程序的次发行版本更新流(1.21.3)或发行的频率(stablefast)。

除了可从 OpenShift Container Platform Web 控制台轻松查看外,还可以通过检查相关订阅的状态来识别是否有较新版本的 Operator 可用。与 currentCSV 字段关联的值是 OLM 已知的最新版本,而 installedCSV 是集群中安装的版本。

1.4.1.2.4. 安装计划

InstallPlan 对象定义的 安装计划(install plan) 描述了一组要创建的资源集合,用于安装或升级到由集群服务版本(CSV)定义的 Operator 的特定版本。

1.4.1.2.5. operator 组

OperatorGroup 资源定义的 Operator 组,为 OLM 安装的 Operator 提供多租户配置。Operator 组选择目标命名空间,在其中为其成员 Operator 生成所需的 RBAC 访问权限。

这一组目标命名空间通过存储在 CSV 的 olm.targetNamespaces 注解中的以逗号分隔的字符串来提供。该注解应用于成员 Operator 的 CSV 实例,并注入它们的部署中。

如需更多信息,请参阅 Operator 组指南。

1.4.2. Operator Lifecycle Manager 架构

本指南概述了 OpenShift Container Platform 中 Operator Lifecycle Manager (OLM) 的组件架构。

1.4.2.1. 组件职责

Operator Lifecycle Manager (OLM) 由两个 Operator 组成,分别为:OLM Operator 和 Catalog Operator。

每个 Operator 均负责管理 CRD,而 CRD 是 OLM 的框架基础:

表 1.2. 由 OLM 和 Catalog Operator 管理的 CRD

资源短名称所有者描述

ClusterServiceVersion (CSV)

csv

OLM

应用程序元数据:名称、版本、图标、所需资源、安装等。

InstallPlan

ip

Catalog

为自动安装或升级 CSV 而需创建的资源的计算列表。

CatalogSource

catsrc

Catalog

定义应用程序的 CSV、CRD 和软件包存储库。

Subscription

sub

Catalog

用于通过跟踪软件包中的频道来保持 CSV 最新。

OperatorGroup

og

OLM

将部署在同一命名空间中的所有 Operator 配置为 OperatorGroup 对象,以便在一系列命名空间或集群范围内监视其自定义资源 ( CR)。

每个 Operator 还负责创建以下资源:

表 1.3. 由 OLM 和 Catalog Operator 创建的资源

资源所有者

部署

OLM

ServiceAccounts

(Cluster)Roles

(Cluster)RoleBindings

CustomResourceDefinitions (CRD)

Catalog

ClusterServiceVersions

1.4.2.2. OLM Operator

集群中存在 CSV 中指定需要的资源后,OLM Operator 将负责部署由 CSV 资源定义的应用程序。

OLM Operator 不负责创建所需资源;用户可选择使用 CLI 手动创建这些资源,也可选择使用 Catalog Operator 来创建这些资源。这种关注点分离的机制可以使得用户逐渐增加他们选择用于其应用程序的 OLM 框架量。

OLM Operator 使用以下工作流:

  1. 观察命名空间中的集群服务版本(CSV),并检查是否满足要求。
  2. 如果满足要求,请运行 CSV 的安装策略。

    注意

    CSV 必须是 Operator 组的活跃成员,才可运行该安装策略。

1.4.2.3. Catalog Operator

Catalog Operator 负责解析和安装集群服务版本(CSV)以及它们指定的所需资源。另外还负责监视频道中的目录源中是否有软件包更新,并将其升级(可选择自动)至最新可用版本。

要跟踪频道中的软件包,您可以创建一个 Subscription 对象来配置所需的软件包、频道和 CatalogSource 对象,以便拉取更新。在找到更新后,便会代表用户将一个适当的 InstallPlan 对象写入命名空间。

Catalog Operator 使用以下工作流:

  1. 连接到集群中的每个目录源。
  2. 监视是否有用户创建的未解析安装计划,如果有:

    1. 查找与请求名称相匹配的 CSV,并将此 CSC 添加为已解析的资源。
    2. 对于每个受管或所需 CRD,将其添加为已解析的资源。
    3. 对于每个所需 CRD,找到管理相应 CRD 的 CSV。
  3. 监视是否有已解析的安装计划并为其创建已发现的所有资源(用户批准或自动)。
  4. 观察目录源和订阅并根据它们创建安装计划。

1.4.2.4. Catalog Registry

Catalog Registry 存储 CSV 和 CRD 以便在集群中创建,并存储有关软件包和频道的元数据。

package manifest 是 Catalog Registry 中的一个条目,用于将软件包标识与 CSV 集相关联。在软件包中,频道指向特定 CSV。因为 CSV 明确引用了所替换的 CSV,软件包清单向 Catalog Operator 提供了将 CSV 更新至频道中最新版本所需的信息,逐步安装和替换每个中间版本。

1.4.3. Operator Lifecycle Manager 工作流

本指南概述了 OpenShift Container Platform 中 Operator Lifecycle Manager (OLM) 的工作流。

1.4.3.1. OLM 中的 Operator 安装和升级工作流

在 Operator Lifecycle Manager (OLM) 生态系统中,以下资源用于解决 Operator 的安装和升级问题:

  • ClusterServiceVersion (CSV)
  • CatalogSource
  • Subscription

CSV 中定义的 Operator 元数据可保存在一个称为目录源的集合中。目录源使用 Operator Registry API,OLM 又使用目录源来查询是否有可用的 Operator 及已安装 Operator 是否有升级版本。

图 1.3. 目录源概述

olm catalogsource

在目录源中,Operator 被整合为更新软件包和更新流,我们称为频道,这应是 OpenShift Container Platform 或其他软件(如 Web 浏览器)在持续发行周期中的常见更新模式。

图 1.4. 目录源中的软件包和频道

olm channels

用户在订阅中的特定目录源中指示特定软件包和频道,如 etcd 包及其 alpha 频道。如果订阅了命名空间中尚未安装的软件包,则会安装该软件包的最新 Operator。

注意

OLM 会刻意避免版本比较,因此给定 catalogchannelpackage 路径提供的“latest”或“newest”Operator 不一定是最高版本号。更应将其视为频道的 head 引用,类似 Git 存储库。

每个 CSV 均有一个 replaces 参数,指明所替换的是哪个 Operator。这样便构建了一个可通过 OLM 查询的 CSV 图,且不同频道之间可共享更新。可将频道视为更新图表的入口点:

图 1.5. OLM 的可用频道更新图表

olm replaces

软件包中的频道示例

packageName: example
channels:
- name: alpha
  currentCSV: example.v0.1.2
- name: beta
  currentCSV: example.v0.1.3
defaultChannel: alpha

为了让 OLM 成功查询更新、给定一个目录源、软件包、频道和 CSV,目录必须能够明确无误地返回替换输入 CSV 的单个 CSV。

1.4.3.1.1. 升级路径示例

对于示例升级场景,假设安装的 Operator 对应于 0.1.1 版 CSV。OLM 查询目录源,并在订阅的频道中检测升级,新的 0.1.3 版 CSV 替换了旧的但未安装的 0.1.2 版 CSV,后者又取代了较早且已安装的 0.1.1 版 CSV。

OLM 通过 CSV 中指定的 replaces 字段从频道头倒退至之前的版本,以确定升级路径为 0.1.30.1.20.1.1,其中箭头代表前者取代后者。OLM 一次仅升级一个 Operator 版本,直至到达频道头。

对于该给定场景,OLM 会安装 0.1.2 版 Operator 来取代现有的 0.1.1 版 Operator。然后再安装 0.1.3 版 Operator 来取代之前安装的 0.1.2 版 Operator。至此,所安装的 0.1.3 版 Operator 与频道头相匹配,意味着升级已完成。

1.4.3.1.2. 跳过升级

OLM 中升级的基本路径是:

  • 通过对 Operator 的一个或多个更新来更新目录源。
  • OLM 会遍历 Operator 的所有版本,直到到达目录源包含的最新版本。

但有时这不是一种安全操作。某些情况下,已发布但尚未就绪的 Operator 版本不可安装至集群中,如版本中存在严重漏洞。

这种情况下,OLM 必须考虑两个集群状态,并提供支持这两个状态的更新图:

  • 集群发现并安装了“不良”中间 Operator。
  • “不良”中间 Operator 尚未安装至集群中。

通过发送新目录并添加跳过的发行版本,可保证无论集群状态如何以及是否发现了不良更新,OLM 总能获得单个唯一更新。

带有跳过发行版本的 CSV 示例

apiVersion: operators.coreos.com/v1alpha1
kind: ClusterServiceVersion
metadata:
  name: etcdoperator.v0.9.2
  namespace: placeholder
  annotations:
spec:
    displayName: etcd
    description: Etcd Operator
    replaces: etcdoperator.v0.9.0
    skips:
    - etcdoperator.v0.9.1

考虑以下 Old CatalogSourceNew CatalogSource 示例。

图 1.6. 跳过更新

olm skipping updates

该图表明:

  • Old CatalogSource 中的任何 Operator 在 New CatalogSource 中均有单一替换项。
  • New CatalogSource 中的任何 Operator 在 New CatalogSource 中均有单一替换项。
  • 如果未曾安装不良更新,将来也绝不会安装。
1.4.3.1.3. 替换多个 Operator

按照描述创建 New CatalogSource 需要发布 CSV 来替换单个 Operator,但可跳过多个。该操作可通过 skipRange 注解来完成:

olm.skipRange: <semver_range>

其中 <semver_range> 具有 semver library 所支持的版本范围格式。

当在目录中搜索更新时,如果某个频道头提供一个 skipRange 注解,且当前安装的 Operator 的版本字段在该范围内,则 OLM 会更新至该频道中的最新条目。

先后顺序:

  1. Subscription 上由 sourceName 指定的源中的频道头(满足其他跳过条件的情况下)。
  2. sourceName 指定的源中替换当前 Operator 的下一 Operator。
  3. 对 Subscription 可见的另一个源中的频道头(满足其他跳过条件的情况下)。
  4. 在对 Subscription 可见的任何源中替换当前 Operator 的下一 Operator。

带有 skipRange 的 CSV 示例

apiVersion: operators.coreos.com/v1alpha1
kind: ClusterServiceVersion
metadata:
    name: elasticsearch-operator.v4.1.2
    namespace: <namespace>
    annotations:
        olm.skipRange: '>=4.1.0 <4.1.2'

1.4.3.1.4. Z-stream 支持

对于相同从版本,z-stream 或补丁版本必须取代所有先前 z-stream 版本。OLM 不考虑主版本、次版本或补丁版本,只需要在目录中构建正确的图表。

换句话说,OLM 必须能够像在 Old CatalogSource 中一样获取一个图表,像在 New CatalogSource 中一样生成一个图表:

图 1.7. 替换多个 Operator

olm z stream

该图表明:

  • Old CatalogSource 中的任何 Operator 在 New CatalogSource 中均有单一替换项。
  • New CatalogSource 中的任何 Operator 在 New CatalogSource 中均有单一替换项。
  • Old CatalogSource 中的所有 z-stream 版本均会更新至 New CatalogSource 中最新 z-stream 版本。
  • 不可用版本可被视为“虚拟”图表节点;它们的内容无需存在,注册表只需像图表看上去这样响应即可。

1.4.4. Operator Lifecycle Manager 依赖项解析

本指南概述了 OpenShift Container Platform 中 Operator Lifecycle Manager (OLM) 内的依赖项解析和自定义资源定义 (CRD) 升级生命周期。

1.4.4.1. 关于依赖项解析

OLM 管理运行 Operator 的依赖项解析和升级生命周期。在很多方面,OLM 的问题与其他操作系统软件包管理程序类似,比如 yumrpm

但其中有一个限制是相似系统一般不存在而 OLM 存在的,那就是:因为 Operator 始终在运行,所以 OLM 会努力确保您所接触的 Operator 组始终相互兼容。

这意味着,OLM 绝不会:

  • 安装一组系统无法提供其所需 API 的 Operator,或
  • 更新某个 Operator 之时导致依赖该 Operator 的另一 Operator 中断。

1.4.4.2. CRD 升级

如果自定义资源定义(CRD)属于单一集群服务版本(CSV),OLM 会立即对其升级。如果某个 CRD 被多个 CSV 拥有,则当该 CRD 满足以下所有向后兼容条件时才会升级:

  • 所有已存在于当前 CRD 中的服务版本都包括在新 CRD 中。
  • 在根据新 CRD 的验证模式(schema)进行验证后,与 CRD 的服务版本关联的所有现有实例或自定义资源均有效。
1.4.4.2.1. 添加新版 CRD

流程

要添加新版 CRD:

  1. 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 推送至您的捆绑包中。
1.4.4.2.2. 弃用或删除 CRD 版本

Operator Lifecycle Manager(OLM)不允许立即删除自定义资源定义(CRD)的服务版本。弃用的 CRD 版本应首先通过将 CRD 的 served 字段设置为 false 来禁用。随后在升级 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 2
    1 2
    对应更新 storage 字段。
    注意

    要从 CRD 中删除曾是或现在是 storage 的特定版本,该版本必须从 CRD 状态下的 storedVersion 中删除。OLM 一旦检测到某个已存储版本在新 CRD 中不再存在,OLM 将尝试执行这一操作。

  3. 使用以上更改来升级 CRD。
  4. 在后续升级周期中,非服务版本可从 CRD 中完全删除。例如:

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

1.4.4.3. 依赖项解析方案示例

在以下示例中,provider(供应商) 是指"拥有" CRD 或 API 服务的 Operator。

示例:弃用从属 API

A 和 B 是 API(CRD):

  • A 的供应商依赖 B。
  • B 的供应商有一个订阅。
  • B 更新供应商提供 C,但弃用 B。

结果:

  • B 不再有供应商。
  • A 不再工作。

这是 OLM 通过升级策略阻止的一个案例。

示例:版本死锁

A 和 B 均为 API:

  • A 的供应商需要 B。
  • B 的供应商需要 A。
  • A 更新的供应商到(提供 A2,需要 B2)并弃用 A。
  • B 更新的供应商到(提供 B2,需要 A2)并弃用 B。

如果 OLM 试图在更新 A 的同时不更新 B,或更新 B 的同时不更新 A,则无法升级到新版 Operator,即使可找到新的兼容集也无法更新。

这是 OLM 通过升级策略阻止的另一案例。

1.4.5. operator 组

本指南概述了 OpenShift Container Platform 中 Operator Lifecycle Manager(OLM)的 Operator 组使用情况。

1.4.5.1. 关于 Operator 组

OperatorGroup 资源定义的 Operator 组,为 OLM 安装的 Operator 提供多租户配置。Operator 组选择目标命名空间,在其中为其成员 Operator 生成所需的 RBAC 访问权限。

这一组目标命名空间通过存储在 CSV 的 olm.targetNamespaces 注解中的以逗号分隔的字符串来提供。该注解应用于成员 Operator 的 CSV 实例,并注入它们的部署中。

1.4.5.2. Operator 组成员

满足以下任一条件,Operator 即可被视为 Operator 组的 member

  • Operator 的 CSV 与 Operator 组位于同一命名空间中。
  • Operator CSV 中的安装模式支持 Operator 组的目标命名空间集。

CSV 中的安装模式由 InstallModeType 字段和 Supported 的布尔值字段组成。CSV 的 spec 可以包含一组由四个不同 InstallModeTypes 组成的安装模式:

表 1.4. 安装模式和支持的 Operator 组

InstallModeType描述

OwnNamespace

Operator 可以是选择其自有命名空间的 Operator 组的成员。

SingleNamespace

Operator 可以是选择一个命名空间的 Operator 组的成员。

MultiNamespace

Operator 可以是选择多个命名空间的 Operator 组的成员。

AllNamespaces

Operator 可以是选择所有命名空间的 Operator 组的成员(目标命名空间集为空字符串 "")。

注意

如果 CSV 的 spec 省略 InstallModeType 条目,则该类型将被视为不受支持,除非可通过隐式支持的现有条目推断出支持。

1.4.5.3. 目标命名空间选择

您可以使用 spec.targetNamespaces 参数为 Operator 组显式命名目标命名空间:

apiVersion: operators.coreos.com/v1
kind: OperatorGroup
metadata:
  name: my-group
  namespace: my-namespace
spec:
  targetNamespaces:
  - my-namespace

您还可以使用带有 spec.selector 参数的标签选择器指定命名空间:

apiVersion: operators.coreos.com/v1
kind: OperatorGroup
metadata:
  name: my-group
  namespace: my-namespace
spec:
  selector:
    cool.io/prod: "true"
重要

不建议通过 spec.targetNamespaces 列出多个命名空间,或通过 spec.selector 使用标签选择器,因为在以后的版本中可能会删除对 Operator 组中多个目标命名空间的支持。

如果 spec.targetNamespacesspec.selector 均已定义,则会忽略 spec.selector。另外,您可以省略 spec.selectorspec.targetNamespaces 来指定一个 全局 Operator 组,该组选择所有命名空间:

apiVersion: operators.coreos.com/v1
kind: OperatorGroup
metadata:
  name: my-group
  namespace: my-namespace

Opeator 组的 status.namespaces 参数中会显示所选命名空间的解析集合。全局 OperatorGroup 的 status.namespace 包含空字符串 (""),而该字符串会向正在使用的 Operator 发出信号,要求其监视所有命名空间。

1.4.5.4. operator 组 CSV 注解

Operator 组的成员 CSV 具有以下注解:

注解描述

olm.operatorGroup=<group_name>

包含 Operator 组的名称。

olm.operatorGroupNamespace=<group_namespace>

包含 Operator 组的命名空间。

olm.targetNamespaces=<target_namespaces>

包含以逗号分隔的字符串,列出 Operator 组的目标命名空间选择。

注意

olm.targetNamespaces 以外的所有注解均包含在复制的 CSV 中。在复制的 CSV 上省略 olm.targetNamespaces 注解可防止租户之间目标命名空间出现重复。

1.4.5.5. 所提供的 API 注解

group/version/kind (GVK) 是 Kubernetes API 的唯一标识符。olm.providedAPIs 注解中会显示有关 Operator 组提供哪些 GVK 的信息。该注解值为一个字符串,由用逗号分隔的 <kind>.<version>.<group> 组成。其中包括由 Operator 组的所有活跃成员 CSV 提供的 CRD 和 APIService 的 GVK。

查看以下 OperatorGroup 示例,该 OperatorGroup 带有提供 PackageManifest 资源的单个活跃成员 CSV:

apiVersion: operators.coreos.com/v1
kind: OperatorGroup
metadata:
  annotations:
    olm.providedAPIs: PackageManifest.v1alpha1.packages.apps.redhat.com
  name: olm-operators
  namespace: local
  ...
spec:
  selector: {}
  serviceAccount:
    metadata:
      creationTimestamp: null
  targetNamespaces:
  - local
status:
  lastUpdated: 2019-02-19T16:18:28Z
  namespaces:
  - local

1.4.5.6. 基于角色的访问控制

创建 Operator 组时,会生成三个集群角色。每个 ClusterRole 均包含一个聚会规则,后者带有一个选择器以匹配标签,如下所示:

集群角色要匹配的标签

<operatorgroup_name>-admin

olm.opgroup.permissions/aggregate-to-admin: <operatorgroup_name>

<operatorgroup_name>-edit

olm.opgroup.permissions/aggregate-to-edit: <operatorgroup_name>

<operatorgroup_name>-view

olm.opgroup.permissions/aggregate-to-view: <operatorgroup_name>

当 CSV 成为 Operator 组的活跃成员时,只要该 CSV 正在使用 AllNamespaces 安装模式来监视所有命名空间,且没有因 InterOperatorGroupOwnerConflict 原因处于故障状态,便会生成以下 RBAC 资源。

  • 来自 CRD 的每个 API 资源的集群角色
  • 来自 API 服务的每个 API 资源的集群角色
  • 其他角色和角色绑定

表 1.5. 来自 CRD 的为每个 API 资源生成的集群角色

集群角色设置

<kind>.<group>-<version>-admin

<kind> 上的操作动词:

  • *

聚合标签:

  • rbac.authorization.k8s.io/aggregate-to-admin: true
  • olm.opgroup.permissions/aggregate-to-admin: <operatorgroup_name>

<kind>.<group>-<version>-edit

<kind> 上的操作动词:

  • create
  • update
  • patch
  • delete

聚合标签:

  • rbac.authorization.k8s.io/aggregate-to-edit: true
  • olm.opgroup.permissions/aggregate-to-edit: <operatorgroup_name>

<kind>.<group>-<version>-view

<kind> 上的操作动词:

  • get
  • list
  • watch

聚合标签:

  • rbac.authorization.k8s.io/aggregate-to-view: true
  • olm.opgroup.permissions/aggregate-to-view: <operatorgroup_name>

<kind>.<group>-<version>-view-crdview

apiextensions.k8s.io customresourcedefinitions <crd-name> 上的操作动词:

  • get

聚合标签:

  • rbac.authorization.k8s.io/aggregate-to-view: true
  • olm.opgroup.permissions/aggregate-to-view: <operatorgroup_name>

表 1.6. 来自 API 服务的为每个 API 资源生成的集群角色

集群角色设置

<kind>.<group>-<version>-admin

<kind> 上的操作动词:

  • *

聚合标签:

  • rbac.authorization.k8s.io/aggregate-to-admin: true
  • olm.opgroup.permissions/aggregate-to-admin: <operatorgroup_name>

<kind>.<group>-<version>-edit

<kind> 上的操作动词:

  • create
  • update
  • patch
  • delete

聚合标签:

  • rbac.authorization.k8s.io/aggregate-to-edit: true
  • olm.opgroup.permissions/aggregate-to-edit: <operatorgroup_name>

<kind>.<group>-<version>-view

<kind> 上的操作动词:

  • get
  • list
  • watch

聚合标签:

  • rbac.authorization.k8s.io/aggregate-to-view: true
  • olm.opgroup.permissions/aggregate-to-view: <operatorgroup_name>

其他角色和角色绑定

  • 如果 CSV 定义了一个目标命名空间,其中包括 *,则会针对 CSV 权限字段中定义的每个 permissions 生成集群角色和对应集群角色绑定。所有生成的资源均会标上 olm.owner: <csv_name>olm.owner.namespace: <csv_namespace> 标签。
  • 如果 CSV 没有定义一个包含 * 的目标命名空间,则 Operator 命名空间中的所有角色和角色绑定都使用 olm.owner: <csv_name>olm.owner.namespace: <csv_namespace> 标签复制到目标命名空间中。

1.4.5.7. 复制的 CSV

OLM 会在 Operator 组的每个目标命名空间中创建 Operator 组的所有活跃成员 CSV 的副本。复制 CSV 的目的在于告诉目标命名空间的用户,特定 Operator 已配置为监视在此创建的资源。

复制的 CSV 会复制状态原因,并会更新以匹配其源 CSV 的状态。在集群上创建复制的 CSV 之前,会从这些 CSV 中分离 olm.targetNamespaces 注解。省略目标命名空间选择可避免租户之间存在目标命名空间重复的现象。

当所复制的 CSV 的源 CSV 不存在或其源 CSV 所属的 Operator 组不再指向复制 CSV 的命名空间时,会删除复制的 CSV。

1.4.5.8. 静态 Operator 组

如果 Operator 组的 spec.staticProvidedAPIs 字段被设置为 true,则 Operator 组为静态。因此,OLM 不会修改 Operator 组的 olm.providedAPIs 注解,这意味着可以提前设置它。如果一组命名空间没有活跃的成员 CSV 来为资源提供 API,而用户想使用 Operator 组来防止命名空间集中发生资源争用,则这一操作十分有用。

以下是一个 Operator 组示例,它使用 something.cool.io/cluster-monitoring: "true" 注解来保护所有命名空间中的 Prometheus 资源:

apiVersion: operators.coreos.com/v1
kind: OperatorGroup
metadata:
  name: cluster-monitoring
  namespace: cluster-monitoring
  annotations:
    olm.providedAPIs: Alertmanager.v1.monitoring.coreos.com,Prometheus.v1.monitoring.coreos.com,PrometheusRule.v1.monitoring.coreos.com,ServiceMonitor.v1.monitoring.coreos.com
spec:
  staticProvidedAPIs: true
  selector:
    matchLabels:
      something.cool.io/cluster-monitoring: "true"

1.4.5.9. operator 组交集

如果两个 Operator 组的目标命名空间集的交集不是空集,且根据 olm.providedAPIs 注解的定义,所提供的 API 集的交集也不是空集,则称这两个 OperatorGroup 的提供的 API 有交集

一个潜在问题是,提供的 API 有交集的 Operator 组可能在命名空间交集中竞争相同资源。

注意

在检查交集规则时,Operator 组的命名空间始终包含在其所选目标命名空间中。

交集规则

每次活跃成员 CSV 同步时,OLM 均会查询集群,以获取 CSV 组和其他所有 CSV 组之间提供的 API 交集。然后 OLM 会检查该交集是否为空集:

  • 如果结果为 true,且 CSV 提供的 API 是 Operator 组提供的 API 的子集:

    • 继续转变。
  • 如果结果为 true,且 CSV 提供的 API 不是 Operator 组提供的 API 的子集:

    • 如果 Operator 组是静态的:

      • 则清理属于 CSV 的所有部署。
      • 将 CSV 转变为故障状态,状态原因为:CannotModifyStaticOperatorGroupProvidedAPIs
    • 如果 Operator 组不是静态的:

      • 将 Operator 组的 olm.providedAPIs 注解替换为其本身与 CSV 提供的 API 的并集。
  • 如果结果为 false,且 CSV 提供的 API 不是 Operator 组提供的 API 的子集:

    • 则清理属于 CSV 的所有部署。
    • 将 CSV 转变为故障状态,状态原因为:InterOperatorGroupOwnerConflict
  • 如果结果为 false,且 CSV 提供的 API 是 Operator 组提供的 API 的子集:

    • 如果 Operator 组是静态的:

      • 则清理属于 CSV 的所有部署。
      • 将 CSV 转变为故障状态,状态原因为:CannotModifyStaticOperatorGroupProvidedAPIs
    • 如果 Operator 组不是静态的:

      • 将 Operator 组的 olm.providedAPIs 注解替换为其本身与 CSV 提供的 API 的差集。
注意

Operator 组所造成的故障状态不是终端状态。

每次 Operator 组同步时都会执行以下操作:

  • 来自活跃成员 CSV 的提供的 API 集是通过集群计算出来的。注意,复制的 CSV 会被忽略。
  • 将集群集与 olm.providedAPIs 进行比较,如果 olm.providedAPIs 包含任何额外 API,则将删除这些 API。
  • 在所有命名空间中提供相同 API 的所有 CSV 均会重新排序。这样可向交集组中的冲突 CSV 发送通知,表明可能已通过调整大小或删除冲突的 CSV 解决了冲突。

1.4.5.10. 对 Operator 组进行故障排除

成员资格
  • 如果一个命名空间中存在多个 Operator 组,则在该命名空间中创建的所有 CSV 均会变成故障状态,故障原因为:TooManyOperatorGroups。处于故障状态的 CSV 会在命名空间中的 Operator 组达到 1 后转变为等待处理状态。
  • 如果 CSV 的安装模式不支持其命名空间中 Operator 组的目标命名空间选择,CSV 会转变为故障状态,原因为 UnsupportedOperatorGroup。处于故障状态的 CSV 会在 Operator 组的目标命名空间选择变为受支持的配置后转变为待处理,或者 CSV 的安装模式被修改来支持目标命名空间选择。

1.4.6. Operator Lifecycle Manager 指标数据

1.4.6.1. 公开的指标

Operator Lifecycle Manager(OLM)会公开某些 OLM 特定资源,供基于 Prometheus 的 OpenShift Container Platform 集群监控堆栈使用。

表 1.7. OLM 公开的指标

名称描述

catalog_source_count

目录源数量。

csv_abnormal

在协调集群服务版本(CSV)时,每当 CSV 版本处于 Succeeded 以外的任何状态时(如没有安装它时)就会存在。包括 namenamespacephasereasonversion 标签。当存在此指标数据时会创建一个 Prometheus 警报。

csv_count

成功注册的 CSV 数量。

csv_succeeded

在协调 CSV 时,代表 CSV 版本处于 Succeeded 状态(值为 1)或没有处于这个状态(值为 0)。包含 namenamespaceversion 标签。

csv_upgrade_count

CSV 升级的 Monotonic 计数。

install_plan_count

安装计划的数量。

subscription_count

订阅数。

subscription_sync_total

订阅同步的单调计数。包括 channelinstalled CSV 和订阅 name 标签。

1.5. 了解 OperatorHub

1.5.1. 关于 OperatorHub

OperatorHub 是集群管理员用来发现和安装 Operator 的 OpenShift Container Platform 中的 Web 控制台界面。只需单击一次,即可从其非集群源拉取 Operator,并将其安装和订阅至集群中,为工程团队使用 Operator Lifecycle Manager (OLM) 在部署环境中自助管理产品做好准备。

集群管理员可从划分成以下类别的 Operator 源中选择:

类别描述

红帽 Operator

已由红帽打包并提供的红帽产品。受红帽支持。

经认证的 Operator

来自主要独立软件供应商 (ISV) 的产品。红帽与 ISV 合作打包并提供。受 ISV 支持。

社区 Operator

operator-framework/community-operators GitHub 存储库中由相关代表维护的可选可见软件。无官方支持。

自定义 Operator

您自行添加至集群的 Operator。如果您尚未添加任何自定义 Operator,则您的 OperatorHub 上 Web 控制台中便不会出现自定义类别。

注意

OperatorHub 内容可每 60 分钟自动刷新一次。

OperatorHub 上的操作员被打包在 OLM 上运行。这包括一个称为集群服务版本(CSV)的 YAML 文件,其中包含安装和安全运行 Operator 所需的所有 CRD 、RBAC 规则、部署和容器镜像。它还包含用户可见的信息,如功能描述和支持的 Kubernetes 版本。

Operator SDK 可以用来协助开发人员打包 Operators 以用于 OLM 和 OperatorHub。如果您有一个您的客户需要访问的商业应用程序,请使用红帽 ISV 合作伙伴门户(connect.redhat.com)提供的认证流程来包含它。

1.5.2. OperatorHub 架构

OperatorHub UI 组件默认由 openshift-marketplace 命名空间中 OpenShift Container Platform 上的 Marketplace Operator 驱动。

Marketplace Operator 管理 OperatorHubOperatorSource 自定义资源定义(CRD)。

注意

尽管有些 OperatorSource 对象信息可以通过 OperatorHub UI 公开,但只有创建自有 Operator 的用户可直接使用这些信息。

1.5.2.1. OperatorHub CRD

您可以使用 OperatorHub CRD 将集群上 OperatorHub 提供的默认 OperatorSource 对象的状态更改为启用和禁用。该功能对于在有限网络环境中配置 OpenShift Container Platform 来说非常实用。

OperatorHub 自定义资源示例

apiVersion: config.openshift.io/v1
kind: OperatorHub
metadata:
  name: cluster
spec:
  disableAllDefaultSources: true 1
  sources: [ 2
    {
      name: "community-operators",
      disabled: false
    }
  ]

1
disableAllDefaultSources 是一种覆盖机制,用于控制在 OpenShift Container Platform 安装期间默认配置的所有默认 OperatorSource 对象的可用性。
2
通过更改每个源的 disabled 参数值来分别禁用默认源。

1.5.2.2. OperatorSource CRD

对于各个 Operator,OperatorSource CRD 用于定义用于存储 Operator 包的外部数据存储。

OperatorSource 自定义资源示例

apiVersion: operators.coreos.com/v1
kind: OperatorSource
metadata:
  name: community-operators
  namespace: marketplace
spec:
  type: appregistry 1
  endpoint: https://quay.io/cnr 2
  registryNamespace: community-operators 3
  displayName: "Community Operators" 4
  publisher: "Red Hat" 5

1
要将数据存储标识为应用程序 registry,请将 type 设置为 appregistry
2
目前,Quay 是 OperatorHub 使用的外部数据存储,因此 Quay.io appregistry 的端点被设置为 https://quay.io/cnr
3
对于社区 Operator,registryNamespace 会被设置为 community-operator
4
可选择将 displayName 设置为 OperatorHub UI 中显示的 Operator 的名称。
5
也可选择将 publisher 设置为 OperatorHub UI 中显示的发布该 Operator 的个人或机构。

1.5.3. 其他资源

1.6. CRD

1.6.1. 使用自定义资源定义来扩展 Kubernetes API

本指南描述了集群管理员如何通过创建和管理自定义资源定义 (CRD) 来扩展其 OpenShift Container Platform 集群。

1.6.1.1. 自定义资源定义

在 Kubernetes API 中,resource(资源)是存储某一类 API 对象集的端点。例如,内置 Pod 资源包含一组 Pod 对象。

自定义资源定义(CRD)对象在集群中定义一个新的、唯一的对象类型,称为 kind,并允许 Kubernetes API 服务器处理其整个生命周期。

自定义资源 (CR) 对象由集群管理员通过集群中已添加的 CRD 创建,并支持所有集群用户在项目中增加新的资源类型。

当集群管理员增加新 CRD 至集群中时,Kubernetes API 服务器的回应方式是新建一个可由整个集群或单个项目(命名空间)访问的 RESTful 资源路径,并开始服务于指定的 CR。

集群管理员如果要向其他用户授予 CRD 访问权限,可使用集群角色聚合来向用户授予 admineditview 默认集群角色访问权限。集群角色聚合支持将自定义策略规则插入到这些集群角色中。此行为将新资源整合到集群的 RBAC 策略中,就像内置资源一样。

Operator 会通过将 CRD 与任何所需 RBAC 策略和其他软件特定逻辑打包到一起来利用 CRD。集群管理员也可以手动将 CRD 添加到 Operator 生命周期之外的集群中,供所有用户使用。

注意

虽然只有集群管理员可创建 CRD,但具有 CRD 读写权限的开发人员也可通过现有 CRD 来创建 CR。

1.6.1.2. 创建自定义资源定义

要创建自定义资源 (CR) 对象,集群管理员首先必须创建一个自定义资源定义 (CRD)。

先决条件

  • cluster-admin 用户身份访问 OpenShift Container Platform 集群。

流程

要创建 CRD:

  1. 先创建一个包含以下字段类型的 YAML 文件:

    CRD 的 YAML 文件示例

    apiVersion: apiextensions.k8s.io/v1beta1 1
    kind: CustomResourceDefinition
    metadata:
      name: crontabs.stable.example.com 2
    spec:
      group: stable.example.com 3
      version: v1 4
      scope: Namespaced 5
      names:
        plural: crontabs 6
        singular: crontab 7
        kind: CronTab 8
        shortNames:
        - ct 9

    1
    使用 apiextensions.k8s.io/v1beta1 API。
    2
    为定义指定名称。这必须采用 <plural-name>.<group> 格式,并使用来自 groupplural 字段的值。
    3
    为 API 指定组名。API 组是一个逻辑上相关的对象集。例如,JobScheduledJob 等所有批处理对象,均可添加至批处理 API 组(如 batch.api.example.com)中。最好使用您机构的完全限定域名(FQDN)。
    4
    指定 URL 中要用的版本名称。每个 API 组都可能存在于多个版本中,例如 v1alphav1betav1
    5
    指定自定义对象可用于某一个项目 (Namespaced) 还是集群中的所有项目 (Cluster)。
    6
    指定 URL 中要用的复数名称。plural 字段与 API URL 网址中的资源相同。
    7
    指定将在 CLI 上用作别名并用于显示的单数名称。
    8
    指定可创建的对象类型。类型可以采用 CamelCase。
    9
    指定与 CLI 中的资源相匹配的较短字符串。
    注意

    默认情况下,CRD 的覆盖范围为整个集群,适用于所有项目。

  2. 创建 CRD 对象:

    $ oc create -f <file_name>.yaml

    在以下位置新建一个 RESTful API 端点:

    /apis/<spec:group>/<spec:version>/<scope>/*/<names-plural>/...

    例如,以下端点便是通过示例文件创建的:

    /apis/stable.example.com/v1/namespaces/*/crontabs/...

    现在,您即可使用该端点 URL 来创建和管理 CR。对象类型基于您创建的 CRD 对象的 spec.kind 字段。

1.6.1.3. 为自定义资源定义创建集群角色

集群管理员可向现有集群范围的自定义资源定义 (CRD) 授予权限。如果使用 admineditview 默认集群角色,请利用集群角色聚合来制定规则。

重要

您必须为每个角色明确分配权限。权限更多的角色不会继承权限较少角色的规则。如果要为某个角色分配规则,还必须将该操作动词分配给具有更多权限的角色。例如,如果要向 view 角色授予 get crontabs 的权限,也必须向 editadmin 角色授予该权限。adminedit 角色通常会分配给通过项目模板创建项目的用户。

先决条件

  • 创建 CRD。

流程

  1. 为 CRD 创建集群角色定义文件。集群角色定义是一个 YAML 文件,其中包含适用于各个集群角色的规则。OpenShift Container Platform 控制器会将您指定的规则添加至默认集群角色中。

    集群角色定义的 YAML 文件示例

    kind: ClusterRole
    apiVersion: rbac.authorization.k8s.io/v1 1
    metadata:
      name: aggregate-cron-tabs-admin-edit 2
      labels:
        rbac.authorization.k8s.io/aggregate-to-admin: "true" 3
        rbac.authorization.k8s.io/aggregate-to-edit: "true" 4
    rules:
    - apiGroups: ["stable.example.com"] 5
      resources: ["crontabs"] 6
      verbs: ["get", "list", "watch", "create", "update", "patch", "delete", "deletecollection"] 7
    ---
    kind: ClusterRole
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: aggregate-cron-tabs-view 8
      labels:
        # Add these permissions to the "view" default role.
        rbac.authorization.k8s.io/aggregate-to-view: "true" 9
        rbac.authorization.k8s.io/aggregate-to-cluster-reader: "true" 10
    rules:
    - apiGroups: ["stable.example.com"] 11
      resources: ["crontabs"] 12
      verbs: ["get", "list", "watch"] 13

    1
    使用 rbac.authorization.k8s.io/v1 API。
    2 8
    为定义指定名称。
    3
    指定该标签向 admin 默认角色授予权限。
    4
    指定该标签向 edit 默认角色授予权限。
    5 11
    指定 CRD 的组名。
    6 12
    指定适用于这些规则的 CRD 的复数名称。
    7 13
    指定代表角色所获得的权限的操作动词。例如,对 adminedit 角色应用读写权限,对 view 角色应用只读权限。
    9
    指定该标签向 view 默认角色授予权限。
    10
    指定该标签向 cluster-reader 默认角色授予权限。
  2. 创建集群角色:

    $ oc create -f <file_name>.yaml

1.6.1.4. 通过文件创建自定义资源

将自定义资源定义 (CRD) 添加至集群后,可使用 CLI 按照自定义资源 (CR) 规范通过文件创建 CR。

先决条件

  • 集群管理员已将 CRD 添加至集群中。

流程

  1. 为 CR 创建 YAML 文件。在下面的定义示例中,cronSpecimage 自定义字段在 Kind: CronTab 的 CR 中设定。Kind 来自 CRD 对象的 spec.kind 字段:

    CR 的 YAML 文件示例

    apiVersion: "stable.example.com/v1" 1
    kind: CronTab 2
    metadata:
      name: my-new-cron-object 3
      finalizers: 4
      - finalizer.stable.example.com
    spec: 5
      cronSpec: "* * * * /5"
      image: my-awesome-cron-image

    1
    指定 CRD 中的组名称和 API 版本(名称/版本)。
    2
    指定 CRD 中的类型。
    3
    指定对象的名称。
    4
    指定对象的结束程序(如有)。结束程序可让控制器实现在删除对象之前必须完成的条件。
    5
    指定特定于对象类型的条件。
  2. 创建完文件后,再创建对象:

    $ oc create -f <file_name>.yaml

1.6.1.5. 检查自定义资源

您可使用 CLI 检查集群中存在的自定义资源 (CR) 对象。

先决条件

  • 您有权访问的命名空间中已存在 CR 对象。

流程

  1. 要获取特定类型的 CR 的信息,请运行:

    $ oc get <kind>

    例如:

    $ oc get crontab

    输出示例

    NAME                 KIND
    my-new-cron-object   CronTab.v1.stable.example.com

    资源名称不区分大小写,您既可使用 CRD 中定义的单数或复数形式,也可使用简称。例如:

    $ oc get crontabs
    $ oc get crontab
    $ oc get ct
  2. 还可查看 CR 的原始 YAML 数据:

    $ oc get <kind> -o yaml

    例如:

    $ oc get ct -o yaml

    输出示例

    apiVersion: v1
    items:
    - apiVersion: stable.example.com/v1
      kind: CronTab
      metadata:
        clusterName: ""
        creationTimestamp: 2017-05-31T12:56:35Z
        deletionGracePeriodSeconds: null
        deletionTimestamp: null
        name: my-new-cron-object
        namespace: default
        resourceVersion: "285"
        selfLink: /apis/stable.example.com/v1/namespaces/default/crontabs/my-new-cron-object
        uid: 9423255b-4600-11e7-af6a-28d2447dc82b
      spec:
        cronSpec: '* * * * /5' 1
        image: my-awesome-cron-image 2

    1 2
    显示用于创建对象的 YAML 的自定义数据。

1.6.2. 管理自定义资源定义中的资源

本指南向开发人员介绍了如何管理来自自定义资源定义 (CRD) 的自定义资源 (CR)。

1.6.2.1. 自定义资源定义

在 Kubernetes API 中,resource(资源)是存储某一类 API 对象集的端点。例如,内置 Pod 资源包含一组 Pod 对象。

自定义资源定义(CRD)对象在集群中定义一个新的、唯一的对象类型,称为 kind,并允许 Kubernetes API 服务器处理其整个生命周期。

自定义资源 (CR) 对象由集群管理员通过集群中已添加的 CRD 创建,并支持所有集群用户在项目中增加新的资源类型。

Operator 会通过将 CRD 与任何所需 RBAC 策略和其他软件特定逻辑打包到一起来利用 CRD。集群管理员也可以手动将 CRD 添加到 Operator 生命周期之外的集群中,供所有用户使用。

注意

虽然只有集群管理员可创建 CRD,但具有 CRD 读写权限的开发人员也可通过现有 CRD 来创建 CR。

1.6.2.2. 通过文件创建自定义资源

将自定义资源定义 (CRD) 添加至集群后,可使用 CLI 按照自定义资源 (CR) 规范通过文件创建 CR。

先决条件

  • 集群管理员已将 CRD 添加至集群中。

流程

  1. 为 CR 创建 YAML 文件。在下面的定义示例中,cronSpecimage 自定义字段在 Kind: CronTab 的 CR 中设定。Kind 来自 CRD 对象的 spec.kind 字段:

    CR 的 YAML 文件示例

    apiVersion: "stable.example.com/v1" 1
    kind: CronTab 2
    metadata:
      name: my-new-cron-object 3
      finalizers: 4
      - finalizer.stable.example.com
    spec: 5
      cronSpec: "* * * * /5"
      image: my-awesome-cron-image

    1
    指定 CRD 中的组名称和 API 版本(名称/版本)。
    2
    指定 CRD 中的类型。
    3
    指定对象的名称。
    4
    指定对象的结束程序(如有)。结束程序可让控制器实现在删除对象之前必须完成的条件。
    5
    指定特定于对象类型的条件。
  2. 创建完文件后,再创建对象:

    $ oc create -f <file_name>.yaml

1.6.2.3. 检查自定义资源

您可使用 CLI 检查集群中存在的自定义资源 (CR) 对象。

先决条件

  • 您有权访问的命名空间中已存在 CR 对象。

流程

  1. 要获取特定类型的 CR 的信息,请运行:

    $ oc get <kind>

    例如:

    $ oc get crontab

    输出示例

    NAME                 KIND
    my-new-cron-object   CronTab.v1.stable.example.com

    资源名称不区分大小写,您既可使用 CRD 中定义的单数或复数形式,也可使用简称。例如:

    $ oc get crontabs
    $ oc get crontab
    $ oc get ct
  2. 还可查看 CR 的原始 YAML 数据:

    $ oc get <kind> -o yaml

    例如:

    $ oc get ct -o yaml

    输出示例

    apiVersion: v1
    items:
    - apiVersion: stable.example.com/v1
      kind: CronTab
      metadata:
        clusterName: ""
        creationTimestamp: 2017-05-31T12:56:35Z
        deletionGracePeriodSeconds: null
        deletionTimestamp: null
        name: my-new-cron-object
        namespace: default
        resourceVersion: "285"
        selfLink: /apis/stable.example.com/v1/namespaces/default/crontabs/my-new-cron-object
        uid: 9423255b-4600-11e7-af6a-28d2447dc82b
      spec:
        cronSpec: '* * * * /5' 1
        image: my-awesome-cron-image 2

    1 2
    显示用于创建对象的 YAML 的自定义数据。

第 2 章 用户任务

2.1. 从已安装的 Operator 创建应用程序

本指南向开发人员介绍了如何使用 OpenShift Container Platform Web 控制台从已安装的 Operator 创建应用程序。

2.1.1. 使用 Operator 创建 etcd 集群

本流程介绍了如何通过由 Operator Lifecycle Manager (OLM) 管理的 etcd Operator 来新建一个 etcd 集群。

先决条件

  • OpenShift Container Platform 4.5 集群访问权限
  • 管理员已在集群范围内安装了 etcd Operator。

流程

  1. 针对此流程在 OpenShift Container Platform Web 控制台中新建一个项目。这个示例使用名为 my-etcd 的项目。
  2. 导航至 Operators → Installed Operators 页面。由集群管理员安装到集群且可供使用的 Operator 将以集群服务版本(CSV)列表形式显示在此处。CSV 用于启动和管理由 Operator 提供的软件。

    提示

    使用以下命令从 CLI 获得该列表:

    $ oc get csv
  3. 进入 Installed Operators 页面,点击 Copied,然后点击 etcd Operator 查看更多详情和可用操作。

    正如 Provided API 下所示,该 Operator 提供了三类新资源,包括一种用于 etcd Cluster 的资源(EtcdCluster 资源)。这些对象的工作方式与内置的原生 Kubernetes 对象(如 DeploymentReplicaSet )相似,但包含特定于管理 etcd 的逻辑。

  4. 新建 etcd 集群:

    1. etcd Cluster API 方框中,点击 Create New
    2. 在下一页上,您可对 EtcdCluster 对象的最小起始模板进行任何修改,比如集群大小。现在,点击 Create 即可完成。点击后即可触发 Operator 启动 pod、服务和新 etcd 集群的其他组件。
  5. 单击 Resources 选项卡,可以看到您的项目现在包含很多由 Operator 自动创建和配置的资源。

    验证已创建了支持您从项目中的其他 pod 访问数据库的 Kubernetes 服务。

  6. 给定项目中具有 edit 角色的所有用户均可创建、管理和删除应用程序实例(本例中为 etcd 集群),这些实例由已在项目中创建的 Operator 以自助方式管理,就像云服务一样。如果要赋予其他用户这一权利,项目管理员可使用以下命令添加角色:

    $ oc policy add-role-to-user edit <user> -n <target_project>

现在您有了一个 etcd 集群,当 pod 运行不畅,或在集群中的节点之间迁移时,该集群将对故障做出反应并重新平衡数据。最重要的是,具有适当访问权限的集群管理员或开发人员现在可轻松将该数据库用于其应用程序。

2.2. 在命名空间中安装 Operator

如果集群管理员将 Operator 安装权限委托给您的帐户,您可以以自助服务的方式将 Operator 安装并订阅到命名空间中。

2.2.1. 先决条件

  • 集群管理员必须在 OpenShift Container Platform 用户帐户中添加某些权限,以便允许将自助服务 Operator 安装到命名空间。详情请参阅允许非集群管理员安装 Operator

2.2.2. 使用 OperatorHub 安装 operator

OperatorHub 是一个发现 Operator 的用户界面,它与 Operator Lifecycle Manager(OLM)一起工作,后者在集群中安装和管理 Operator。

作为具有适当权限的用户,您可以使用 OpenShift Container Platform Web 控制台或 CLI 安装来自 OperatorHub 的 Operator。

安装过程中,您必须为 Operator 确定以下初始设置:

安装模式
选择要在其中安装 Operator 的特定命名空间。
更新频道
如果某个 Operator 可通过多个频道获得,则可任选您想要订阅的频道。例如,要通过 stable 频道部署(如果可用),则从列表中选择这个选项。
批准策略

您可以选择自动或者手动更新。

如果选择自动更新某个已安装的 Operator,则当所选频道中有该 Operator 的新版本时,Operator Lifecycle Manager(OLM)将自动升级 Operator 的运行实例,而无需人为干预。

如果选择手动更新,则当有新版 Operator 可用时,OLM 会创建更新请求。作为集群管理员,您必须手动批准该更新请求,才可将 Operator 更新至新版本。

2.2.3. 使用 Web 控制台从 OperatorHub 安装

您可以使用 OpenShift Container Platform Web 控制台从 OperatorHub 安装并订阅 Operator。

先决条件

  • 使用具有 Operator 安装权限的账户访问 OpenShift Container Platform 集群。

流程

  1. 在 Web 控制台中导航至 Operators → OperatorHub 页面。
  2. 找到您需要的 Operator(滚动页面会在 Filter by keyword 框中输入查找关键字)。例如,输入 advanced 来查找 Advanced Cluster Management for Kubernetes Operator。

    您还可以根据基础架构功能过滤选项。例如,如果您希望 Operator 在断开连接的环境中工作,请选择 Disconnected

  3. 选择要显示更多信息的 Operator。

    注意

    选择 Community Operator 会警告红帽没有认证社区 Operator ; 您必须确认该警告方可继续。

  4. 阅读 Operator 信息并单击 Install
  5. Install Operator 页面中:

    1. 选择要在其中安装 Operator 的特定单一命名空间。该 Operator 仅限在该单一命名空间中监视和使用。
    2. 选择一个更新频道(如有多个可用)。
    3. 如前面所述,选择自动手动批准策略。
  6. 点击 Install 使 Operator 可供 OpenShift Container Platform 集群上的所选命名空间使用。

    1. 如果选择了手动批准策略,订阅的升级状态将保持在 Upgrading 状态,直至您审核并批准安装计划。

      Install Plan 页面批准后,订阅的升级状态将变为 Up to date

    2. 如果选择了 Automatic 批准策略,升级状态会在不用人工参与的情况下变为 Up to date
  7. 在订阅的升级状态成为 Up to date 后,选择 Operators → Installed Operators 来验证已安装 Operator 的 ClusterServiceVersion(CSV)是否最终出现了。状态最终会在相关命名空间中变为 InstallSucceeded

    注意

    对于 All namespaces…​ 安装模式,状态在 openshift-operators 命名空间中解析为 InstallSucceeded,但如果检查其他命名空间,则状态为 Copied

    如果没有:

    1. 检查 openshift-operators 项目(如果选择了 A specific namespace…​ 安装模式)中的 openshift-operators 项目中的 pod 的日志,这会在 Workloads → Pods 页面中报告问题以便进一步排除故障。

2.2.4. 使用 CLI 从 OperatorHub 安装

您可以使用 CLI 从 OperatorHub 安装 Operator,而不必使用 OpenShift Container Platform Web 控制台。使用 oc 命令来创建或更新一个订阅对象。

先决条件

  • 使用具有 Operator 安装权限的账户访问 OpenShift Container Platform 集群。
  • 在您的本地系统安装 oc 命令。

流程

  1. 查看 OperatorHub 中集群可用的 Operator 列表:

    $ oc get packagemanifests -n openshift-marketplace

    输出示例

    NAME                               CATALOG               AGE
    3scale-operator                    Red Hat Operators     91m
    advanced-cluster-management        Red Hat Operators     91m
    amq7-cert-manager                  Red Hat Operators     91m
    ...
    couchbase-enterprise-certified     Certified Operators   91m
    crunchy-postgres-operator          Certified Operators   91m
    mongodb-enterprise                 Certified Operators   91m
    ...
    etcd                               Community Operators   91m
    jaeger                             Community Operators   91m
    kubefed                            Community Operators   91m
    ...

    记录下所需 Operator 的目录。

  2. 检查所需 Operator,以验证其支持的安装模式和可用频道:

    $ oc describe packagemanifests <operator_name> -n openshift-marketplace
  3. 一个 Operator 组(由 OperatorGroup 对象定义),在其中选择目标命名空间,在其中为与 Operator 组相同的命名空间中的所有 Operator 生成所需的 RBAC 访问权限。

    订阅 Operator 的命名空间必须具有与 Operator 的安装模式相匹配的 Operator 组,可采用 AllNamespaces 模式,也可采用 SingleNamespace 模式。如果您要使用 AllNamespaces 安装 Operator,则 openshift-operators 命名空间已有适当的 Operator 组。

    如果要安装的 Operator 采用 SingleNamespace 模式,而您没有适当的 Operator 组,则必须创建一个。

    注意

    在选择 SingleNamespace 模式时,该流程的 Web 控制台版本会在后台自动为您处理 OperatorGroupSubscription 对象的创建。

    1. 创建 OperatorGroup 对象 YAML 文件,如 operatorgroup.yaml

      OperatorGroup 对象示例

      apiVersion: operators.coreos.com/v1
      kind: OperatorGroup
      metadata:
        name: <operatorgroup_name>
        namespace: <namespace>
      spec:
        targetNamespaces:
        - <namespace>

    2. 创建 OperatorGroup 对象:

      $ oc apply -f operatorgroup.yaml
  4. 创建一个 Subscription 对象 YAML 文件,以便为 Operator 订阅一个命名空间,如 sub.yaml

    Subscription 对象示例

    apiVersion: operators.coreos.com/v1alpha1
    kind: Subscription
    metadata:
      name: <subscription_name>
      namespace: openshift-operators 1
    spec:
      channel: <channel_name> 2
      name: <operator_name> 3
      source: redhat-operators 4
      sourceNamespace: openshift-marketplace 5

    1
    对于 AllNamespaces 安装模式的使用,指定 openshift-operators 命名空间。否则,为 SingleNamespace 安装模式使用指定相关单一命名空间。
    2
    要订阅的频道的名称。
    3
    要订阅的 Operator 的名称。
    4
    提供 Operator 的目录源的名称。
    5
    目录源的命名空间。将 openshift-marketplace 用于默认的 OperatorHub 目录源。
  5. 创建 Subscription 对象:

    $ oc apply -f sub.yaml

    此时,OLM 已了解所选的 Operator。Operator 的集群服务版本(CSV)应出现在目标命名空间中,由 Operator 提供的 API 应可用于创建。

2.2.5. 安装 Operator 的特定版本

您可以通过在 Subscription 对象中设置集群服务版本(CSV)来安装 Operator 的特定版本。

先决条件

  • 使用具有 Operator 安装权限的账户访问 OpenShift Container Platform 集群
  • 已安装 OpenShift CLI(oc

流程

  1. 通过设置 startingCSV 字段,创建一个 Subscription 对象 YAML 文件,向带有特定版本的 Operator 订阅一个命名空间。将 installPlanApproval 字段设置为 Manual,以便在目录中存在更新的版本时防止 Operator 自动升级。

    例如,可以使用以下 sub.yaml 文件安装 Red Hat Quay Operator,专门用于版本 3.4.0:

    带有特定起始 Operator 版本的订阅

    apiVersion: operators.coreos.com/v1alpha1
    kind: Subscription
    metadata:
      name: quay-operator
      namespace: quay
    spec:
      channel: quay-v3.4
      installPlanApproval: Manual 1
      name: quay-operator
      source: redhat-operators
      sourceNamespace: openshift-marketplace
      startingCSV: quay-operator.v3.4.0 2

    1
    如果您指定的版本会被目录中的更新版本取代,则将批准策略设置为 Manual。此计划阻止自动升级到更新的版本,且需要在启动 CSV 可以完成安装前手动批准。
    2
    设置 Operator CSV 的特定版本。
  2. 创建 Subscription 对象:

    $ oc apply -f sub.yaml
  3. 手动批准待处理的安装计划以完成 Operator 安装。

2.3. Operator Lifecycle Manager 中的管理准入 webhook。

验证(validating)和变异(mutating)准入 webhook 允许 Operator 作者在资源被保存到对象存储并由 Operator 控制器处理前,拦截、修改、接受或拒绝资源。当 webhook 与 Operator 一同提供时,Operator Lifecycle Manager(OLM)可以管理这些 webhook 的生命周期。

2.3.1. 在 CSV 中定义 webhook

ClusterServiceVersion(CSV)资源包括一个 webhookdefinitions 部分,用于定义 Operator 中附带的验证和变异准入 webhook。例如:

包含验证准入 webhook 的 CSV

apiVersion: operators.coreos.com/v1alpha1
kind: ClusterServiceVersion
metadata:
  annotations:
    description: |-
      An example CSV that contains a webhook
  name: example-webhook.v1.0.0
  namespace: placeholder
spec:
  webhookdefinitions:
  - generateName: example.webhook.com
    type: ValidatingAdmissionWebhook
    deploymentName: "example-webhook-deployment"
    containerPort: 443
    sideEffects: "None"
    failurePolicy: "Ignore"
    admissionReviewVersions:
    - "v1"
    - "v1beta1"
    rules:
    - operations:
      - "CREATE"
      apiGroups:
      - ""
      apiVersions:
      - "v1"
      resources:
      - "configmaps"
    objectSelector:
      foo: bar
    webhookPath: "/validate"
...

Operator Lifecycle Manager(OLM)需要您定义以下内容:

  • type 字段必须设置为 ValidatingAdmissionWebhookMutatingAdmissionWebhook,或者 CSV 会被放置到失败的阶段。
  • CSV 必须包含一个 Deployment,它的名称相当于 webhookdefinitiondeploymentName 字段中提供的值。

创建 webhook 时,OLM 确保 webhook 仅在与 Operator 部署的 Operator 组相匹配的命名空间上操作。

2.3.2. Webhook 注意事项

在开发由 Operator Lifecycle Manager(OLM)管理的准入 webhook 时,请考虑以下限制:

证书颁发机构限制

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

  • TLS 证书文件挂载到部署的 /apiserver.local.config/certificates/apiserver.crt
  • TLS 密钥文件挂载到部署的 /apiserver.local.config/certificates/apiserver.key
Admission webhook 规则约束

为防止 Operator 将集群配置为无法恢复的状态,OLM 如果准入 webhook 中定义的规则拦截了以下请求中的规则,则 OLM 会将 CSV 放置到失败的阶段:

  • 请求目标所有组
  • 请求以 operators.coreos.com 组为目标
  • 请求目标为 ValidatingWebhookConfigurationsMutatingWebhookConfigurations 资源

2.3.3. 其他资源

第 3 章 管理员任务

3.1. 在集群中添加 Operator

集群管理员可以通过 OperatorHub 将 Operator 订阅到命名空间来将 Operator 安装到 OpenShift Container Platform 集群。

3.1.1. 使用 OperatorHub 安装 operator

OperatorHub 是一个发现 Operator 的用户界面,它与 Operator Lifecycle Manager(OLM)一起工作,后者在集群中安装和管理 Operator。

作为具有适当权限的用户,您可以使用 OpenShift Container Platform Web 控制台或 CLI 安装来自 OperatorHub 的 Operator。

安装过程中,您必须为 Operator 确定以下初始设置:

安装模式
选择要在其中安装 Operator 的特定命名空间。
更新频道
如果某个 Operator 可通过多个频道获得,则可任选您想要订阅的频道。例如,要通过 stable 频道部署(如果可用),则从列表中选择这个选项。
批准策略

您可以选择自动或者手动更新。

如果选择自动更新某个已安装的 Operator,则当所选频道中有该 Operator 的新版本时,Operator Lifecycle Manager(OLM)将自动升级 Operator 的运行实例,而无需人为干预。

如果选择手动更新,则当有新版 Operator 可用时,OLM 会创建更新请求。作为集群管理员,您必须手动批准该更新请求,才可将 Operator 更新至新版本。

3.1.2. 使用 Web 控制台从 OperatorHub 安装

您可以使用 OpenShift Container Platform Web 控制台从 OperatorHub 安装并订阅 Operator。

先决条件

  • 使用具有 cluster-admin 权限的账户访问 OpenShift Container Platform 集群。
  • 使用具有 Operator 安装权限的账户访问 OpenShift Container Platform 集群。

流程

  1. 在 Web 控制台中导航至 Operators → OperatorHub 页面。
  2. 找到您需要的 Operator(滚动页面会在 Filter by keyword 框中输入查找关键字)。例如,输入 advanced 来查找 Advanced Cluster Management for Kubernetes Operator。

    您还可以根据基础架构功能过滤选项。例如,如果您希望 Operator 在断开连接的环境中工作,请选择 Disconnected

  3. 选择要显示更多信息的 Operator。

    注意

    选择 Community Operator 会警告红帽没有认证社区 Operator ; 您必须确认该警告方可继续。

  4. 阅读 Operator 信息并单击 Install
  5. Install Operator 页面中:

    1. 任选以下一项:

      • All namespaces on the cluster (default),选择该项会将 Operator 安装至默认 openshift-operators 命名空间,以便供集群中的所有命名空间监视和使用。该选项并非始终可用。
      • A specific namespace on the cluster,该项支持您选择单一特定命名空间来安装 Operator。该 Operator 仅限在该单一命名空间中监视和使用。
    2. 选择要在其中安装 Operator 的特定单一命名空间。该 Operator 仅限在该单一命名空间中监视和使用。
    3. 选择一个更新频道(如有多个可用)。
    4. 如前面所述,选择自动手动批准策略。
  6. 点击 Install 使 Operator 可供 OpenShift Container Platform 集群上的所选命名空间使用。

    1. 如果选择了手动批准策略,订阅的升级状态将保持在 Upgrading 状态,直至您审核并批准安装计划。

      Install Plan 页面批准后,订阅的升级状态将变为 Up to date

    2. 如果选择了 Automatic 批准策略,升级状态会在不用人工参与的情况下变为 Up to date
  7. 在订阅的升级状态成为 Up to date 后,选择 Operators → Installed Operators 来验证已安装 Operator 的 ClusterServiceVersion(CSV)是否最终出现了。状态最终会在相关命名空间中变为 InstallSucceeded

    注意

    对于 All namespaces…​ 安装模式,状态在 openshift-operators 命名空间中解析为 InstallSucceeded,但如果检查其他命名空间,则状态为 Copied

    如果没有:

    1. 检查 openshift-operators 项目(如果选择了 A specific namespace…​ 安装模式)中的 openshift-operators 项目中的 pod 的日志,这会在 Workloads → Pods 页面中报告问题以便进一步排除故障。

3.1.3. 使用 CLI 从 OperatorHub 安装

您可以使用 CLI 从 OperatorHub 安装 Operator,而不必使用 OpenShift Container Platform Web 控制台。使用 oc 命令来创建或更新一个订阅对象。

先决条件

  • 使用具有 Operator 安装权限的账户访问 OpenShift Container Platform 集群。
  • 在您的本地系统安装 oc 命令。

流程

  1. 查看 OperatorHub 中集群可用的 Operator 列表:

    $ oc get packagemanifests -n openshift-marketplace

    输出示例

    NAME                               CATALOG               AGE
    3scale-operator                    Red Hat Operators     91m
    advanced-cluster-management        Red Hat Operators     91m
    amq7-cert-manager                  Red Hat Operators     91m
    ...
    couchbase-enterprise-certified     Certified Operators   91m
    crunchy-postgres-operator          Certified Operators   91m
    mongodb-enterprise                 Certified Operators   91m
    ...
    etcd                               Community Operators   91m
    jaeger                             Community Operators   91m
    kubefed                            Community Operators   91m
    ...

    记录下所需 Operator 的目录。

  2. 检查所需 Operator,以验证其支持的安装模式和可用频道:

    $ oc describe packagemanifests <operator_name> -n openshift-marketplace
  3. 一个 Operator 组(由 OperatorGroup 对象定义),在其中选择目标命名空间,在其中为与 Operator 组相同的命名空间中的所有 Operator 生成所需的 RBAC 访问权限。

    订阅 Operator 的命名空间必须具有与 Operator 的安装模式相匹配的 Operator 组,可采用 AllNamespaces 模式,也可采用 SingleNamespace 模式。如果您要使用 AllNamespaces 安装 Operator,则 openshift-operators 命名空间已有适当的 Operator 组。

    如果要安装的 Operator 采用 SingleNamespace 模式,而您没有适当的 Operator 组,则必须创建一个。

    注意

    在选择 SingleNamespace 模式时,该流程的 Web 控制台版本会在后台自动为您处理 OperatorGroupSubscription 对象的创建。

    1. 创建 OperatorGroup 对象 YAML 文件,如 operatorgroup.yaml

      OperatorGroup 对象示例

      apiVersion: operators.coreos.com/v1
      kind: OperatorGroup
      metadata:
        name: <operatorgroup_name>
        namespace: <namespace>
      spec:
        targetNamespaces:
        - <namespace>

    2. 创建 OperatorGroup 对象:

      $ oc apply -f operatorgroup.yaml
  4. 创建一个 Subscription 对象 YAML 文件,以便为 Operator 订阅一个命名空间,如 sub.yaml

    Subscription 对象示例

    apiVersion: operators.coreos.com/v1alpha1
    kind: Subscription
    metadata:
      name: <subscription_name>
      namespace: openshift-operators 1
    spec:
      channel: <channel_name> 2
      name: <operator_name> 3
      source: redhat-operators 4
      sourceNamespace: openshift-marketplace 5

    1
    对于 AllNamespaces 安装模式的使用,指定 openshift-operators 命名空间。否则,为 SingleNamespace 安装模式使用指定相关单一命名空间。
    2
    要订阅的频道的名称。
    3
    要订阅的 Operator 的名称。
    4
    提供 Operator 的目录源的名称。
    5
    目录源的命名空间。将 openshift-marketplace 用于默认的 OperatorHub 目录源。
  5. 创建 Subscription 对象:

    $ oc apply -f sub.yaml

    此时,OLM 已了解所选的 Operator。Operator 的集群服务版本(CSV)应出现在目标命名空间中,由 Operator 提供的 API 应可用于创建。

其他资源

3.1.4. 安装 Operator 的特定版本

您可以通过在 Subscription 对象中设置集群服务版本(CSV)来安装 Operator 的特定版本。

先决条件

  • 使用具有 Operator 安装权限的账户访问 OpenShift Container Platform 集群
  • 已安装 OpenShift CLI(oc

流程

  1. 通过设置 startingCSV 字段,创建一个 Subscription 对象 YAML 文件,向带有特定版本的 Operator 订阅一个命名空间。将 installPlanApproval 字段设置为 Manual,以便在目录中存在更新的版本时防止 Operator 自动升级。

    例如,可以使用以下 sub.yaml 文件安装 Red Hat Quay Operator,专门用于版本 3.4.0:

    带有特定起始 Operator 版本的订阅

    apiVersion: operators.coreos.com/v1alpha1
    kind: Subscription
    metadata:
      name: quay-operator
      namespace: quay
    spec:
      channel: quay-v3.4
      installPlanApproval: Manual 1
      name: quay-operator
      source: redhat-operators
      sourceNamespace: openshift-marketplace
      startingCSV: quay-operator.v3.4.0 2

    1
    如果您指定的版本会被目录中的更新版本取代,则将批准策略设置为 Manual。此计划阻止自动升级到更新的版本,且需要在启动 CSV 可以完成安装前手动批准。
    2
    设置 Operator CSV 的特定版本。
  2. 创建 Subscription 对象:

    $ oc apply -f sub.yaml
  3. 手动批准待处理的安装计划以完成 Operator 安装。

3.2. 升级安装的 Operator

作为集群管理员,您可以升级以前使用 OpenShift Container Platform 集群上的 Operator Lifecycle Manager(OLM)安装的 Operator。

3.2.1. 更改 Operator 的更新频道

已安装的 Operator 的订阅指定一个更新频道,用于跟踪和接收 Operator 的更新。要升级 Operator 以开始跟踪并从更新频道接受更新,您可以更改订阅中的更新频道。

Subscription 中更新频道的名称可能会因 Operator 而异,但应遵守给定 Operator 中的常见约定。一些命名方案包括:

  • 4.34.44.5
  • stable-4.3, stable-4.4, stable-4.5
  • alphabetastablelatest

另外,频道名称可能会跟随 Operator 提供的应用程序的版本号。

注意

安装的 Operator 无法变为比当前频道旧的频道。

如果订阅中的批准策略被设置为 Automatic,则升级过程会在所选频道中提供新的 Operator 版本时立即启动。如果批准策略设为 Manual,则必须手动批准待处理的升级。

先决条件

  • 之前使用 Operator Lifecycle Manager(OLM)安装的 Operator。

流程

  1. 在 OpenShift Container Platform Web 控制台的 Administrator 视角中,进入 Operators → Installed Operators
  2. 点击您要更改更新频道的 Operator 名称。
  3. Subscription 标签页。
  4. Channel 中的更新频道的名称。
  5. 点要更改的更新频道,然后点 Save
  6. 对于带有 自动批准策略 的订阅,升级会自动开始。返回 Operators → Installed Operators 页面来监控升级的过程。完成后,状态会变为 SucceededUp to date

    对于采用手动批准策略的订阅,您可以使用 Subscription 选项卡手动批准升级。

3.2.2. 手动批准待处理的 Operator 升级

如果已安装的 Operator 的订阅被设置为 Manual,则当其当前更新频道中发布新更新时,在开始安装前必须手动批准更新。

先决条件

  • 之前使用 Operator Lifecycle Manager(OLM)安装的 Operator。

流程

  1. 在 OpenShift Container Platform Web 控制台的 Administrator 视角中,进入 Operators → Installed Operators
  2. 处于待定升级的 Operator 会显示 Upgrade available 状态。点您要升级的 Operator 的名称。
  3. Subscription 标签页。任何需要批准的升级都会在 Upgrade Status 旁边显示。例如:它可能会显示 1 requires approval
  4. 1 requires approval,然后点 Preview Install Plan
  5. 查看列出可用于升级的资源。在满意后,点 Approve
  6. 返回 Operators → Installed Operators 页面来监控升级的过程。完成后,状态会变为 SucceededUp to date

3.3. 从集群中删除 Operator

下面介绍如何删除以前使用 OpenShift Container Platform 集群上的 Operator Lifecycle Manager(OLM)安装的 Operator。

3.3.1. 使用 Web 控制台从集群中删除 Operator

集群管理员可以使用 Web 控制台从所选命名空间中删除已安装的 Operator。

先决条件

  • 使用具有 cluster-admin 权限的账户访问 OpenShift Container Platform 集群 Web 控制台。

流程

  1. 进入 OperatorsInstalled Operators 页面,在 Filter by name 字段滚动鼠标或键入关键词,以查找您想要的 Operator。然后点击。
  2. Operator Details 页面右侧,从 Actions 下拉菜单中选择 Uninstall Operator

    此时会显示 Uninstall Operator? 对话框,提醒您:

    删除 Operator 不会移除任何自定义资源定义或受管资源。如果 Operator 在集群中部署了应用程序,或者配置了非集群资源,则这些应用程序将继续运行,需要手动清理。

    此操作移除了 Operator、任何 Operator 部署和 pod。由 Operator 管理的任何资源(包括 CRD 和 CR)都不会被删除。Web 控制台为一些 Operator 启用仪表板和导航项。要在卸载 Operator 后删除这些,您可能需要手动删除 Operator CRD。

  3. 选择 Uninstall。此 Operator 将停止运行,并且不再接收更新。

3.3.2. 使用 CLI 从集群中删除 Operator

集群管理员可以使用 CLI 从所选命名空间中删除已安装的 Operator。

先决条件

  • 使用具有 cluster-admin 权限的账户访问 OpenShift Container Platform 集群。
  • 已在工作站上安装 oc 命令。

流程

  1. 通过 currentCSV 字段检查已订阅 Operator 的当前版本(如 jaeger):

    $ oc get subscription jaeger -n openshift-operators -o yaml | grep currentCSV

    输出示例

      currentCSV: jaeger-operator.v1.8.2

  2. 删除订阅(如 jaeger):

    $ oc delete subscription jaeger -n openshift-operators

    输出示例

    subscription.operators.coreos.com "jaeger" deleted

  3. 使用上一步中的 currentCSV 值来删除目标命名空间中相应 Operator 的 CSV:

    $ oc delete clusterserviceversion jaeger-operator.v1.8.2 -n openshift-operators

    输出示例

    clusterserviceversion.operators.coreos.com "jaeger-operator.v1.8.2" deleted

3.4. 在 Operator Lifecycle Manager 中配置代理支持

如果在 OpenShift Container Platform 集群中配置了全局代理,Operator Lifecycle Manager(OLM)会自动配置使用集群范围代理管理的 Operator。但是,您也可以配置已安装的 Operator 来覆盖全局代理服务器或注入自定义 CA 证书。

其他资源

3.4.1. 覆盖 Operator 的代理设置

如果配置了集群范围的出口代理,使用 Operator Lifecycle Manager(OLM)运行的 Operator 会继承其部署上的集群范围代理设置。集群管理员还可以通过配置 Operator 的订阅来覆盖这些代理设置。

重要

操作员必须为任何受管 Operands 处理 pod 中的代理设置环境变量。

先决条件

  • 使用具有 cluster-admin 权限的账户访问 OpenShift Container Platform 集群。

流程

  1. 在 Web 控制台中导航至 Operators → OperatorHub 页面。
  2. 选择 Operator 并点 Install
  3. Install Operator 页面中,修改 Subscription 对象,使其在 spec 部分中包含一个或多个以下环境变量:

    • HTTP_PROXY
    • HTTPS_PROXY
    • NO_PROXY

    例如:

    带有代理设置的Subscription 对象覆盖

    apiVersion: operators.coreos.com/v1alpha1
    kind: Subscription
    metadata:
      name: etcd-config-test
      namespace: openshift-operators
    spec:
      config:
        env:
        - name: HTTP_PROXY
          value: test_http
        - name: HTTPS_PROXY
          value: test_https
        - name: NO_PROXY
          value: test
      channel: clusterwide-alpha
      installPlanApproval: Automatic
      name: etcd
      source: community-operators
      sourceNamespace: openshift-marketplace
      startingCSV: etcdoperator.v0.9.4-clusterwide

    注意

    这些环境变量也可以使用空值取消设置,以删除所有之前设定的集群范围或自定义代理设置。

    OLM 将这些环境变量作为一个单元处理; 如果至少设置了一个环境变量,则所有 3 个变量都将被视为覆盖,并且集群范围的默认值不会用于订阅的 Operator 部署。

  4. 点击 Install 使 Operator 可供所选命名空间使用。
  5. 当 Operator 的 CSV 出现在相关命名空间中后,您可以验证部署中是否设置了自定义代理环境变量。例如,使用 CLI:

    $ oc get deployment -n openshift-operators \
        etcd-operator -o yaml \
        | grep -i "PROXY" -A 2

    输出示例

            - name: HTTP_PROXY
              value: test_http
            - name: HTTPS_PROXY
              value: test_https
            - name: NO_PROXY
              value: test
            image: quay.io/coreos/etcd-operator@sha256:66a37fd61a06a43969854ee6d3e21088a98b93838e284a6086b13917f96b0d9c
    ...

3.4.2. 注入自定义 CA 证书

当集群管理员使用配置映射向集群添加自定义 CA 证书时,Cluster Network Operator 会将用户提供的证书和系统 CA 证书合并为一个捆绑包(bundle)。您可以将这个合并捆绑包注入 Operator Lifecycle Manager (OLM) 上运行的 Operator 中,如果您有一个中间人(man-in-the-middle)HTTPS 代理,这将会有用。

先决条件

  • 使用具有 cluster-admin 权限的账户访问 OpenShift Container Platform 集群。
  • 使用配置映射添加自定义 CA 证书至集群。
  • 在 OLM 上安装并运行所需的 Operator。

流程

  1. 在存在 Operator 订阅的命名空间中创建一个空配置映射,并包括以下标签:

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: trusted-ca 1
      labels:
        config.openshift.io/inject-trusted-cabundle: "true" 2
    1
    配置映射的名称。
    2
    请求 Cluster Network Operator 注入合并的捆绑包。

    创建此配置映射后,它会立即使用合并捆绑包的证书内容填充。

  2. 更新您的 Subscription 对象,使其包含 spec.config 部分,该部分可将 trusted-ca 配置映射作为卷挂载到需要自定义 CA 的 pod 中的每个容器:

    kind: Subscription
    metadata:
      name: my-operator
    spec:
      package: etcd
      channel: alpha
      config: 1
      - selector:
          matchLabels:
            <labels_for_pods> 2
        volumes: 3
        - name: trusted-ca
          configMap:
            name: trusted-ca
            items:
              - key: ca-bundle.crt 4
                path: tls-ca-bundle.pem 5
        volumeMounts: 6
        - name: trusted-ca
          mountPath: /etc/pki/ca-trust/extracted/pem
          readOnly: true
    1
    如果不存在,请添加 config 部分。
    2
    指定标签以匹配 Operator 拥有的 pod。
    3
    创建一个 trusted-ca 卷。
    4
    ca-bundle.crt 需要作为配置映射键。
    5
    tls-ca-bundle.pem 需要作为配置映射路径。
    6
    创建一个 trusted-ca 卷挂载。

3.5. 查看 Operator 状态

了解 Operator Lifecycle Manager (OLM) 中的系统状态,对于决定和调试已安装 Operator 的问题来说非常重要。OLM 可让您了解订阅和相关目录源的状态以及执行的操作。这样有助于用户更好地理解 Operator 的运行状况。

3.5.1. operator 订阅状况类型

订阅可报告以下状况类型:

表 3.1. 订阅状况类型

状况描述

CatalogSourcesUnhealthy

用于解析的一个或多个目录源不健康。

InstallPlanMissing

缺少订阅的安装计划。

InstallPlanPending

订阅的安装计划正在安装中。

InstallPlanFailed

订阅的安装计划失败。

注意

默认 OpenShift Container Platform 集群 Operator 由 Cluster Version Operator(CVO)管理,它们没有 Subscription 对象。应用程序 Operator 由 Operator Lifecycle Manager(OLM)管理,它们具有 Subscription 对象。

3.5.2. 使用 CLI 查看 Operator 订阅状态

您可以使用 CLI 查看 Operator 订阅状态。

先决条件

  • 您可以使用具有 cluster-admin 角色的用户访问集群。
  • 已安装 OpenShift CLI(oc)。

流程

  1. 列出 Operator 订阅:

    $ oc get subs -n <operator_namespace>
  2. 使用 oc describe 命令检查 Subscription 资源:

    $ oc describe sub <subscription_name> -n <operator_namespace>
  3. 在命令输出中,找到 Operator 订阅状况类型的 Conditions 部分。在以下示例中,CatalogSourcesUnhealthy 条件类型具有 false 状态,因为所有可用目录源都健康:

    输出示例

    Conditions:
       Last Transition Time:  2019-07-29T13:42:57Z
       Message:               all available catalogsources are healthy
       Reason:                AllCatalogSourcesHealthy
       Status:                False
       Type:                  CatalogSourcesUnhealthy

注意

默认 OpenShift Container Platform 集群 Operator 由 Cluster Version Operator(CVO)管理,它们没有 Subscription 对象。应用程序 Operator 由 Operator Lifecycle Manager(OLM)管理,它们具有 Subscription 对象。

3.6. 允许非集群管理员安装 Operator

Operator 可能需要广泛权限才可运行,且不同版本需要的权限也可能不同。Operator Lifecycle Manager (OLM) 需要 cluster-admin 权限才可运行。默认情况下,Operator 作者可在集群服务版本(CSV)中指定任意权限集,OLM 之后会将其授予 Operator。

集群管理员应采取措施,确保 Operator 无法获得全集群权限,且用户不可使用 OLM 来提升权限。要实现这一目的的一种方法要求集群管理员在将 Operator 添加至集群之前先对其进行审核。集群管理员还可获得一些工具来决定和限制在使用服务账户安装或升级 Operator 期间允许的操作。

通过将 Operator 组与获得一组权限的服务账户相关联,集群管理员便可对 Operator 设定策略,以确保它们仅在预先决定的边界范围内按照 RBAC 规则运行。Operator 无法执行任何这些规则未明确允许的操作。

非集群管理员可自行安装 Operator 但范围有限,这一规定意味着更多 Operator Framework 工具可安全提供给更多用户,为通过 Operator 构建应用程序提供更丰富的体验。

3.6.1. 了解 Operator 安装策略

通过使用 OLM,集群管理员可选择为一个 OperatorGroup 指定一个服务账户,以便部署与这个 Operator 组相关联的所有 Operator,并按照服务账户获得的权限运行。

APIServiceCustomResourceDefinition 资源都由 OLM 使用 cluster-admin 角色来创建。不应向与 Operator 组相关联的服务账户授予写入这些资源的权限。

如果指定的服务账户对于正在安装或升级的 Operator 没有足够权限,则会在相应资源状态中添加实用背景信息,以便集群管理员轻松排除故障并解决问题。

与该 Operator 组相关联的所有 Operator 现已被限制在指定服务账户获得的权限范围内。如果 Operator 请求了超出服务账户范围的权限,安装将会失败,并将显示相应错误。

3.6.1.1. 安装场景

在确定是否可在集群上安装或升级 Operator 时,Operator Lifecycle Manager(OLM)会考虑以下情况:

  • 集群管理员新建了一个 Operator 组并指定了服务账户。已安装与该 Operator 组关联的所有 Operator,并根据相应服务账户获得的权限运行。
  • 集群管理员新建了一个 Operator 组,且不指定任何服务帐户。OpenShift Container Platform 保持向后兼容性,因此会保留默认行为,并允许安装和升级 Operator。
  • 对于未指定服务账户的现有 Operator 组,会保留默认行为,并允许安装和升级 Operator。
  • 集群管理员更新了现有 Operator 组并指定了服务帐户。OLM 支持现有 Operator 继续根据当前权限运行。现有 Operator 升级后,它会重新安装并根据相应服务账户获得的权限运行,与新 Operator 一样。
  • 由 Operator 组指定的服务帐户通过添加或删除权限来更改,或者现有服务账户被换为新服务帐户。现有 Operator 升级后,它会重新安装并根据更新后的服务账户获得的权限运行,与新 Operator 一样。
  • 集群管理员从 Operator 组中删除服务账户。默认行为保留,并允许安装和升级 Operator。

3.6.1.2. 安装工作流

当 Operator 组与服务账户绑定,并且安装或升级了 Operator 时,Operator Lifecycle Manager(OLM)会使用以下工作流:

  1. OLM 会提取给定订阅对象。
  2. OLM 获取与该订阅相关联的 Operator 组。
  3. OLM 确定 Operator 组是否指定了服务帐户。
  4. OLM 在服务账户范围内创建一个客户端,并使用该范围内客户端来安装 Operator。这样可确保 Operator 请求的任何权限始终限制在 Operator 组中服务账户的权限范围内。
  5. OLM 新建一个服务账户,在 CSV 中指定其权限集,并将其分配至 Operator。Operator 将根据所分配的服务账户运行。

3.6.2. 限定 Operator 安装范围

要为 Operator Lifecycle Manager(OLM)上的 Operator 安装和升级提供范围规则,请将服务帐户与 Operator 组关联。

集群管理员可借鉴本例,将一组 Operator 限制到指定命名空间中。

流程

  1. 新建命名空间:

    $ cat <<EOF | oc create -f -
    apiVersion: v1
    kind: Namespace
    metadata:
      name: scoped
    EOF
  2. 分配 Operator 的权限范围。这涉及创建新服务帐户、相关角色和角色绑定。

    $ cat <<EOF | oc create -f -
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: scoped
      namespace: scoped
    EOF

    为简便起见,以下示例授予服务账户在指定命名空间进行任何操作的权限。在生产环境中,应创建更为精细的权限集:

    $ cat <<EOF | oc create -f -
    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      name: scoped
      namespace: scoped
    rules:
    - apiGroups: ["*"]
      resources: ["*"]
      verbs: ["*"]
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: scoped-bindings
      namespace: scoped
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: Role
      name: scoped
    subjects:
    - kind: ServiceAccount
      name: scoped
      namespace: scoped
    EOF
  3. 在指定的命名空间中创建 OperatorGroup 对象。该 Operator 组以指定的命名空间为目标,以确保其租期仅限于该命名空间。

    另外,Operator 组允许用户指定服务帐户。指定上一步中创建的服务帐户:

    $ cat <<EOF | oc create -f -
    apiVersion: operators.coreos.com/v1
    kind: OperatorGroup
    metadata:
      name: scoped
      namespace: scoped
    spec:
      serviceAccountName: scoped
      targetNamespaces:
      - scoped
    EOF

    在指定命名空间中安装的任何 Operator 均会关联至此 Operator 组,因此也会关联到指定的服务账户。

  4. 在指定命名空间中创建 Subscription 对象以安装 Operator:

    $ cat <<EOF | oc create -f -
    apiVersion: operators.coreos.com/v1alpha1
    kind: Subscription
    metadata:
      name: etcd
      namespace: scoped
    spec:
      channel: singlenamespace-alpha
      name: etcd
      source: <catalog_source_name> 1
      sourceNamespace: <catalog_source_namespace> 2
    EOF
    1
    指定已存在于指定命名空间中或位于全局目录命名空间中的目录源。
    2
    指定创建目录源的命名空间。

    与该 Operator 组相关联的所有 Operator 都仅限于为指定服务账户授予的权限。如果 Operator 请求的权限超出服务账户范围,安装会失败并显示相关错误。

3.6.2.1. 细粒度权限

Operator Lifecycle Manager(OLM)使用 Operator 组中指定的服务账户来创建或更新与正在安装的 Operator 相关的以下资源:

  • ClusterServiceVersion
  • Subscription
  • Secret
  • ServiceAccount
  • Service
  • ClusterRoleClusterRoleBinding
  • RoleRoleBinding

要将 Operator 限制到指定命名空间,集群管理员可以首先向服务账户授予以下权限:

注意

以下角色只是一个通用示例,具体 Operator 可能需要额外规则。

kind: Role
rules:
- apiGroups: ["operators.coreos.com"]
  resources: ["subscriptions", "clusterserviceversions"]
  verbs: ["get", "create", "update", "patch"]
- apiGroups: [""]
  resources: ["services", "serviceaccounts"]
  verbs: ["get", "create", "update", "patch"]
- apiGroups: ["rbac.authorization.k8s.io"]
  resources: ["roles", "rolebindings"]
  verbs: ["get", "create", "update", "patch"]
- apiGroups: ["apps"] 1
  resources: ["deployments"]
  verbs: ["list", "watch", "get", "create", "update", "patch", "delete"]
- apiGroups: [""] 2
  resources: ["pods"]
  verbs: ["list", "watch", "get", "create", "update", "patch", "delete"]
1 2
增加创建其他资源的权限,如此处显示的部署和 pod。

另外,如果任何 Operator 指定了 pull secret,还必须增加以下权限:

kind: ClusterRole 1
rules:
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["get"]
---
kind: Role
rules:
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["create", "update", "patch"]
1
需要从 OLM 命名空间中获取 secret。

3.6.3. 故障排除权限失败

如果因为缺少权限而导致 Operator 安装失败,请按照以下流程找出错误。

流程

  1. 查看 Subscription 对象。其状态中有一个指向 InstallPlan 对象的对象引用 installPlanRef,该对象试图为 Operator 创建需要的 [Cluster]Role[Binding]

    apiVersion: operators.coreos.com/v1
    kind: Subscription
    metadata:
      name: etcd
      namespace: scoped
    status:
      installPlanRef:
        apiVersion: operators.coreos.com/v1
        kind: InstallPlan
        name: install-4plp8
        namespace: scoped
        resourceVersion: "117359"
        uid: 2c1df80e-afea-11e9-bce3-5254009c9c23
  2. 检查 InstallPlan 对象的状态中的任何错误:

    apiVersion: operators.coreos.com/v1
    kind: InstallPlan
    status:
      conditions:
      - lastTransitionTime: "2019-07-26T21:13:10Z"
        lastUpdateTime: "2019-07-26T21:13:10Z"
        message: 'error creating clusterrole etcdoperator.v0.9.4-clusterwide-dsfx4: clusterroles.rbac.authorization.k8s.io
          is forbidden: User "system:serviceaccount:scoped:scoped" cannot create resource
          "clusterroles" in API group "rbac.authorization.k8s.io" at the cluster scope'
        reason: InstallComponentFailed
        status: "False"
        type: Installed
      phase: Failed

    错误信息中会显示:

    • 创建失败的资源类型,包括资源的 API 组。本例中为 rbac.authorization.k8s.io 组中的 clusterroles
    • 资源名称。
    • 错误类型:is forbidden 表明相应用户没有足够权限来执行这一操作。
    • 试图创建或更新资源的用户名称。本例中指的是 Operator 组中指定的服务账户。
    • 操作范围:集群范围内或范围外。

      用户可在服务账户中增加所缺权限,然后迭代操作。

      注意

      Operator Lifecycle Manager(OLM)目前未提供第一次尝试的完整错误列表。

3.7. 管理自定义目录

本指南介绍了如何在 OpenShift Container Platform 的 Operator Lifecycle Manager (OLM) 中处理以 Package Manifest Format 或 Bundle Format 打包的自定义目录。

3.7.1. 使用 Package Manifest Format 的自定义目录

3.7.1.1. 了解 Operator 目录镜像

Operator Lifecycle Manager (OLM) 始终从 Operator 目录的最新版本安装 Operator。对于 OpenShift Container Platform 4.5,红帽提供的 Operator 通过 quay.io 中的 Quay App Registry 目录发布。

表 3.2. 红帽提供的 App Registry 目录

Catalog描述

redhat-operators

提供由红帽打包并提供的红帽产品的公共目录。受红帽支持。

certified-operators

提供来自主要独立软件供应商(ISV)的产品的公共目录。红帽与 ISV 合作打包并提供。受 ISV 支持。

community-operators

提供由 operator-framework/community-operators GitHub 存储库中相关代表维护的软件的公共目录。无官方支持。

随着目录的更新,Operator 的最新版本会发生变化,旧版本可能会被删除或修改。此行为可能会导致长时间维护可重复生成的安装时出现问题。另外,当 OLM 在受限网络环境中的 OpenShift Container Platform 集群上运行时,它无法直接从 quay.io 访问目录。

使用 oc adm catalog build 命令,集群管理员可创建 Operator 目录镜像。Operator 目录镜像为:

  • App Registry 类型目录内容的时间点导出。
  • 将 App Registry 目录转换为容器镜像类型目录的结果。
  • 不可变工件。

通过创建 Operator 目录镜像,可以在不发生上述问题的情况下简单地使用此内容。

3.7.1.2. 构建 Operator 目录镜像

集群管理员可以根据 Operator Lifecycle Manager(OLM)使用的 Package Manifest Format 来构建自定义 Operator 目录镜像。目录镜像可推送到支持 Docker v2-2 的容器镜像 registry。对于受限网络中的集群,此 registry 可以是集群有网络访问权限的 registry,如在受限网络集群安装过程中创建的镜像 registry。

重要

OpenShift Container Platform 集群的内部 registry 不能用作目标 registry,因为它不支持没有标签的推送(在镜像过程中需要这个功能)。

在这一示例中,流程假定在使用镜像 registry 时可访问您的网络以及互联网。

注意

只有 oc 客户端的 Linux 版本可用于此流程,因为 Windows 和 macOS 版本不提供 oc adm catalog build 命令。

先决条件

  • 没有网络访问限制的工作站
  • oc 版本 4.3.5+ Linux 客户端
  • podman 1.4.4+ 版
  • 访问支持 Docker v2-2 的镜像(mirror)registry
  • 如果您正在使用私有 registry,请将 REG_CREDS 环境变量设置为到 registry 凭证的文件路径。例如,对于 podman CLI:

    $ REG_CREDS=${XDG_RUNTIME_DIR}/containers/auth.json
  • 如果您正在使用 quay.io 帐户可访问的私有命名空间,您必须设置 Quay 身份验证令牌。使用您的 quay.io 凭证对登录 API 发出请求,从而设置用于 --auth-token 标志的 AUTH_TOKEN 环境变量:

    $ AUTH_TOKEN=$(curl -sH "Content-Type: application/json" \
        -XPOST https://quay.io/cnr/api/v1/users/login -d '
        {
            "user": {
                "username": "'"<quay_username>"'",
                "password": "'"<quay_password>"'"
            }
        }' | jq -r '.token')

流程

  1. 在没有网络访问限制的工作站中,与目标镜像(mirror) registry 进行身份验证:

    $ podman login <registry_host_name>

    还可使用 registry.redhat.io 验证,以便在构建期间拉取基础镜像:

    $ podman login registry.redhat.io
  2. 根据 Quay.io 中的 redhat-operators 目录构建目录镜像,进行标记并将其推送到您的镜像 registry:

    $ oc adm catalog build \
        --appregistry-org redhat-operators \1
        --from=registry.redhat.io/openshift4/ose-operator-registry:v4.5 \2
        --filter-by-os="linux/amd64" \3
        --to=<registry_host_name>:<port>/olm/redhat-operators:v1 \4
        [-a ${REG_CREDS}] \5
        [--insecure] \6
        [--auth-token "${AUTH_TOKEN}"] 7
    1
    从 App Registry 实例中拉取的机构(命名空间)。
    2
    使用与目标 OpenShift Container Platform 集群主版本和次版本匹配的标签,将 --from 设置为 ose-operator-registry 基础镜像。
    3
    --filter-by-os 设置为用于基本镜像的操作系统和架构,该镜像必须与目标 OpenShift Container Platform 集群匹配。有效值是 linux/amd64linux/ppc64lelinux/s390x
    4
    为您的目录镜像命名并包含标签,例如: v1
    5
    可选:如果需要,指定 registry 凭证文件的位置。
    6
    可选:如果您不想为目标 registry 配置信任,请添加 --insecure 标志。
    7
    可选:如果使用其他不公开的应用程序 registry 目录,则需要指定 Quay 身份验证令牌。

    输出示例

    INFO[0013] loading Bundles                               dir=/var/folders/st/9cskxqs53ll3wdn434vw4cd80000gn/T/300666084/manifests-829192605
    ...
    Pushed sha256:f73d42950021f9240389f99ddc5b0c7f1b533c054ba344654ff1edaf6bf827e3 to example_registry:5000/olm/redhat-operators:v1

    有时红帽提供的无效清单是意外引入的目录 ; 当发生这种情况时,您可能会看到一些错误:

    出错的输出示例

    ...
    INFO[0014] directory                                     dir=/var/folders/st/9cskxqs53ll3wdn434vw4cd80000gn/T/300666084/manifests-829192605 file=4.2 load=package
    W1114 19:42:37.876180   34665 builder.go:141] error building database: error loading package into db: fuse-camel-k-operator.v7.5.0 specifies replacement that couldn't be found
    Uploading ... 244.9kB/s

    这些错误通常不是致命的,如果所提及 Operator 软件包不包含您计划安装的 Operator 或其依赖项,则可以忽略它们。

3.7.1.3. 构建 Operator 目录的镜像

集群管理员可将其目录的内容通过镜像方式放入 registry 中,并使用 CatalogSource 将内容加载到 OpenShift Container Platform 集群。本例中的流程使用之前构建并推送到受支持的 registry 的自定义 redhat-operators 目录镜像。

先决条件

  • 没有网络访问限制的工作站
  • 推送到受支持的 registry 的自定义 Operator 目录镜像
  • oc 版本 4.3.5+
  • podman 1.4.4+ 版
  • 访问支持 Docker v2-2 的镜像(mirror)registry
  • 如果您正在使用私有 registry,请将 REG_CREDS 环境变量设置为到 registry 凭证的文件路径。例如,对于 podman CLI:

    $ REG_CREDS=${XDG_RUNTIME_DIR}/containers/auth.json

流程

  1. oc adm catalog mirror 命令提取自定义 Operator catalog 镜像的内容,以生成镜像(mirror)所需的清单:您可以选择:

    • 允许该命令的默认行为在生成清单后自动将所有镜像内容镜像到您的镜像 registry 中,或者
    • 添加 --manifests-only 标志来只生成镜像所需的清单,但并不实际将镜像内容镜像到 registry。这对检查哪些要镜像(mirror)非常有用。如果您只需要部分内容的话,可以对映射列表做出任何修改。然后,您可以使用该文件与 oc image mirror 命令一起,在以后的步骤中镜像修改的镜像列表。

    在没有网络访问限制的工作站中,运行以下命令:

    $ oc adm catalog mirror \
        <registry_host_name>:<port>/olm/redhat-operators:v1 \1
        <registry_host_name>:<port> \
        [-a ${REG_CREDS}] \2
        [--insecure] \3
        --filter-by-os='.*' \4
        [--manifests-only] 5
    1
    指定 Operator 目录镜像。
    2
    可选:如果需要,指定 registry 凭证文件的位置。
    3
    可选:如果您不想为目标 registry 配置信任,请添加 --insecure 标志。
    4
    由于对多个构架支持的已知问题,当前需要此标志。
    5
    可选:只生成镜像所需的清单,但并不实际将镜像内容镜像到 registry。
    警告

    如果未设置 --filter-by-os 标志或设置为 .* 以外的任何值,该命令会过滤不同的架构,用来更改清单列表摘要,也称为 多架构镜像。不正确的摘要会导致在断开连接的集群中部署这些镜像和 Operator 失败。如需更多信息,请参阅 BZ#1890951

    输出示例

    using database path mapping: /:/tmp/190214037
    wrote database to /tmp/190214037
    using database at: /tmp/190214037/bundles.db 1
    ...

    1
    命令生成的临时数据库。

    在运行命令后,会在当前目录中生成 <image_name>-manifests/ 目录以及以下文件:

    • 用来定义 ImageContentSourcePolicy 对象的 imageContentSourcePolicy.yaml,它可以将节点配置为在 Operator 清单中存储的镜像(image)引用和镜像 (mirror) 的 registry 间进行转换。
    • mapping.txt 文件,在其中包含所有源镜像,并将它们映射到目标 registry。此文件与 oc image mirror 命令兼容,可用于进一步自定义镜像(mirror)配置。
  2. 如果您在上一步中使用 --manifests-only 标志,并只想镜像部分内容:

    1. mapping.txt 文件中的镜像列表改为您的规格。如果您不确定要镜像的镜像子集的名称和版本,请使用以下步骤查找:

      1. oc adm catalog mirror 命令生成的临时数据库运行 sqlite3 工具,以检索与一般搜索查询匹配的镜像列表。输出以后如何编辑 mapping.txt 文件的帮助信息。

        例如,要检索与字符串 clusterlogging.4.3 类似的镜像列表:

        $ echo "select * from related_image \
            where operatorbundle_name like 'clusterlogging.4.3%';" \
            | sqlite3 -line /tmp/190214037/bundles.db 1
        1
        请参阅 oc adm catalog mirror 命令的输出结果来查找数据库文件的路径。

        输出示例

        image = registry.redhat.io/openshift4/ose-logging-kibana5@sha256:aa4a8b2a00836d0e28aa6497ad90a3c116f135f382d8211e3c55f34fb36dfe61
        operatorbundle_name = clusterlogging.4.3.33-202008111029.p0
        
        image = registry.redhat.io/openshift4/ose-oauth-proxy@sha256:6b4db07f6e6c962fc96473d86c44532c93b146bbefe311d0c348117bf759c506
        operatorbundle_name = clusterlogging.4.3.33-202008111029.p0
        ...

      2. 使用上一步的结果来编辑 mapping.txt 文件,使其只包含您要镜像的镜像子集。

        例如,您可以使用前面示例输出中的 image 值来找出您的 mapping.txt 文件中存在以下匹配行:

        mapping.txt 中的匹配镜像映射

        registry.redhat.io/openshift4/ose-logging-kibana5@sha256:aa4a8b2a00836d0e28aa6497ad90a3c116f135f382d8211e3c55f34fb36dfe61=<registry_host_name>:<port>/openshift4-ose-logging-kibana5:a767c8f0
        registry.redhat.io/openshift4/ose-oauth-proxy@sha256:6b4db07f6e6c962fc96473d86c44532c93b146bbefe311d0c348117bf759c506=<registry_host_name>:<port>/openshift4-ose-oauth-proxy:3754ea2b

        在这个示例中,如果您只想镜像这些 image,可以在 mapping.txt 文件中删除所有其他条目,仅保留上述两行。

    2. 在您的没有网络访问限制的工作站中,使用您修改的 mapping.txt 文件,使用 oc image mirror 命令将镜像镜像到 registry:

      $ oc image mirror \
          [-a ${REG_CREDS}] \
          --filter-by-os='.*' \
          -f ./redhat-operators-manifests/mapping.txt
      警告

      如果未设置 --filter-by-os 标志或设置为 .* 以外的任何值,该命令会过滤不同的架构,用来更改清单列表摘要,也称为 多架构镜像。不正确的摘要会导致在断开连接的集群中部署这些镜像和 Operator 失败。

  3. 应用 ImageContentSourcePolicy 对象:

    $ oc apply -f ./redhat-operators-manifests/imageContentSourcePolicy.yaml
  4. 创建一个 CatalogSource 对象来引用您的目录镜像。

    1. 按照您的规格修改以下内容,并将它保存为 catalogsource.yaml 文件:

      apiVersion: operators.coreos.com/v1alpha1
      kind: CatalogSource
      metadata:
        name: my-operator-catalog
        namespace: openshift-marketplace
      spec:
        sourceType: grpc
        image: <registry_host_name>:<port>/olm/redhat-operators:v1 1
        displayName: My Operator Catalog
        publisher: grpc
      1
      指定您的自定义 Operator 目录镜像。
    2. 使用该文件创建 CatalogSource 对象:

      $ oc create -f catalogsource.yaml
  5. 确定成功创建以下资源。

    1. 检查 pod:

      $ oc get pods -n openshift-marketplace

      输出示例

      NAME                                    READY   STATUS    RESTARTS  AGE
      my-operator-catalog-6njx6               1/1     Running   0         28s
      marketplace-operator-d9f549946-96sgr    1/1     Running   0         26h

    2. 检查目录源:

      $ oc get catalogsource -n openshift-marketplace

      输出示例

      NAME                  DISPLAY               TYPE PUBLISHER  AGE
      my-operator-catalog   My Operator Catalog   grpc            5s

    3. 检查软件包清单:

      $ oc get packagemanifest -n openshift-marketplace

      输出示例

      NAME    CATALOG              AGE
      etcd    My Operator Catalog  34s

现在,您可在受限网络 OpenShift Container Platform 集群的 web 控制台中,通过 OperatorHub 安装 Operator。

3.7.1.4. 更新 Operator 目录镜像

集群管理员将 OperatorHub 配置为使用自定义 Operator 目录镜像后,管理员可通过红帽提供的 App Registry 目录获得更新,使其 OpenShift Container Platform 集群与最新的 Operator 保持一致。这可以通过构建和推送新的 Operator 目录镜像,然后将 CatalogSource 对象中现有的 spec.image 参数替换为新镜像摘要。

在本例中,该流程假设已配置了自定义 redhat-operators 目录镜像,以便与 OperatorHub 搭配使用。

注意

只有 oc 客户端的 Linux 版本可用于此流程,因为 Windows 和 macOS 版本不提供 oc adm catalog build 命令。

先决条件

  • 没有网络访问限制的工作站
  • oc 版本 4.3.5+ Linux 客户端
  • podman 1.4.4+ 版
  • 访问支持 Docker v2-2 的镜像(mirror)registry
  • OperatorHub 配置为使用自定义目录镜像
  • 如果您正在使用私有 registry,请将 REG_CREDS 环境变量设置为到 registry 凭证的文件路径。例如,对于 podman CLI:

    $ REG_CREDS=${XDG_RUNTIME_DIR}/containers/auth.json
  • 如果您正在使用 quay.io 帐户可访问的私有命名空间,您必须设置 Quay 身份验证令牌。使用您的 quay.io 凭证对登录 API 发出请求,从而设置用于 --auth-token 标志的 AUTH_TOKEN 环境变量:

    $ AUTH_TOKEN=$(curl -sH "Content-Type: application/json" \
        -XPOST https://quay.io/cnr/api/v1/users/login -d '
        {
            "user": {
                "username": "'"<quay_username>"'",
                "password": "'"<quay_password>"'"
            }
        }' | jq -r '.token')

流程

  1. 在没有网络访问限制的工作站中,与目标镜像(mirror) registry 进行身份验证:

    $ podman login <registry_host_name>

    还可使用 registry.redhat.io 验证,以便在构建期间拉取基础镜像:

    $ podman login registry.redhat.io
  2. 根据 Quay.io 中的 redhat-operators 目录构建新目录镜像,标记并将其推送到您的镜像 registry:

    $ oc adm catalog build \
        --appregistry-org redhat-operators \1
        --from=registry.redhat.io/openshift4/ose-operator-registry:v4.5 \2
        --filter-by-os="linux/amd64" \3
        --to=<registry_host_name>:<port>/olm/redhat-operators:v2 \4
        [-a ${REG_CREDS}] \5
        [--insecure] \6
        [--auth-token "${AUTH_TOKEN}"] 7
    1
    从 App Registry 实例中拉取的机构(命名空间)。
    2
    使用与目标 OpenShift Container Platform 集群主版本和次版本匹配的标签,将 --from 设置为 ose-operator-registry 基础镜像。
    3
    --filter-by-os 设置为用于基本镜像的操作系统和架构,该镜像必须与目标 OpenShift Container Platform 集群匹配。有效值是 linux/amd64linux/ppc64lelinux/s390x
    4
    为您的目录镜像命名并包含一个标签,例如: v2 ,因为它是更新的目录。
    5
    可选:如果需要,指定 registry 凭证文件的位置。
    6
    可选:如果您不想为目标 registry 配置信任,请添加 --insecure 标志。
    7
    可选:如果使用其他不公开的应用程序 registry 目录,则需要指定 Quay 身份验证令牌。

    输出示例

    INFO[0013] loading Bundles                               dir=/var/folders/st/9cskxqs53ll3wdn434vw4cd80000gn/T/300666084/manifests-829192605
    ...
    Pushed sha256:f73d42950021f9240389f99ddc5b0c7f1b533c054ba344654ff1edaf6bf827e3 to example_registry:5000/olm/redhat-operators:v2

  3. 将目录镜像 (mirror) 到目标 registry。以下 oc adm catalog mirror 命令提取自定义 Operator catalog 镜像的内容,以生成镜像 (mirror) 和把镜像(image)镜像 (mirror)到 registry 所需的清单:

    $ oc adm catalog mirror \
        <registry_host_name>:<port>/olm/redhat-operators:v2 \1
        <registry_host_name>:<port> \
        [-a ${REG_CREDS}] \2
        [--insecure] \3
        --filter-by-os='.*' 4
    1
    指定新 Operator 目录镜像。
    2
    可选:如果需要,指定 registry 凭证文件的位置。
    3
    可选:如果您不想为目标 registry 配置信任,请添加 --insecure 标志。
    4
    由于对多个构架支持的已知问题,当前需要此标志。如果未设置 --filter-by-os 标志或设置为 .* 以外的任何值,该命令会过滤不同的架构,用来更改清单列表摘要,也称为 多架构镜像。不正确的摘要会导致在断开连接的集群中部署这些镜像和 Operator 失败。如需更多信息,请参阅 BZ#1890951
  4. 应用新生成的清单:

    $ oc apply -f ./redhat-operators-manifests
    重要

    您可能不需要应用 imageContentSourcePolicy.yaml 清单。对文件进行一个 diff 操作来决定是否需要改变。

  5. 更新 CatalogSource 对象以引用您的目录镜像。

    1. 如果您有此 CatalogSource 对象的原始 catalogsource.yaml 文件:

      1. 编辑 catalogsource.yaml 文件,在 spec.image 字段中引用新目录镜像 :

        apiVersion: operators.coreos.com/v1alpha1
        kind: CatalogSource
        metadata:
          name: my-operator-catalog
          namespace: openshift-marketplace
        spec:
          sourceType: grpc
          image: <registry_host_name>:<port>/olm/redhat-operators:v2 1
          displayName: My Operator Catalog
          publisher: grpc
        1
        指定新 Operator 目录镜像。
      2. 使用更新的文件替换 CatalogSource 对象:

        $ oc replace -f catalogsource.yaml
    2. 或者,使用以下命令编辑目录源,在 spec.image 参数中引用您的新目录镜像 :

      $ oc edit catalogsource <catalog_source_name> -n openshift-marketplace

现在,OpenShift Container Platform 集群上的 OperatorHub 页中应可以提供更新的 Operator。

3.7.1.5. 测试 Operator 目录镜像。

要验证 Operator 目录镜像内容,您可以将其作为容器运行并查询其 gRPC API。要进一步测试镜像,您可以通过引用 CatalogSource 对象中的镜像来解析 OLM 订阅。本例中的流程使用之前构建并推送到受支持的 registry 的自定义 redhat-operators 目录镜像。

先决条件

  • 推送到受支持的 registry 的自定义 Operator 目录镜像
  • podman 1.4.4+ 版
  • oc 版本 4.3.5+
  • 访问支持 Docker v2-2 的镜像(mirror)registry
  • grpcurl

流程

  1. 拉取 Operator 目录镜像:

    $ podman pull <registry_host_name>:<port>/olm/redhat-operators:v1
  2. 运行镜像:

    $ podman run -p 50051:50051 \
        -it <registry_host_name>:<port>/olm/redhat-operators:v1
  3. 使用 grpcurl 查询正在运行的镜像中的可用软件包:

    $ grpcurl -plaintext localhost:50051 api.Registry/ListPackages

    输出示例

    {
      "name": "3scale-operator"
    }
    {
      "name": "amq-broker"
    }
    {
      "name": "amq-online"
    }

  4. 在频道中获取最新的 Operator 捆绑包:

    $  grpcurl -plaintext -d '{"pkgName":"kiali-ossm","channelName":"stable"}' localhost:50051 api.Registry/GetBundleForChannel

    输出示例

    {
      "csvName": "kiali-operator.v1.0.7",
      "packageName": "kiali-ossm",
      "channelName": "stable",
    ...

  5. 获取镜像摘要:

    $ podman inspect \
        --format='{{index .RepoDigests 0}}' \
        <registry_host_name>:<port>/olm/redhat-operators:v1

    输出示例

    example_registry:5000/olm/redhat-operators@sha256:f73d42950021f9240389f99ddc5b0c7f1b533c054ba344654ff1edaf6bf827e3

  6. 假设命名空间 my-ns 中存在一个支持您的 Operator 及其依赖项的 Operator 组,使用镜像摘要创建一个 CatalogSource 对象。例如:

    apiVersion: operators.coreos.com/v1alpha1
    kind: CatalogSource
    metadata:
      name: custom-redhat-operators
      namespace: my-ns
    spec:
      sourceType: grpc
      image: example_registry:5000/olm/redhat-operators@sha256:f73d42950021f9240389f99ddc5b0c7f1b533c054ba344654ff1edaf6bf827e3
      displayName: Red Hat Operators
  7. 创建一个可从您的目录镜像解析最新可用 servicemeshoperator 及其依赖项的订阅:

    apiVersion: operators.coreos.com/v1alpha1
    kind: Subscription
    metadata:
      name: servicemeshoperator
      namespace: my-ns
    spec:
      source: custom-redhat-operators
      sourceNamespace: my-ns
      name: servicemeshoperator
      channel: "1.0"

3.7.2. 使用 Bundle Format 的自定义目录

3.7.2.1. opm CLI

新的 opm CLI 工具与新的 Bundle Format 一起引入。您可以通过一个名为 index 的捆绑包列表,创建和维护 Operator 目录,它相当于“存储库”。其结果是名为 index image 的容器镜像,它可以存储在容器 registry 中,然后安装到集群中。

索引包含一个指向 Operator 清单内容的指针数据库,可通过在运行容器镜像时提供的已包含 API 进行查询。在 OpenShift Container Platform 中,OLM 可通过引用 CatalogSource 中的索引镜像作为目录(catalog),它会定期轮询镜像,以对集群上安装的 Operator 进行更新。

其他资源

3.7.2.2. 安装 opm

您可在工作站上安装 opm CLI 工具。

先决条件

  • podman 1.4.4+ 版

流程

  1. 请将 REG_CREDS 环境变量设置为 registry 凭证的文件路径,以便之后的步骤中使用。例如,对于 podman CLI:

    $ REG_CREDS=${XDG_RUNTIME_DIR}/containers/auth.json
  2. 通过 registry.redhat.io 进行身份验证:

    $ podman login registry.redhat.io
  3. 从 Operator Registry 镜像中提取 opm 二进制文件并将其复制到本地文件系统:

    $ oc image extract registry.redhat.io/openshift4/ose-operator-registry:v4.5 \
        -a ${REG_CREDS} \1
        --path /usr/bin/opm:. \
        --confirm
    1
    指定 registry 凭证文件的位置。
  4. 使二进制文件可执行:

    $ chmod +x ./opm
  5. 将文件放在PATH中的任何位置,例如/usr/local/bin/

    $ sudo mv ./opm /usr/local/bin/
  6. 验证是否已正确安装客户端:

    $ opm version

    输出示例

    Version: version.Version{OpmVersion:"1.12.3", GitCommit:"", BuildDate:"2020-07-01T23:18:58Z", GoOs:"linux", GoArch:"amd64"}

3.7.2.3. 创建索引镜像

您可以使用 opm CLI 创建索引镜像。

先决条件

  • opm 版本 1.12.3+
  • podman 1.4.4+ 版
  • 构建并推送到 registry 的捆绑包镜像。

流程

  1. 启动一个新的索引:

    $ opm index add \
        --bundles quay.io/<namespace>/test-operator:v0.1.0 \1
        --tag quay.io/<namespace>/test-catalog:latest \2
        [--binary-image <registry_base_image>] 3
    1
    要添加到索引中的捆绑包镜像以逗号分隔的列表。
    2
    希望索引镜像具有的镜像标签。
    3
    可选:用于为目录提供服务的备选 registry 基础镜像。
  2. 将索引镜像推送到 registry:

    $ podman push quay.io/<namespace>/test-catalog:latest

3.7.2.4. 从索引镜像创建目录

您可以从索引镜像创建目录,并将其应用到 OpenShift Container Platform 集群。

先决条件

  • 构建并推送到 registry 的索引镜像。

流程

  1. CatalogSource 对象应用到集群以引用索引镜像:

    $ cat <<EOF | oc apply -f -
    
    apiVersion: operators.coreos.com/v1alpha1
    kind: CatalogSource
    metadata:
      name: test-catalog
      namespace: openshift-marketplace
    spec:
      sourceType: grpc
      image: quay.io/<namespace>/test-catalog:latest 1
      displayName: Test Catalog
      updateStrategy:
        registryPoll: 2
          interval: 30m
    EOF
    1
    指定索引镜像。
    2
    目录源可以自动检查新版本以保持最新。
  2. 使用 OpenShift Container Platform Web 控制台或 CLI 来验证目录是否已成功加载并且软件包可用。例如,使用 CLI:

    1. 检查 pod:

      $ oc get pods -n openshift-marketplace
    2. 检查目录源:

      $ oc get catalogsource -n openshift-marketplace
    3. 检查软件包清单:

      $ oc get packagemanifests -n openshift-marketplace

3.7.2.5. 更新索引镜像

您可以使用 opm CLI 更新现有索引镜像。

先决条件

  • opm 版本 1.12.3+
  • podman 1.4.4+ 版
  • 构建并推送到 registry 的索引镜像。
  • 创建并应用到集群的 CatalogSource 对象。

流程

  1. 更新现有索引:

    $ opm index add \
        --bundles quay.io/<namespace>/another-operator:v1 \1
        --from-index quay.io/<namespace>/test-catalog:latest \2
        --tag quay.io/<namespace>/test-catalog:latest 3
    1
    要添加到索引的额外捆绑包镜像。
    2
    之前推送的现有索引。
    3
    您想让更新的索引镜像具有的镜像标签。
  2. 推送更新的索引镜像:

    $ podman push quay.io/<namespace>/test-catalog:latest
  3. Operator Lifecycle Manager(OLM)定期轮询索引镜像后,验证是否已成功添加新软件包:

    $ oc get packagemanifests -n openshift-marketplace

3.8. 在受限网络中使用 Operator Lifecycle Manager

对于在受限网络中安装的 OpenShift Container Platform 集群(也称为断开连接的集群),Operator Lifecycle Manager(OLM)默认无法访问 Quay.io 上托管的红帽提供的 OperatorHub 源,因为这些远程源需要足够的互联网连接。

但是,作为集群管理员,如果您有一个有完全互联网访问的工作站,则仍可以让集群在受限网络中使用 OLM。该工作站用于将远程 OperatorHub 源在本地进行一个镜像,它需要可以通过互联网来拉取远程内容。

本指南描述了在受限网络中启用 OLM 所需的流程:

  • 为 OLM 禁用默认远程 OperatorHub 源。
  • 使用有完全互联网访问的工作站来创建 OperatorHub 内容的本地镜像。
  • 将 OLM 配置为,从本地源而不是默认的远程源安装和管理 Operator。

在受限网络中启用 OLM 后,您可以继续使用不受限制的工作站在发布新版 Operator 时保持本地 OperatorHub 源的更新。

重要

虽然 OLM 可以从本地源管理 Operator,但给定 Operator 在受限网络中能否成功运行仍取决于 Operator 本身。Operator 必须:

  • ClusterServiceVersion (CSV) 对象的 relatedImages参数中列出所有相关的镜像,或 Operator 执行时可能需要的其他容器镜像。
  • 通过摘要 (SHA) 而不是标签来引用所有指定的镜像。

如需了解在断开连接的模式模中可以运行的 Operator 列表,请参阅以下红帽知识库文章:

https://access.redhat.com/articles/4740011

3.8.1. 了解 Operator 目录镜像

Operator Lifecycle Manager (OLM) 始终从 Operator 目录的最新版本安装 Operator。对于 OpenShift Container Platform 4.5,红帽提供的 Operator 通过 quay.io 中的 Quay App Registry 目录发布。

表 3.3. 红帽提供的 App Registry 目录

Catalog描述

redhat-operators

提供由红帽打包并提供的红帽产品的公共目录。受红帽支持。

certified-operators

提供来自主要独立软件供应商(ISV)的产品的公共目录。红帽与 ISV 合作打包并提供。受 ISV 支持。

community-operators

提供由 operator-framework/community-operators GitHub 存储库中相关代表维护的软件的公共目录。无官方支持。

随着目录的更新,Operator 的最新版本会发生变化,旧版本可能会被删除或修改。此行为可能会导致长时间维护可重复生成的安装时出现问题。另外,当 OLM 在受限网络环境中的 OpenShift Container Platform 集群上运行时,它无法直接从 quay.io 访问目录。

使用 oc adm catalog build 命令,集群管理员可创建 Operator 目录镜像。Operator 目录镜像为:

  • App Registry 类型目录内容的时间点导出。
  • 将 App Registry 目录转换为容器镜像类型目录的结果。
  • 不可变工件。

通过创建 Operator 目录镜像,可以在不发生上述问题的情况下简单地使用此内容。

3.8.2. 构建 Operator 目录镜像

集群管理员可以根据 Operator Lifecycle Manager(OLM)使用的 Package Manifest Format 来构建自定义 Operator 目录镜像。目录镜像可推送到支持 Docker v2-2 的容器镜像 registry。对于受限网络中的集群,此 registry 可以是集群有网络访问权限的 registry,如在受限网络集群安装过程中创建的镜像 registry。

重要

OpenShift Container Platform 集群的内部 registry 不能用作目标 registry,因为它不支持没有标签的推送(在镜像过程中需要这个功能)。

在这一示例中,流程假定在使用镜像 registry 时可访问您的网络以及互联网。

注意

只有 oc 客户端的 Linux 版本可用于此流程,因为 Windows 和 macOS 版本不提供 oc adm catalog build 命令。

先决条件

  • 没有网络访问限制的工作站
  • oc 版本 4.3.5+ Linux 客户端
  • podman 1.4.4+ 版
  • 访问支持 Docker v2-2 的镜像(mirror)registry
  • 如果您正在使用私有 registry,请将 REG_CREDS 环境变量设置为到 registry 凭证的文件路径。例如,对于 podman CLI:

    $ REG_CREDS=${XDG_RUNTIME_DIR}/containers/auth.json
  • 如果您正在使用 quay.io 帐户可访问的私有命名空间,您必须设置 Quay 身份验证令牌。使用您的 quay.io 凭证对登录 API 发出请求,从而设置用于 --auth-token 标志的 AUTH_TOKEN 环境变量:

    $ AUTH_TOKEN=$(curl -sH "Content-Type: application/json" \
        -XPOST https://quay.io/cnr/api/v1/users/login -d '
        {
            "user": {
                "username": "'"<quay_username>"'",
                "password": "'"<quay_password>"'"
            }
        }' | jq -r '.token')

流程

  1. 在没有网络访问限制的工作站中,与目标镜像(mirror) registry 进行身份验证:

    $ podman login <registry_host_name>

    还可使用 registry.redhat.io 验证,以便在构建期间拉取基础镜像:

    $ podman login registry.redhat.io
  2. 根据 Quay.io 中的 redhat-operators 目录构建目录镜像,进行标记并将其推送到您的镜像 registry:

    $ oc adm catalog build \
        --appregistry-org redhat-operators \1
        --from=registry.redhat.io/openshift4/ose-operator-registry:v4.5 \2
        --filter-by-os="linux/amd64" \3
        --to=<registry_host_name>:<port>/olm/redhat-operators:v1 \4
        [-a ${REG_CREDS}] \5
        [--insecure] \6
        [--auth-token "${AUTH_TOKEN}"] 7
    1
    从 App Registry 实例中拉取的机构(命名空间)。
    2
    使用与目标 OpenShift Container Platform 集群主版本和次版本匹配的标签,将 --from 设置为 ose-operator-registry 基础镜像。
    3
    --filter-by-os 设置为用于基本镜像的操作系统和架构,该镜像必须与目标 OpenShift Container Platform 集群匹配。有效值是 linux/amd64linux/ppc64lelinux/s390x
    4
    为您的目录镜像命名并包含标签,例如: v1
    5
    可选:如果需要,指定 registry 凭证文件的位置。
    6
    可选:如果您不想为目标 registry 配置信任,请添加 --insecure 标志。
    7
    可选:如果使用其他不公开的应用程序 registry 目录,则需要指定 Quay 身份验证令牌。

    输出示例

    INFO[0013] loading Bundles                               dir=/var/folders/st/9cskxqs53ll3wdn434vw4cd80000gn/T/300666084/manifests-829192605
    ...
    Pushed sha256:f73d42950021f9240389f99ddc5b0c7f1b533c054ba344654ff1edaf6bf827e3 to example_registry:5000/olm/redhat-operators:v1

    有时红帽提供的无效清单是意外引入的目录 ; 当发生这种情况时,您可能会看到一些错误:

    出错的输出示例

    ...
    INFO[0014] directory                                     dir=/var/folders/st/9cskxqs53ll3wdn434vw4cd80000gn/T/300666084/manifests-829192605 file=4.2 load=package
    W1114 19:42:37.876180   34665 builder.go:141] error building database: error loading package into db: fuse-camel-k-operator.v7.5.0 specifies replacement that couldn't be found
    Uploading ... 244.9kB/s

    这些错误通常不是致命的,如果所提及 Operator 软件包不包含您计划安装的 Operator 或其依赖项,则可以忽略它们。

3.8.3. 针对受限网络配置 OperatorHub

集群管理员可以使用自定义 Operator 目录镜像将 OLM 和 OperatorHub 配置为在受限网络环境中使用本地内容。本例中的流程使用之前构建并推送到受支持的 registry 的自定义 redhat-operators 目录镜像。

先决条件

  • 没有网络访问限制的工作站
  • 推送到受支持的 registry 的自定义 Operator 目录镜像
  • oc 版本 4.3.5+
  • podman 1.4.4+ 版
  • 访问支持 Docker v2-2 的镜像(mirror)registry
  • 如果您正在使用私有 registry,请将 REG_CREDS 环境变量设置为到 registry 凭证的文件路径。例如,对于 podman CLI:

    $ REG_CREDS=${XDG_RUNTIME_DIR}/containers/auth.json

流程

  1. 通过在 spec 中添加 disableAllDefaultSources: true 来禁用默认 OperatorSource 对象:

    $ oc patch OperatorHub cluster --type json \
        -p '[{"op": "add", "path": "/spec/disableAllDefaultSources", "value": true}]'

    这禁用了在 OpenShift Container Platform 安装期间默认配置的默认源。

  2. oc adm catalog mirror 命令提取自定义 Operator catalog 镜像的内容,以生成镜像(mirror)所需的清单:您可以选择:

    • 允许该命令的默认行为在生成清单后自动将所有镜像内容镜像到您的镜像 registry 中,或者
    • 添加 --manifests-only 标志来只生成镜像所需的清单,但并不实际将镜像内容镜像到 registry。这对检查哪些要镜像(mirror)非常有用。如果您只需要部分内容的话,可以对映射列表做出任何修改。然后,您可以使用该文件与 oc image mirror 命令一起,在以后的步骤中镜像修改的镜像列表。

    在没有网络访问限制的工作站中,运行以下命令:

    $ oc adm catalog mirror \
        <registry_host_name>:<port>/olm/redhat-operators:v1 \1
        <registry_host_name>:<port> \
        [-a ${REG_CREDS}] \2
        [--insecure] \3
        --filter-by-os='.*' \4
        [--manifests-only] 5
    1
    指定 Operator 目录镜像。
    2
    可选:如果需要,指定 registry 凭证文件的位置。
    3
    可选:如果您不想为目标 registry 配置信任,请添加 --insecure 标志。
    4
    由于对多个构架支持的已知问题,当前需要此标志。
    5
    可选:只生成镜像所需的清单,但并不实际将镜像内容镜像到 registry。
    警告

    如果未设置 --filter-by-os 标志或设置为 .* 以外的任何值,该命令会过滤不同的架构,用来更改清单列表摘要,也称为 多架构镜像。不正确的摘要会导致在断开连接的集群中部署这些镜像和 Operator 失败。如需更多信息,请参阅 BZ#1890951

    输出示例

    using database path mapping: /:/tmp/190214037
    wrote database to /tmp/190214037
    using database at: /tmp/190214037/bundles.db 1
    ...

    1
    命令生成的临时数据库。

    在运行命令后,会在当前目录中生成 <image_name>-manifests/ 目录以及以下文件:

    • 用来定义 ImageContentSourcePolicy 对象的 imageContentSourcePolicy.yaml,它可以将节点配置为在 Operator 清单中存储的镜像(image)引用和镜像 (mirror) 的 registry 间进行转换。
    • mapping.txt 文件,在其中包含所有源镜像,并将它们映射到目标 registry。此文件与 oc image mirror 命令兼容,可用于进一步自定义镜像(mirror)配置。
  3. 如果您在上一步中使用 --manifests-only 标志,并只想镜像部分内容:

    1. mapping.txt 文件中的镜像列表改为您的规格。如果您不确定要镜像的镜像子集的名称和版本,请使用以下步骤查找:

      1. oc adm catalog mirror 命令生成的临时数据库运行 sqlite3 工具,以检索与一般搜索查询匹配的镜像列表。输出以后如何编辑 mapping.txt 文件的帮助信息。

        例如,要检索与字符串 clusterlogging.4.3 类似的镜像列表:

        $ echo "select * from related_image \
            where operatorbundle_name like 'clusterlogging.4.3%';" \
            | sqlite3 -line /tmp/190214037/bundles.db 1
        1
        请参阅 oc adm catalog mirror 命令的输出结果来查找数据库文件的路径。

        输出示例

        image = registry.redhat.io/openshift4/ose-logging-kibana5@sha256:aa4a8b2a00836d0e28aa6497ad90a3c116f135f382d8211e3c55f34fb36dfe61
        operatorbundle_name = clusterlogging.4.3.33-202008111029.p0
        
        image = registry.redhat.io/openshift4/ose-oauth-proxy@sha256:6b4db07f6e6c962fc96473d86c44532c93b146bbefe311d0c348117bf759c506
        operatorbundle_name = clusterlogging.4.3.33-202008111029.p0
        ...

      2. 使用上一步的结果来编辑 mapping.txt 文件,使其只包含您要镜像的镜像子集。

        例如,您可以使用前面示例输出中的 image 值来找出您的 mapping.txt 文件中存在以下匹配行:

        mapping.txt 中的匹配镜像映射

        registry.redhat.io/openshift4/ose-logging-kibana5@sha256:aa4a8b2a00836d0e28aa6497ad90a3c116f135f382d8211e3c55f34fb36dfe61=<registry_host_name>:<port>/openshift4-ose-logging-kibana5:a767c8f0
        registry.redhat.io/openshift4/ose-oauth-proxy@sha256:6b4db07f6e6c962fc96473d86c44532c93b146bbefe311d0c348117bf759c506=<registry_host_name>:<port>/openshift4-ose-oauth-proxy:3754ea2b

        在这个示例中,如果您只想镜像这些 image,可以在 mapping.txt 文件中删除所有其他条目,仅保留上述两行。

    2. 在您的没有网络访问限制的工作站中,使用您修改的 mapping.txt 文件,使用 oc image mirror 命令将镜像镜像到 registry:

      $ oc image mirror \
          [-a ${REG_CREDS}] \
          --filter-by-os='.*' \
          -f ./redhat-operators-manifests/mapping.txt
      警告

      如果未设置 --filter-by-os 标志或设置为 .* 以外的任何值,该命令会过滤不同的架构,用来更改清单列表摘要,也称为 多架构镜像。不正确的摘要会导致在断开连接的集群中部署这些镜像和 Operator 失败。

  4. 应用 ImageContentSourcePolicy 对象:

    $ oc apply -f ./redhat-operators-manifests/imageContentSourcePolicy.yaml
  5. 创建一个 CatalogSource 对象来引用您的目录镜像。

    1. 按照您的规格修改以下内容,并将它保存为 catalogsource.yaml 文件:

      apiVersion: operators.coreos.com/v1alpha1
      kind: CatalogSource
      metadata:
        name: my-operator-catalog
        namespace: openshift-marketplace
      spec:
        sourceType: grpc
        image: <registry_host_name>:<port>/olm/redhat-operators:v1 1
        displayName: My Operator Catalog
        publisher: grpc
      1
      指定您的自定义 Operator 目录镜像。
    2. 使用该文件创建 CatalogSource 对象:

      $ oc create -f catalogsource.yaml
  6. 确定成功创建以下资源。

    1. 检查 pod:

      $ oc get pods -n openshift-marketplace

      输出示例

      NAME                                    READY   STATUS    RESTARTS  AGE
      my-operator-catalog-6njx6               1/1     Running   0         28s
      marketplace-operator-d9f549946-96sgr    1/1     Running   0         26h

    2. 检查目录源:

      $ oc get catalogsource -n openshift-marketplace

      输出示例

      NAME                  DISPLAY               TYPE PUBLISHER  AGE
      my-operator-catalog   My Operator Catalog   grpc            5s

    3. 检查软件包清单:

      $ oc get packagemanifest -n openshift-marketplace

      输出示例

      NAME    CATALOG              AGE
      etcd    My Operator Catalog  34s

现在,您可在受限网络 OpenShift Container Platform 集群的 web 控制台中,通过 OperatorHub 安装 Operator。

3.8.4. 更新 Operator 目录镜像

集群管理员将 OperatorHub 配置为使用自定义 Operator 目录镜像后,管理员可通过红帽提供的 App Registry 目录获得更新,使其 OpenShift Container Platform 集群与最新的 Operator 保持一致。这可以通过构建和推送新的 Operator 目录镜像,然后将 CatalogSource 对象中现有的 spec.image 参数替换为新镜像摘要。

在本例中,该流程假设已配置了自定义 redhat-operators 目录镜像,以便与 OperatorHub 搭配使用。

注意

只有 oc 客户端的 Linux 版本可用于此流程,因为 Windows 和 macOS 版本不提供 oc adm catalog build 命令。

先决条件

  • 没有网络访问限制的工作站
  • oc 版本 4.3.5+ Linux 客户端
  • podman 1.4.4+ 版
  • 访问支持 Docker v2-2 的镜像(mirror)registry
  • OperatorHub 配置为使用自定义目录镜像
  • 如果您正在使用私有 registry,请将 REG_CREDS 环境变量设置为到 registry 凭证的文件路径。例如,对于 podman CLI:

    $ REG_CREDS=${XDG_RUNTIME_DIR}/containers/auth.json
  • 如果您正在使用 quay.io 帐户可访问的私有命名空间,您必须设置 Quay 身份验证令牌。使用您的 quay.io 凭证对登录 API 发出请求,从而设置用于 --auth-token 标志的 AUTH_TOKEN 环境变量:

    $ AUTH_TOKEN=$(curl -sH "Content-Type: application/json" \
        -XPOST https://quay.io/cnr/api/v1/users/login -d '
        {
            "user": {
                "username": "'"<quay_username>"'",
                "password": "'"<quay_password>"'"
            }
        }' | jq -r '.token')

流程

  1. 在没有网络访问限制的工作站中,与目标镜像(mirror) registry 进行身份验证:

    $ podman login <registry_host_name>

    还可使用 registry.redhat.io 验证,以便在构建期间拉取基础镜像:

    $ podman login registry.redhat.io
  2. 根据 Quay.io 中的 redhat-operators 目录构建新目录镜像,标记并将其推送到您的镜像 registry:

    $ oc adm catalog build \
        --appregistry-org redhat-operators \1
        --from=registry.redhat.io/openshift4/ose-operator-registry:v4.5 \2
        --filter-by-os="linux/amd64" \3
        --to=<registry_host_name>:<port>/olm/redhat-operators:v2 \4
        [-a ${REG_CREDS}] \5
        [--insecure] \6
        [--auth-token "${AUTH_TOKEN}"] 7
    1
    从 App Registry 实例中拉取的机构(命名空间)。
    2
    使用与目标 OpenShift Container Platform 集群主版本和次版本匹配的标签,将 --from 设置为 ose-operator-registry 基础镜像。
    3
    --filter-by-os 设置为用于基本镜像的操作系统和架构,该镜像必须与目标 OpenShift Container Platform 集群匹配。有效值是 linux/amd64linux/ppc64lelinux/s390x
    4
    为您的目录镜像命名并包含一个标签,例如: v2 ,因为它是更新的目录。
    5
    可选:如果需要,指定 registry 凭证文件的位置。
    6
    可选:如果您不想为目标 registry 配置信任,请添加 --insecure 标志。
    7
    可选:如果使用其他不公开的应用程序 registry 目录,则需要指定 Quay 身份验证令牌。

    输出示例

    INFO[0013] loading Bundles                               dir=/var/folders/st/9cskxqs53ll3wdn434vw4cd80000gn/T/300666084/manifests-829192605
    ...
    Pushed sha256:f73d42950021f9240389f99ddc5b0c7f1b533c054ba344654ff1edaf6bf827e3 to example_registry:5000/olm/redhat-operators:v2

  3. 将目录镜像 (mirror) 到目标 registry。以下 oc adm catalog mirror 命令提取自定义 Operator catalog 镜像的内容,以生成镜像 (mirror) 和把镜像(image)镜像 (mirror)到 registry 所需的清单:

    $ oc adm catalog mirror \
        <registry_host_name>:<port>/olm/redhat-operators:v2 \1
        <registry_host_name>:<port> \
        [-a ${REG_CREDS}] \2
        [--insecure] \3
        --filter-by-os='.*' 4
    1
    指定新 Operator 目录镜像。
    2
    可选:如果需要,指定 registry 凭证文件的位置。
    3
    可选:如果您不想为目标 registry 配置信任,请添加 --insecure 标志。
    4
    由于对多个构架支持的已知问题,当前需要此标志。如果未设置 --filter-by-os 标志或设置为 .* 以外的任何值,该命令会过滤不同的架构,用来更改清单列表摘要,也称为 多架构镜像。不正确的摘要会导致在断开连接的集群中部署这些镜像和 Operator 失败。如需更多信息,请参阅 BZ#1890951
  4. 应用新生成的清单:

    $ oc apply -f ./redhat-operators-manifests
    重要

    您可能不需要应用 imageContentSourcePolicy.yaml 清单。对文件进行一个 diff 操作来决定是否需要改变。

  5. 更新 CatalogSource 对象以引用您的目录镜像。

    1. 如果您有此 CatalogSource 对象的原始 catalogsource.yaml 文件:

      1. 编辑 catalogsource.yaml 文件,在 spec.image 字段中引用新目录镜像 :

        apiVersion: operators.coreos.com/v1alpha1
        kind: CatalogSource
        metadata:
          name: my-operator-catalog
          namespace: openshift-marketplace
        spec:
          sourceType: grpc
          image: <registry_host_name>:<port>/olm/redhat-operators:v2 1
          displayName: My Operator Catalog
          publisher: grpc
        1
        指定新 Operator 目录镜像。
      2. 使用更新的文件替换 CatalogSource 对象:

        $ oc replace -f catalogsource.yaml
    2. 或者,使用以下命令编辑目录源,在 spec.image 参数中引用您的新目录镜像 :

      $ oc edit catalogsource <catalog_source_name> -n openshift-marketplace

现在,OpenShift Container Platform 集群上的 OperatorHub 页中应可以提供更新的 Operator。

3.8.5. 测试 Operator 目录镜像。

要验证 Operator 目录镜像内容,您可以将其作为容器运行并查询其 gRPC API。要进一步测试镜像,您可以通过引用 CatalogSource 对象中的镜像来解析 OLM 订阅。本例中的流程使用之前构建并推送到受支持的 registry 的自定义 redhat-operators 目录镜像。

先决条件

  • 推送到受支持的 registry 的自定义 Operator 目录镜像
  • podman 1.4.4+ 版
  • oc 版本 4.3.5+
  • 访问支持 Docker v2-2 的镜像(mirror)registry
  • grpcurl

流程

  1. 拉取 Operator 目录镜像:

    $ podman pull <registry_host_name>:<port>/olm/redhat-operators:v1
  2. 运行镜像:

    $ podman run -p 50051:50051 \
        -it <registry_host_name>:<port>/olm/redhat-operators:v1
  3. 使用 grpcurl 查询正在运行的镜像中的可用软件包:

    $ grpcurl -plaintext localhost:50051 api.Registry/ListPackages

    输出示例

    {
      "name": "3scale-operator"
    }
    {
      "name": "amq-broker"
    }
    {
      "name": "amq-online"
    }

  4. 在频道中获取最新的 Operator 捆绑包:

    $  grpcurl -plaintext -d '{"pkgName":"kiali-ossm","channelName":"stable"}' localhost:50051 api.Registry/GetBundleForChannel

    输出示例

    {
      "csvName": "kiali-operator.v1.0.7",
      "packageName": "kiali-ossm",
      "channelName": "stable",
    ...

  5. 获取镜像摘要:

    $ podman inspect \
        --format='{{index .RepoDigests 0}}' \
        <registry_host_name>:<port>/olm/redhat-operators:v1

    输出示例

    example_registry:5000/olm/redhat-operators@sha256:f73d42950021f9240389f99ddc5b0c7f1b533c054ba344654ff1edaf6bf827e3

  6. 假设命名空间 my-ns 中存在一个支持您的 Operator 及其依赖项的 Operator 组,使用镜像摘要创建一个 CatalogSource 对象。例如:

    apiVersion: operators.coreos.com/v1alpha1
    kind: CatalogSource
    metadata:
      name: custom-redhat-operators
      namespace: my-ns
    spec:
      sourceType: grpc
      image: example_registry:5000/olm/redhat-operators@sha256:f73d42950021f9240389f99ddc5b0c7f1b533c054ba344654ff1edaf6bf827e3
      displayName: Red Hat Operators
  7. 创建一个可从您的目录镜像解析最新可用 servicemeshoperator 及其依赖项的订阅:

    apiVersion: operators.coreos.com/v1alpha1
    kind: Subscription
    metadata:
      name: servicemeshoperator
      namespace: my-ns
    spec:
      source: custom-redhat-operators
      sourceNamespace: my-ns
      name: servicemeshoperator
      channel: "1.0"

第 4 章 开发 Operator

4.1. Operator SDK 入门

本指南将介绍 Operator SDK 的基础知识,指导可作为集群管理员访问基于 Kubernetes 的集群(如 OpenShift Container Platform)的 Operator 作者构建简单 Go-based Memcached Operator 的示例,并管理从安装到升级的整个生命周期。

通过以下两个 Operator Framework 核心组件便可实现这一目的:Operator SDK(operator-sdk CLI 工具和 controller-runtime 库 API)以及 Operator Lifecycle Manager (OLM)。

注意

OpenShift Container Platform 4.5 支持 Operator SDK v0.17.2。

4.1.1. Operator SDK 构架

Operator Framework 是一个开源工具包,用于以有效、自动化且可扩展的方式管理 Kubernetes 原生应用程序,即 Operator。Operator 利用 Kubernetes 的可扩展性来展现云服务的自动化优势,如置备、扩展以及备份和恢复,同时能够在 Kubernetes 可运行的任何地方运行。

Operator 有助于简化对 Kubernetes 上的复杂、有状态的应用程序的管理。然而,现在编写 Operator 并不容易,会面临一些挑战,如使用低级别 API、编写样板文件以及缺乏模块化功能(这会导致重复工作)。

Operator SDK 是一个框架,通过提供以下内容来降低 Operator 的编写难度:

  • 高级 API 和抽象,用于更直观地编写操作逻辑
  • 支架和代码生成工具,用于快速引导新项目
  • 扩展项,覆盖常见的 Operator 用例

4.1.1.1. 工作流

Operator SDK 提供以下工作流来开发新的 Operator:

  1. 使用 Operator SDK 命令行界面 (CLI) 新建一个 Operator 项目。
  2. 通过添加自定义资源定义 (CRD) 来定义新的资源 API。
  3. 使用 Operator SDK API 来指定要监视的资源。
  4. 在指定的处理程序中定义 Operator 协调逻辑,并使用 Operator SDK API 与资源交互。
  5. 使用 Operator SDK CLI 来构建和生成 Operator 部署清单。

图 4.1. Operator SDK 工作流

osdk workflow

在高级别上,使用了 Operator SDK 的 Operator 会在 Operator 作者定义的处理程序中处理与被监视资源相关的事件,并采取措施协调应用程序的状态。

4.1.1.2. 管理器文件

Operator 的主要程序为 cmd/manager/main.go 中的管理器文件。管理器会自动注册 pkg/apis/ 下定义的所有自定义资源(CR)的方案,并运行 pkg/controller/ 下的所有控制器。

管理器可限制所有控制器监视资源的命名空间:

mgr, err := manager.New(cfg, manager.Options{Namespace: namespace})

默认情况下,这是 Operator 运行时所处的命名空间。要监视所有命名空间,把命名空间选项设为空:

mgr, err := manager.New(cfg, manager.Options{Namespace: ""})

4.1.1.3. Prometheus Operator 支持

Prometheus 是一个开源系统监视和警报工具包。Prometheus Operator 会创建、配置和管理在基于 Kubernetes 的集群(如 OpenShift Container Platform)中运行的 Prometheus 集群。

默认情况下,Operator SDK 中包括帮助函数,用于在任何生成的 Go-based Operator 中自动设置指标,以便在部署了 Prometheus Operator 的集群上使用。

4.1.2. 安装 Operator SDK CLI

Operator SDK 配有一个 CLI 工具,可协助开发人员创建、构建和部署新的 Operator 项目。您可在工作站上安装 SDK CLI,为编写您自己的 Operator 做准备。

注意

本指南中,minikube v0.25.0+ 用作本地 Kubernetes 集群,Quay.io 用于公共 registry。

4.1.2.1. 从 GitHub 版本安装

您可以从 GitHub 上的项目下载并安装 Operator SDK CLI 的预构建发行版二进制文件。

先决条件

  • Go v1.13+
  • docker v17.03+、podman v1.2.0+ 或 buildah v1.7+
  • 已安装 OpenShift CLI (oc) v4.5+
  • 访问基于 Kubernetes v1.12.0+ 的集群
  • 访问容器 registry

流程

  1. 设置发行版本变量:

    $ RELEASE_VERSION=v0.17.2
  2. 下载发行版二进制文件。

    • Linux:

      $ curl -OJL https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu
    • macOS:

      $ curl -OJL https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin
  3. 验证所下载的发行版本二进制文件。

    1. 下载提供的 .asc 文件。

      • Linux:

        $ curl -OJL https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu.asc
      • macOS:

        $ curl -OJL https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin.asc
    2. 将二进制文件和对应的 .asc 文件放在同一个目录中,并运行以下命令验证该二进制文件:

      • Linux:

        $ gpg --verify operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu.asc
      • macOS:

        $ gpg --verify operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin.asc

      如果您的工作站上没有维护人员的公钥,则会出现以下错误:

      带有错误的输出示例

      $ gpg: assuming signed data in 'operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin'
      $ gpg: Signature made Fri Apr  5 20:03:22 2019 CEST
      $ gpg:                using RSA key <key_id> 1
      $ gpg: Can't check signature: No public key

      1
      RSA 密钥字符串。

      要下载密钥,请运行以下命令,用上一条命令输出的 RSA 密钥字符串来替换 <key_id>

      $ gpg [--keyserver keys.gnupg.net] --recv-key "<key_id>" 1
      1
      如果您尚未配置密钥服务器,请使用 --keyserver 选项指定一个密钥服务器。
  4. 在您的 PATH 中安装发行版本二进制文件:

    • Linux:

      $ chmod +x operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu
      $ sudo cp operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu /usr/local/bin/operator-sdk
      $ rm operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu
    • macOS:

      $ chmod +x operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin
      $ sudo cp operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin /usr/local/bin/operator-sdk
      $ rm operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin
  5. 验证是否已正确安装 CLI 工具:

    $ operator-sdk version

4.1.2.2. 通过 Homebrew 安装

可使用 Homebrew 来安装 SDK CLI。

先决条件

  • Homebrew
  • docker v17.03+、podman v1.2.0+ 或 buildah v1.7+
  • 已安装 OpenShift CLI (oc) v4.5+
  • 访问基于 Kubernetes v1.12.0+ 的集群
  • 访问容器 registry

流程

  1. 使用 brew 命令安装 SDK CLI:

    $ brew install operator-sdk
  2. 验证是否已正确安装 CLI 工具:

    $ operator-sdk version

4.1.2.3. 通过源代码编译并安装

可获取 Operator SDK 源代码来编译和安装 SDK CLI。

先决条件

  • Git
  • Go v1.13+
  • docker v17.03+、podman v1.2.0+ 或 buildah v1.7+
  • 已安装 OpenShift CLI (oc) v4.5+
  • 访问基于 Kubernetes v1.12.0+ 的集群
  • 访问容器 registry

流程

  1. 克隆 operator-sdk 存储库:

    $ mkdir -p $GOPATH/src/github.com/operator-framework
    $ cd $GOPATH/src/github.com/operator-framework
    $ git clone https://github.com/operator-framework/operator-sdk
    $ cd operator-sdk
  2. 检查所需的发行版本分支:

    $ git checkout master
  3. 编译并安装 SDK CLI:

    $ make dep
    $ make install

    该操作会在 $GOPATH/bin 中安装 CLI 二进制 operator-sdk

  4. 验证是否已正确安装 CLI 工具:

    $ operator-sdk version

4.1.3. 使用 Operator SDK 来构建基于 Go 的 Operator

Operator SDK 可简化 Kubernetes 原生应用程序的构建,构建该应用程序原本需要深入掌握特定于应用程序的操作知识。SDK 不仅降低了这一障碍,而且有助于减少许多常见管理功能(如计量或监控)所需的样板代码量。

本流程介绍了一个使用 SDK 提供的工具和库构建简单 Memcached Operator 的示例。

先决条件

  • 开发工作站已安装 Operator SDK CLI
  • 基于 Kubernetes 的集群(v1.8 或更高版本,支持 apps/v1beta2 API 组,如 OpenShift Container Platform 4.5)上已安装 Operator Lifecycle Manager (OLM)
  • 使用具有 cluster-admin 权限的账户访问该集群
  • 已安装 OpenShift CLI (oc) v4.5+

流程

  1. 创建一个新项目。

    使用 CLI 来新建 memcached-operator 项目:

    $ mkdir -p $GOPATH/src/github.com/example-inc/
    $ cd $GOPATH/src/github.com/example-inc/
    $ operator-sdk new memcached-operator
    $ cd memcached-operator
  2. 添加新的自定义资源定义(CRD)。

    1. 使用 CLI 来添加名为 Memcached 的新 CRD API,将 APIVersion 设置为 cache.example.com/v1apha1,将 Kind 设置为 Memcached

      $ operator-sdk add api \
          --api-version=cache.example.com/v1alpha1 \
          --kind=Memcached

      这样会将 Memcached 资源 API 构建至 pkg/apis/cache/v1alpha1/ 下。

    2. 修改 pkg/apis/cache/v1alpha1/memcached_types.go 文件中 Memcached 自定义资源(CR)的 spec 和状态:

      type MemcachedSpec struct {
      	// Size is the size of the memcached deployment
      	Size int32 `json:"size"`
      }
      type MemcachedStatus struct {
      	// Nodes are the names of the memcached pods
      	Nodes []string `json:"nodes"`
      }
    3. 修改好 *_types.go 文件后,务必要运行以下命令来更新该资源类型的生成代码:

      $ operator-sdk generate k8s
  3. 可选:将自定义验证添加到 CRD 中。

    当生成清单时,OpenAPI v3.0 模式会添加到 spec.validation 块中的 CRD 清单中。此验证块允许 Kubernetes 在 Memcached CR 创建或更新时验证其中的属性。

    另外,还会生成 pkg/apis/<group>/<version>/zz_generated.openapi.go 文件。如果 +k8s:openapi-gen=true annotation 位于默认存在的 Kind 类型声明之上,则该文件包含此验证块的 Go 表示。这个自动生成的代码是 Go Kind 类型的 OpenAPI 模型,您可以从中创建一个完整的 OpenAPI 规格并生成客户端。

    作为 Operator 作者,您可以使用 Kubebuilder 标记(注解)来配置 API 的自定义验证。这些标记必须始终具有 +kubebuilder:validation 前缀。例如,可以通过添加以下标记来添加一个 enum-type 规格:

    // +kubebuilder:validation:Enum=Lion;Wolf;Dragon
    type Alias string

    API 代码中的标记用法会在 Kubebuilder 生成 CRD用于配置/代码生成的标记文档中讨论。Kubebuilder CRD 验证文档还提供了 OpenAPIv3 验证标记的完整列表。

    如果添加任何自定义验证,请运行以下命令为 CRD 更新 deploy/crds/cache.example.com_memcacheds_crd.yaml 文件中的 OpenAPI 验证部分:

    $ operator-sdk generate crds

    生成的 YAML 示例

    spec:
      validation:
        openAPIV3Schema:
          properties:
            spec:
              properties:
                size:
                  format: int32
                  type: integer

  4. 添加新控制器。

    1. 在项目中添加新控制器以观察和协调 Memcached 资源:

      $ operator-sdk add controller \
          --api-version=cache.example.com/v1alpha1 \
          --kind=Memcached

      这会在 pkg/controller/memcached/ 下构建新的控制器实现。

    2. 在本示例中,将所生成的控制器文件 pkg/controller/memcached/memcached_controller.go 替换成示例实现

      示例控制器为每个 Memcached 资源执行以下协调逻辑:

      • 如果尚无 Memcached 部署,创建一个。
      • 确保 Deployment 大小与 Memcached CR spec 中指定的大小相同。
      • 使用 Memcached pod 的名称来更新 Memcached 资源状态。

      接下来的两个子步骤检查控制器如何监视资源以及协调循环的触发方式。您可跳过这些步骤,直接构建和运行 Operator。

    3. 检查 pkg/controller/memcached/memcached_controller.go 文件中的控制器实现,查看控制器如何监视资源。

      首先要监视的是作为主要资源的 Memcached 类型。对于每个添加、更新或删除事件,协调循环均会针对该 Memcached 对象发送协调 Request(一个 <namespace>:<name> 键):

      err := c.Watch(
        &source.Kind{Type: &cachev1alpha1.Memcached{}}, &handler.EnqueueRequestForObject{})

      接下来监视 Deployment,但事件处理程序会将每个事件映射到 Deployment 所有者的协调 Request 中。在这种情况下,这是创建部署的 Memcached 对象。这允许控制器将部署视为辅助资源:

      err := c.Watch(&source.Kind{Type: &appsv1.Deployment{}}, &handler.EnqueueRequestForOwner{
      		IsController: true,
      		OwnerType:    &cachev1alpha1.Memcached{},
      	})
    4. 每个控制器均有一个 Reconciler 对象,且该对象带有实现协调循环的 Reconcile() 方法。系统会将 Request 参数传递到该协调循环,该参数是一个用于从缓存中查找主资源对象 Memcached<namespace>:<name> 键:

      func (r *ReconcileMemcached) Reconcile(request reconcile.Request) (reconcile.Result, error) {
        // Lookup the Memcached instance for this reconcile request
        memcached := &cachev1alpha1.Memcached{}
        err := r.client.Get(context.TODO(), request.NamespacedName, memcached)
        ...
      }

      根据 Reconcile() 函数的返回值,协调 Request 可能会重新排队,且可能会再次触发循环:

      // Reconcile successful - don't requeue
      return reconcile.Result{}, nil
      // Reconcile failed due to error - requeue
      return reconcile.Result{}, err
      // Requeue for any reason other than error
      return reconcile.Result{Requeue: true}, nil
  5. 构建并运行 Operator。

    1. 在运行 Operator 之前,必须使用 Kubernetes API 服务器来注册 CRD:

      $ oc create \
          -f deploy/crds/cache_v1alpha1_memcached_crd.yaml
    2. 注册 CRD 之后,运行 Operator 时有两个选项可供选择:

      • 作为 Kubernetes 集群内的一个 Deployment 来运行
      • 作为集群外的 Go 程序运行

      选择以下任一方法。

      1. 选项 A: 作为集群内的一个部署运行。

        1. 构建 memcached-operator 镜像并将其推送至 registry:

          $ operator-sdk build quay.io/example/memcached-operator:v0.0.1
        2. 部署清单在 deploy/operator.yaml 中生成。按如下方式更新部署镜像,因为默认值只是一个占位符:

          $ sed -i 's|REPLACE_IMAGE|quay.io/example/memcached-operator:v0.0.1|g' deploy/operator.yaml
        3. 确保 Quay.io 上有一个可供下一步使用的账户,或者替换您的首选容器 registry。在 registry 中,创建一个名为 memcached-operator 的新公共镜像存储库。
        4. 将镜像推送至 registry:

          $ podman push quay.io/example/memcached-operator:v0.0.1
        5. 设置 RBAC 并创建 memcached-operator 清单:

          $ oc create -f deploy/role.yaml
          $ oc create -f deploy/role_binding.yaml
          $ oc create -f deploy/service_account.yaml
          $ oc create -f deploy/operator.yaml
        6. 验证 memcached-operator 部署是否正在运行:

          $ oc get deployment

          输出示例

          NAME                     DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
          memcached-operator       1         1         1            1           1m

      2. 选项 B:在集群外本地运行。

        这是开发循环中的首选方法,可加快部署和测试的速度。

        使用 $HOME/.kube/config 中的默认 Kubernetes 配置文件在本地运行 Operator:

        $ operator-sdk run --local --namespace=default

        您可借助标记 --kubeconfig=<path/to/kubeconfig> 来使用特定的 kubeconfig

  6. 通过创建一个 Memcached CR 来验证 Operator 可以部署 Memcached 应用程序。

    1. 创建 deploy/crds/cache_v1alpha1_memcached_cr.yaml 中生成的 Memcached CR 示例。
    2. 查看文件:

      $ cat deploy/crds/cache_v1alpha1_memcached_cr.yaml

      输出示例

      apiVersion: "cache.example.com/v1alpha1"
      kind: "Memcached"
      metadata:
        name: "example-memcached"
      spec:
        size: 3

    3. 创建对象:

      $ oc apply -f deploy/crds/cache_v1alpha1_memcached_cr.yaml
    4. 确保 memcached-operator 为 CR 创建部署:

      $ oc get deployment

      输出示例

      NAME                     DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
      memcached-operator       1         1         1            1           2m
      example-memcached        3         3         3            3           1m

    5. 检查 pod 和 CR,以确认 CR 状态已更新为 pod 名称:

      $ oc get pods

      输出示例

      NAME                                  READY     STATUS    RESTARTS   AGE
      example-memcached-6fd7c98d8-7dqdr     1/1       Running   0          1m
      example-memcached-6fd7c98d8-g5k7v     1/1       Running   0          1m
      example-memcached-6fd7c98d8-m7vn7     1/1       Running   0          1m
      memcached-operator-7cc7cfdf86-vvjqk   1/1       Running   0          2m

      $ oc get memcached/example-memcached -o yaml

      输出示例

      apiVersion: cache.example.com/v1alpha1
      kind: Memcached
      metadata:
        clusterName: ""
        creationTimestamp: 2018-03-31T22:51:08Z
        generation: 0
        name: example-memcached
        namespace: default
        resourceVersion: "245453"
        selfLink: /apis/cache.example.com/v1alpha1/namespaces/default/memcacheds/example-memcached
        uid: 0026cc97-3536-11e8-bd83-0800274106a1
      spec:
        size: 3
      status:
        nodes:
        - example-memcached-6fd7c98d8-7dqdr
        - example-memcached-6fd7c98d8-g5k7v
        - example-memcached-6fd7c98d8-m7vn7

  7. 通过更新部署的大小来验证 Operator 可否管理所部署的 Memcached 应用程序

    1. memcached CR 中的 spec.size 字段从 3 改为 4

      $ cat deploy/crds/cache_v1alpha1_memcached_cr.yaml

      输出示例

      apiVersion: "cache.example.com/v1alpha1"
      kind: "Memcached"
      metadata:
        name: "example-memcached"
      spec:
        size: 4

    2. 应用更改:

      $ oc apply -f deploy/crds/cache_v1alpha1_memcached_cr.yaml
    3. 确认 Operator 已更改部署大小:

      $ oc get deployment

      输出示例

      NAME                 DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
      example-memcached    4         4         4            4           5m

  8. 清理资源:

    $ oc delete -f deploy/crds/cache_v1alpha1_memcached_cr.yaml
    $ oc delete -f deploy/crds/cache_v1alpha1_memcached_crd.yaml
    $ oc delete -f deploy/operator.yaml
    $ oc delete -f deploy/role.yaml
    $ oc delete -f deploy/role_binding.yaml
    $ oc delete -f deploy/service_account.yaml

其他资源

  • 如需有关 CRD 中的 OpenAPI v3.0 验证模式的更多信息,请参阅 Kubernetes 文档

4.1.4. 使用 Operator Lifecycle Manager 来管理基于 Go 的 Operator

上一节介绍了如何手动运行 Operator。下面将探索如何使用 Operator Lifecycle Manager(OLM),OLM 将为生产环境中运行的 Operator 启用更强大的部署模型。

OLM 可帮助您在 Kubernetes 集群中安装、更新所有 Operator(及其相关服务)并对其整个生命周期实施一般性管理。OLM 将作为 Kubernetes 的扩展程序运行,支持您使用 oc 实现所有生命周期管理功能,而无需额外工具。

先决条件

  • 基于 Kubernetes 的集群(v1.8 或更高版本,支持 apps/v1beta2 API 组,如 OpenShift Container Platform 4.5)上已安装 OLM
  • 已构建 Memcached Operator

流程

  1. 生成 Operator 清单。

    Operator 清单描述了如何整体显示、创建和管理应用程序,即本例中的 Memcached。该清单由 ClusterServiceVersion (CSV) 对象定义,是运行 OLM 的必要条件。

    从您在构建 Memcached Operator 时创建的 memcached-operator/ 目录中生成 CSV 清单:

    $ operator-sdk generate csv --csv-version 0.0.1
    注意

    更多有关手动定义清单文件的信息,请参阅构建用于 Operator Framework 的 CSV

  2. 创建一个 Operator 组,指定 Operator 的目标命名空间。在要创建 CSV 的命名空间中创建以下 Operator 组。本例中使用了 default 命名空间:

    apiVersion: operators.coreos.com/v1
    kind: OperatorGroup
    metadata:
      name: memcached-operator-group
      namespace: default
    spec:
      targetNamespaces:
      - default
  3. 部署 Operator。使用在您构建 Memcached Operator 时由 Operator SDK 生成并存储至 deploy/ 目录中的文件。

    1. 通过在 spec.customresourcedefinitions. owned 部分中为每个自定义资源定义(CRD)kind 添加 displayName 字段来编辑生成的 CSV 清单文件:

      deploy/olm-catalog/memcached-operator/0.0.1/memcached-operator.v0.0.1.clusterserviceversion.yaml 文件

      ...
      spec:
        customresourcedefinitions:
          owned:
          - kind: Memcached
            name: memcacheds.cache.example.com
            version: v1alpha1
            description: Memcached is the Schema for the memcacheds API
            displayName: Memcached 1
      ...

      1
      为 CRD 指定显示名称。
    2. 将 CSV 清单应用到集群中的指定命名空间:

      $ oc apply -f deploy/olm-catalog/memcached-operator/0.0.1/memcached-operator.v0.0.1.clusterserviceversion.yaml

      应用该清单时,集群不会立即更新,因为尚未满足清单中指定的要求。

    3. 创建角色、角色绑定和服务账户,为 Operator 授予资源权限,创建自定义资源定义(CRD)来创建 Operator 管理的 Memcached 自定义资源:

      $ oc create -f deploy/crds/cache.example.com_memcacheds_crd.yaml
      $ oc create -f deploy/service_account.yaml
      $ oc create -f deploy/role.yaml
      $ oc create -f deploy/role_binding.yaml

      因为在应用清单时,OLM 会在特定命名空间中创建 Operator,所以管理员可利用原生 Kubernetes RBAC 权限模型来限制哪些用户可以安装 Operator。

  4. 创建应用程序实例。

    Memcached Operator 正在 default 命名空间中运行。用户通过自定义资源实例与 Operator 交互 ; 在这种情况下,资源具有 Memcached 类型。原生 Kubernetes RBAC 也适用于自定义资源,让管理员控制与每个 Operator 的交互。

    在该命名空间中创建 Memcached 对象实例将触发 Memcached Operator,以针对运行由 Operator 管理的 Memcached 服务器的 Pod 进行实例化。您创建的自定义资源越大,在此命名空间中运行的 Memcached Operator 管理更唯一的 Memcached 应用程序实例。

    $ cat <<EOF | oc apply -f -
    apiVersion: "cache.example.com/v1alpha1"
    kind: "Memcached"
    metadata:
      name: "memcached-for-wordpress"
    spec:
      size: 1
    EOF
    $ cat <<EOF | oc apply -f -
    apiVersion: "cache.example.com/v1alpha1"
    kind: "Memcached"
    metadata:
      name: "memcached-for-drupal"
    spec:
      size: 1
    EOF
    $ oc get Memcached

    输出示例

    NAME                      AGE
    memcached-for-drupal      22s
    memcached-for-wordpress   27s

    $ oc get pods

    输出示例

    NAME                                       READY     STATUS    RESTARTS   AGE
    memcached-app-operator-66b5777b79-pnsfj    1/1       Running   0          14m
    memcached-for-drupal-5476487c46-qbd66      1/1       Running   0          3s
    memcached-for-wordpress-65b75fd8c9-7b9x7   1/1       Running   0          8s

4.1.5. 其他资源

4.2. 创建基于 Ansible 的 Operator

本指南概述了 Operator SDK 中的 Ansible 支持,通过一些示例指导 Operator 作者通过使用 Ansible playbook 和模块的 operator-sdk CLI 工具来构建和运行基于 Ansible 的 Operator。

4.2.1. Operator SDK 中的 Ansible 支持

Operator Framework 是一个开源工具包,用于以有效、自动化且可扩展的方式管理 Kubernetes 原生应用程序,即 Operator。该框架中包含 Operator SDK,可协助开发人员利用自己的专业知识来引导和构建 Operator,而无需了解 Kubernetes API 复杂性。

通过 Operator SDK 生成 Operator 项目的其中一种方案是利用现有 Ansible playbook 和模块来部署 Kubernetes 资源作为统一应用程序,而无需编写任何 Go 代码。

4.2.1.1. 自定义资源文件

Operator 会使用 Kubernetes 的扩展机制,即自定义资源定义 (CRD),这样您的自定义资源 (CR) 的外观和行为均类似于内置的原生 Kubernetes 对象。

CR 文件格式是一个 Kubernetes 资源文件。该对象具有必填和选填字段:

表 4.1. 自定义资源字段

字段描述

apiVersion

要创建 CR 的版本。

kind

要创建 CR 的类型。

metadata

要创建的 Kubernetes 特定元数据。

spec(选填)

传输至 Ansible 的变量键值列表。本字段默认为空。

status

总结对象的当前状态。对于基于 Ansible 的 Operator,status 子资源默认为 CRD 启用,由 operator_sdk.util.k8s_status Ansible 模块管理,其中包含 CR statuscondition 信息。

annotations

要附于 CR 的 Kubernetes 特定注解。

以下 CR 注解列表会修改 Operator 的行为:

表 4.2. 基于 Ansible 的 Operator 注解

注解描述

ansible.operator-sdk/reconcile-period

为 CR 指定协调间隔。该值将通过标准 Golang 软件包 time 来解析。具体来说,使用 ParseDuration,默认后缀 s,给出的数值以秒为单位。

基于 Ansible 的 Operator 注解示例

apiVersion: "test1.example.com/v1alpha1"
kind: "Test1"
metadata:
  name: "example"
annotations:
  ansible.operator-sdk/reconcile-period: "30s"

4.2.1.2. watches.yaml file

group/version/kind (GVK) 是 Kubernetes API 的唯一标识符。watches.yaml 文件包含从自定义资源(CR)中标识的自定义资源(CR)到 Ansible 角色或 playbook 的映射列表。Operator 期望这个映射文件位于 /opt/ansible/watches.yaml 的预定义位置。

表 4.3. watches.yaml 文件映射

字段描述

group

要监视的 CR 组。

version

要监视的 CR 版本。

kind

要监视的 CR 类型

role(默认)

添加至容器中的 Ansible 角色的路径。例如:如果您的 roles 目录位于 /opt/ansible/roles/ 中,角色名为 busybox,则该值应为 /opt/ansible/roles/busybox。该字段与 playbook 字段相互排斥。

playbook

添加至容器中的 Ansible playbook 的路径。期望这个 playbook 作为一种调用角色的方法。该字段与 role 字段相互排斥。

reconcilePeriod(选填)

给定 CR 的协调间隔,角色或 playbook 运行的频率。

manageStatus(选填)

如果设置为 true(默认),则 CR 的状态通常由 Operator 来管理。如果设置为 false,则 CR 的状态则会由指定角色或 playbook 在别处管理,或在单独控制器中管理。

watches.yaml 文件示例

- version: v1alpha1 1
  group: test1.example.com
  kind: Test1
  role: /opt/ansible/roles/Test1

- version: v1alpha1 2
  group: test2.example.com
  kind: Test2
  playbook: /opt/ansible/playbook.yml

- version: v1alpha1 3
  group: test3.example.com
  kind: Test3
  playbook: /opt/ansible/test3.yml
  reconcilePeriod: 0
  manageStatus: false

1
Test1 映射到 test1 角色的简单示例。
2
Test2 映射到 playbook 的简单示例。
3
Test3 kind 更复杂的示例。在 playbook 中禁止对 CR 状态重新排队和管理。
4.2.1.2.1. 高级选项

高级功能可通过添加至每个 GVK 的 watches.yaml 文件中来启用。它们可放在 groupversionkindplaybookrole 字段下方。

可使用 CR 上的注解覆盖每个资源的一些功能。可覆盖的选项会指定以下注解。

表 4.4. 高级 watches.yaml 文件选项

功能YAML 密钥描述覆盖注解默认值

协调周期

reconcilePeriod

特定 CR 的协调运行间隔时间。

ansbile.operator-sdk/reconcile-period

1m

管理状态

manageStatus

允许 Operator 管理每个 CR status 部分中的 conditions 部分。

 

true

监视依赖资源

watchDependentResources

支持 Operator 动态监视由 Ansible 创建的资源。

 

true

监控集群范围内的资源

watchClusterScopedResources

支持 Operator 监视由 Ansible 创建的集群范围的资源。

 

false

最大运行程序工件

maxRunnerArtifacts

管理 Ansible Runner 在 Operator 容器中为每个单独资源保存的构件目录的数量。

ansible.operator-sdk/max-runner-artifacts

20

带有高级选项的 watches.yml 文件示例

- version: v1alpha1
  group: app.example.com
  kind: AppService
  playbook: /opt/ansible/playbook.yml
  maxRunnerArtifacts: 30
  reconcilePeriod: 5s
  manageStatus: False
  watchDependentResources: False

4.2.1.3. 发送至 Ansible 的额外变量

额外变量可发送至 Ansible,然后由 Operator 管理。自定义资源 (CR) 的 spec 部分作为额外变量按照键值对传递。等同于传递给 ansible-playbook 命令的额外变量。

Operator 还会在 meta 字段下传递额外变量,用于 CR 的名称和 CR 的命名空间。

对于以下 CR 示例:

apiVersion: "app.example.com/v1alpha1"
kind: "Database"
metadata:
  name: "example"
spec:
  message:"Hello world 2"
  newParameter: "newParam"

作为额外变量传递至 Ansible 的结构为:

{ "meta": {
        "name": "<cr_name>",
        "namespace": "<cr_namespace>",
  },
  "message": "Hello world 2",
  "new_parameter": "newParam",
  "_app_example_com_database": {
     <full_crd>
   },
}

messagenewParameter 字段在顶层被设置为额外变量,meta 则为 Operator 中定义的 CR 提供相关元数据。meta 字段可使用 Ansible 中的点符号来访问,如:

- debug:
    msg: "name: {{ meta.name }}, {{ meta.namespace }}"

4.2.1.4. Ansible Runner 目录

Ansible Runner 会将与 Ansible 运行相关的信息保存至容器中。具体位于:/tmp/ansible-operator/runner/<group>/<version>/<kind>/<namespace>/<name>

其他资源

4.2.2. 安装 Operator SDK CLI

Operator SDK 配有一个 CLI 工具,可协助开发人员创建、构建和部署新的 Operator 项目。您可在工作站上安装 SDK CLI,为编写您自己的 Operator 做准备。

注意

本指南中,minikube v0.25.0+ 用作本地 Kubernetes 集群,Quay.io 用于公共 registry。

4.2.2.1. 从 GitHub 版本安装

您可以从 GitHub 上的项目下载并安装 Operator SDK CLI 的预构建发行版二进制文件。

先决条件

  • Go v1.13+
  • docker v17.03+、podman v1.2.0+ 或 buildah v1.7+
  • 已安装 OpenShift CLI (oc) v4.5+
  • 访问基于 Kubernetes v1.12.0+ 的集群
  • 访问容器 registry

流程

  1. 设置发行版本变量:

    $ RELEASE_VERSION=v0.17.2
  2. 下载发行版二进制文件。

    • Linux:

      $ curl -OJL https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu
    • macOS:

      $ curl -OJL https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin
  3. 验证所下载的发行版本二进制文件。

    1. 下载提供的 .asc 文件。

      • Linux:

        $ curl -OJL https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu.asc
      • macOS:

        $ curl -OJL https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin.asc
    2. 将二进制文件和对应的 .asc 文件放在同一个目录中,并运行以下命令验证该二进制文件:

      • Linux:

        $ gpg --verify operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu.asc
      • macOS:

        $ gpg --verify operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin.asc

      如果您的工作站上没有维护人员的公钥,则会出现以下错误:

      带有错误的输出示例

      $ gpg: assuming signed data in 'operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin'
      $ gpg: Signature made Fri Apr  5 20:03:22 2019 CEST
      $ gpg:                using RSA key <key_id> 1
      $ gpg: Can't check signature: No public key

      1
      RSA 密钥字符串。

      要下载密钥,请运行以下命令,用上一条命令输出的 RSA 密钥字符串来替换 <key_id>

      $ gpg [--keyserver keys.gnupg.net] --recv-key "<key_id>" 1
      1
      如果您尚未配置密钥服务器,请使用 --keyserver 选项指定一个密钥服务器。
  4. 在您的 PATH 中安装发行版本二进制文件:

    • Linux:

      $ chmod +x operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu
      $ sudo cp operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu /usr/local/bin/operator-sdk
      $ rm operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu
    • macOS:

      $ chmod +x operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin
      $ sudo cp operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin /usr/local/bin/operator-sdk
      $ rm operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin
  5. 验证是否已正确安装 CLI 工具:

    $ operator-sdk version

4.2.2.2. 通过 Homebrew 安装

可使用 Homebrew 来安装 SDK CLI。

先决条件

  • Homebrew
  • docker v17.03+、podman v1.2.0+ 或 buildah v1.7+
  • 已安装 OpenShift CLI (oc) v4.5+
  • 访问基于 Kubernetes v1.12.0+ 的集群
  • 访问容器 registry

流程

  1. 使用 brew 命令安装 SDK CLI:

    $ brew install operator-sdk
  2. 验证是否已正确安装 CLI 工具:

    $ operator-sdk version

4.2.2.3. 通过源代码编译并安装

可获取 Operator SDK 源代码来编译和安装 SDK CLI。

先决条件

  • Git
  • Go v1.13+
  • docker v17.03+、podman v1.2.0+ 或 buildah v1.7+
  • 已安装 OpenShift CLI (oc) v4.5+
  • 访问基于 Kubernetes v1.12.0+ 的集群
  • 访问容器 registry

流程

  1. 克隆 operator-sdk 存储库:

    $ mkdir -p $GOPATH/src/github.com/operator-framework
    $ cd $GOPATH/src/github.com/operator-framework
    $ git clone https://github.com/operator-framework/operator-sdk
    $ cd operator-sdk
  2. 检查所需的发行版本分支:

    $ git checkout master
  3. 编译并安装 SDK CLI:

    $ make dep
    $ make install

    该操作会在 $GOPATH/bin 中安装 CLI 二进制 operator-sdk

  4. 验证是否已正确安装 CLI 工具:

    $ operator-sdk version

4.2.3. 使用 Operator SDK 来构建基于 Ansible 的 Operator

本流程介绍了使用 Operator SDK 中的工具和库来构建由 Ansible playbook 和模块提供技术支持的简单 Memcached Operator 示例。

先决条件

  • 开发工作站已安装 Operator SDK CLI
  • 使用具有 cluster-admin 权限的账户访问基于 Kubernetes 的集群 v1.11.3+(如 OpenShift Container Platform 4.5)
  • 已安装 OpenShift CLI (oc) v4.5+
  • ansible v2.9.0+
  • ansible-runner v1.1.0+
  • ansible-runner-http v1.0.0+

流程

  1. 创建新 Operator 项目。命名空间范围的 Operator 会监视和管理单一命名空间中的资源。命名空间范围的 Operator 因具有高灵活性而常被视为首选。这类 Operator 支持解耦升级、针对故障和监控隔离命名空间以及区别化 API 定义。

    要创建基于 Ansible 的、全命名空间范围的新 memcached-operator 项目并改为新目录,请使用以下命令:

    $ operator-sdk new memcached-operator \
        --api-version=cache.example.com/v1alpha1 \
        --kind=Memcached \
        --type=ansible
    $ cd memcached-operator

    这会创建 memcached-operator 项目,专门用于监视 API 版本 example.com/v1apha1 和 kind MemcachedMemcached 资源。

  2. 自定义 Operator 逻辑。

    在本例中,memcached-operator 会针对每个 Memcached 自定义资源 (CR) 执行以下协调逻辑:

    • 如果尚无 Memcached 部署,创建一个。
    • 确保部署的大小与 Memcached CR 指定的大小相同。

    默认情况下,memcached-operator 会监视 Memcached 资源事件,如 watches.yaml 文件中所示,并执行 Ansible 角色 Memcached

    - version: v1alpha1
      group: cache.example.com
      kind: Memcached

    您可选择在 watches.yaml 文件中自定义以下逻辑:

    1. 指定 role 选项会将 Operator 配置为在通过 Ansible 角色启动 ansible-runner 时使用该指定路径。默认情况下,operator-sdk new 命令会填写到您的角色应前往的绝对路径:

      - version: v1alpha1
        group: cache.example.com
        kind: Memcached
        role: /opt/ansible/roles/memcached
    2. 指定 watches.yaml 文件中的 playbook 选项会将 Operator 配置为在通过 Ansible playbook 启动 ansible-runner 时使用该指定路径。

      - version: v1alpha1
        group: cache.example.com
        kind: Memcached
        playbook: /opt/ansible/playbook.yaml
  3. 构建 Memcached Ansible 角色。

    修改 roles/memcached/ 目录下生成的 Ansible 角色。该 Ansible 角色会控制修改资源时所执行的逻辑。

    1. 定义 Memcached spec。

      可完全在 Ansible 中定义基于 Ansible 的 Operator spec。Ansible Operator 会将 CR spec 字段中列出的所有键值对作为变量传递给 Ansible。在运行 Ansible 之前,Operator 会将 spec 字段中所有变量的名称转换为 snake 格式(小写并附带下划线)。例如,spec 中的 serviceAccount 在 Ansible 中会变成 service_account

      提示

      您应在 Ansible 中对变量执行一些类型验证,以确保应用程序收到所需输入。

      如果用户未设置 spec 字段,则请修改 roles/memcached/defaults/main.yml 文件设置默认值:

      size: 1
    2. 定义 Memcached 部署。

      定义了 Memcached spec 后,即可定义资源发生更改时实际应执行的 Ansible。因为这是一个 Ansible 角色,所以默认行为是执行 roles/memcached/tasks/main.yml 文件中的任务。

      目的是在不存在部署的情况下让 Ansible 创建 Deployment,该 Deployment 将运行 memcached:1.4.36-alpine 镜像。Ansible 2.7+ 支持 k8s Ansible 模块,本例利用该模块来控制部署定义。

      修改 roles/memcached/tasks/main.yml 以匹配以下内容:

      - name: start memcached
        k8s:
          definition:
            kind: Deployment
            apiVersion: apps/v1
            metadata:
              name: '{{ meta.name }}-memcached'
              namespace: '{{ meta.namespace }}'
            spec:
              replicas: "{{size}}"
              selector:
                matchLabels:
                  app: memcached
              template:
                metadata:
                  labels:
                    app: memcached
                spec:
                  containers:
                  - name: memcached
                    command:
                    - memcached
                    - -m=64
                    - -o
                    - modern
                    - -v
                    image: "docker.io/memcached:1.4.36-alpine"
                    ports:
                      - containerPort: 11211
      注意

      本例使用 size 变量来控制 Memcached 部署的副本数。本示例将默认值设定为 1,但任何用户都可以创建一个 CR 覆盖该默认值。

  4. 部署 CRD。

    在运行 Operator 之前,Kubernetes 需要了解 Operator 将会监视的新自定义资源定义 (CRD)。部署 Memcached CRD:

    $ oc create -f deploy/crds/cache.example.com_memcacheds_crd.yaml
  5. 构建并运行 Operator。

    有两种方式来构建和运行 Operator:

    • 作为 Kubernetes 集群内的一个 pod。
    • 作为集群外的 Go 程序,使用 operator-sdk up 命令。

    选择以下任一方法:

    1. 作为 Kubernetes 集群内的一个 pod 来运行。这是生产环境的首先方法。

      1. 构建 memcached-operator 镜像并将其推送至 registry:

        $ operator-sdk build quay.io/example/memcached-operator:v0.0.1
        $ podman push quay.io/example/memcached-operator:v0.0.1
      2. deploy/operator.yaml 文件中会生成 Deployment 清单。本文件中的部署镜像需要从占位符 REPLACE_IMAGE 修改为之前构建的镜像。为此,请运行:

        $ sed -i 's|REPLACE_IMAGE|quay.io/example/memcached-operator:v0.0.1|g' deploy/operator.yaml
      3. 部署 memcached-operator 清单:

        $ oc create -f deploy/service_account.yaml
        $ oc create -f deploy/role.yaml
        $ oc create -f deploy/role_binding.yaml
        $ oc create -f deploy/operator.yaml
      4. 验证 memcached-operator 部署是否正在运行:

        $ oc get deployment
        NAME                     DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
        memcached-operator       1         1         1            1           1m
    2. 在集群外运行。这是开发阶段的首选方法,可加快部署和测试的速度。

      请确保已安装 Ansible Runner 和 Ansible Runner HTTP Plug-in,否则在创建 CR 时,系统会显示 Ansible Runner 出现意外错误。

      此外,还务必要确保您的计算机上存在 watches.yaml 文件中引用的角色路径。因为通常会在磁盘上角色所处的位置使用容器,所以必须手动将角色复制到已配置的 Ansible 角色路径中(如 /etc/ansible/roles)。

      1. 要使用 $HOME/.kube/config 中的默认 Kubernetes 配置文件在本地运行 Operator:

        $ operator-sdk run --local

        要使用所提供的 Kubernetes 配置文件在本地运行 Operator:

        $ operator-sdk run --local --kubeconfig=config
  6. 创建一个 Memcached CR。

    1. 按所示方式修改 deploy/crds/cache_v1alpha1_memcached_cr.yaml 文件并创建一个 Memcached CR:

      $ cat deploy/crds/cache_v1alpha1_memcached_cr.yaml

      输出示例

      apiVersion: "cache.example.com/v1alpha1"
      kind: "Memcached"
      metadata:
        name: "example-memcached"
      spec:
        size: 3

      $ oc apply -f deploy/crds/cache_v1alpha1_memcached_cr.yaml
    2. 确保 memcached-operator 为 CR 创建部署:

      $ oc get deployment

      输出示例

      NAME                     DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
      memcached-operator       1         1         1            1           2m
      example-memcached        3         3         3            3           1m

    3. 检查 pod,确认已创建三个副本:

      $ oc get pods
      NAME                                  READY     STATUS    RESTARTS   AGE
      example-memcached-6fd7c98d8-7dqdr     1/1       Running   0          1m
      example-memcached-6fd7c98d8-g5k7v     1/1       Running   0          1m
      example-memcached-6fd7c98d8-m7vn7     1/1       Running   0          1m
      memcached-operator-7cc7cfdf86-vvjqk   1/1       Running   0          2m
  7. 更新大小。

    1. memcached CR 中的 spec.size 字段从 3 改为 4,并应用以下更改:

      $ cat deploy/crds/cache_v1alpha1_memcached_cr.yaml

      输出示例

      apiVersion: "cache.example.com/v1alpha1"
      kind: "Memcached"
      metadata:
        name: "example-memcached"
      spec:
        size: 4

      $ oc apply -f deploy/crds/cache_v1alpha1_memcached_cr.yaml
    2. 确认 Operator 已更改部署大小:

      $ oc get deployment

      输出示例

      NAME                 DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
      example-memcached    4         4         4            4           5m

  8. 清理资源:

    $ oc delete -f deploy/crds/cache_v1alpha1_memcached_cr.yaml
    $ oc delete -f deploy/operator.yaml
    $ oc delete -f deploy/role_binding.yaml
    $ oc delete -f deploy/role.yaml
    $ oc delete -f deploy/service_account.yaml
    $ oc delete -f deploy/crds/cache_v1alpha1_memcached_crd.yaml

4.2.4. 使用 k8s Ansible 模块来管理应用程序生命周期

要使用 Ansible 管理 Kubernetes 上的应用程序生命周期,您可使用 k8s Ansible 模块。该 Ansible 模块支持开发人员利用其现有 Kubernetes 资源文件(用 YAML 编写),或用原生 Ansible 来表达生命周期管理。

将 Ansible 与现有 Kubernetes 资源文件相结合的一个最大好处在于可使用 Jinja 模板,这样您只需借助 Ansible 中的几个变量即可轻松自定义资源。

本部分将详细介绍 k8s Ansible 模块的用途。开始之前,请先在本地工作站安装该模块,然后使用 playbook 进行测试,最后移至 Operator 中继续使用。

4.2.4.1. 安装 k8s Ansible 模块

要在本地工作站中安装 k8s Ansible 模块:

流程

  1. 安装 Ansible 2.9+:

    $ sudo yum install ansible
  2. 使用 pip 来安装 OpenShift python 客户端软件包:

    $ sudo pip install openshift
    $ sudo pip install kubernetes

4.2.4.2. 在本地测试 k8s Ansible 模块

有时,开发人员最好在其本地机器上运行 Ansible 代码,而不必每次都运行和重构 Operator。

流程

  1. 安装 community.kubernetes 集合:

    $ ansible-galaxy collection install community.kubernetes
  2. 初始化基于 Ansible 的新 Operator 项目:

    $ operator-sdk new --type ansible \
        --kind Test1 \
        --api-version test1.example.com/v1alpha1 test1-operator

    输出示例

    Create test1-operator/tmp/init/galaxy-init.sh
    Create test1-operator/tmp/build/Dockerfile
    Create test1-operator/tmp/build/test-framework/Dockerfile
    Create test1-operator/tmp/build/go-test.sh
    Rendering Ansible Galaxy role [test1-operator/roles/test1]...
    Cleaning up test1-operator/tmp/init
    Create test1-operator/watches.yaml
    Create test1-operator/deploy/rbac.yaml
    Create test1-operator/deploy/crd.yaml
    Create test1-operator/deploy/cr.yaml
    Create test1-operator/deploy/operator.yaml
    Run git init ...
    Initialized empty Git repository in /home/user/go/src/github.com/user/opsdk/test1-operator/.git/
    Run git init done

    $ cd test1-operator
  3. 使用您想要的 Ansible 逻辑来修改 roles/test1/tasks/main.yml 文件。本示例通过变量切换来创建和删除命名空间。

    - name: set test namespace to "{{ state }}"
      community.kubernetes.k8s:
        api_version: v1
        kind: Namespace
        state: "{{ state }}"
        name: test
      ignore_errors: true 1
    1
    设置 ignore_errors: true 可确保删除不存在的项目不会失败。
  4. 修改 roles/test1/defaults/main.yml 文件,将默认 state 设置为 present:

    state: present
  5. 在顶层目录中创建一个 Ansible playbook playbook.yml 文件,其中包含 test1 角色:

    - hosts: localhost
      roles:
        - test1
  6. 运行 playbook:

    $ ansible-playbook playbook.yml

    输出示例

     [WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
    
    PLAY [localhost] ***************************************************************************
    
    PROCEDURE [Gathering Facts] *********************************************************************
    ok: [localhost]
    
    Task [test1 : set test namespace to present]
    changed: [localhost]
    
    PLAY RECAP *********************************************************************************
    localhost                  : ok=2    changed=1    unreachable=0    failed=0

  7. 检查是否已创建命名空间:

    $ oc get namespace

    输出示例

    NAME          STATUS    AGE
    default       Active    28d
    kube-public   Active    28d
    kube-system   Active    28d
    test          Active    3s

  8. 重新运行 playbook,设置 stateabsent

    $ ansible-playbook playbook.yml --extra-vars state=absent

    输出示例

     [WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
    
    PLAY [localhost] ***************************************************************************
    
    PROCEDURE [Gathering Facts] *********************************************************************
    ok: [localhost]
    
    Task [test1 : set test namespace to absent]
    changed: [localhost]
    
    PLAY RECAP *********************************************************************************
    localhost                  : ok=2    changed=1    unreachable=0    failed=0

  9. 检查是否已删除命名空间:

    $ oc get namespace

    输出示例

    NAME          STATUS    AGE
    default       Active    28d
    kube-public   Active    28d
    kube-system   Active    28d

4.2.4.3. 在 Operator 内测试 k8s Ansible 模块

熟悉在本地使用 k8s Ansible 模块后,您可在 Operator 内触发自定义资源 (CR) 发生变化时的相同 Ansible 逻辑。本示例将 Ansible 角色映射到 Operator 所监视的特定 Kubernetes 资源。该映射在 watches.yaml 文件中完成。

4.2.4.3.1. 本地测试基于 Ansible 的 Operator

熟悉在本地测试 Ansible 工作流后,您可以在本地运行的基于 Ansible 的 Operator 内测试逻辑。

为此,请使用 Operator 项目顶层目录中的 operator-sdk run --local 命令。此命令读取 watches.yaml 文件,并使用 ~/.kube/config 文件与 Kubernetes 集群通信,就如同 k8s Ansible 模块一样。

流程

  1. 因为 run --local 命令是从 watches.yaml 文件中读取的,所以有一些选项可供 Operator 作者使用。如果 role 独立存在(默认为 /opt/ansible/roles/<name>),则必须直接从 Operator 中复制该角色至 /opt/ansible/roles/ 目录。

    这很麻烦,因为更改不会反映在当前目录中。相反,可更改 role 字段以指向当前目录并注释掉现有行:

    - version: v1alpha1
      group: test1.example.com
      kind: Test1
      #  role: /opt/ansible/roles/Test1
      role: /home/user/test1-operator/Test1
  2. 为自定义资源(CR)Test1 创建自定义资源定义(CRD)和适当的基于角色的访问控制(RBAC)定义。operator-sdk 命令会在 deploy/ 目录中自动生成这些文件:

    $ oc create -f deploy/crds/test1_v1alpha1_test1_crd.yaml
    $ oc create -f deploy/service_account.yaml
    $ oc create -f deploy/role.yaml
    $ oc create -f deploy/role_binding.yaml
  3. 运行 run --local 命令:

    $ operator-sdk run --local

    输出示例

    [...]
    INFO[0000] Starting to serve on 127.0.0.1:8888
    INFO[0000] Watching test1.example.com/v1alpha1, Test1, default

  4. 现在,Operator 正在监视资源 Test1 中的事件,创建 CR 会触发您的 Ansible 角色执行。查看 deploy/cr.yaml 文件:

    apiVersion: "test1.example.com/v1alpha1"
    kind: "Test1"
    metadata:
      name: "example"

    因为未设置 spec 字段,所以调用 Ansible 时无额外变量。下一部分将介绍额外变量如何从 CR 传递至 Ansible。这也是务必要为 Operator 设置合理的默认值的原因。

  5. 创建 Test1 的 CR 实例,并将默认变量 state 设置为 present:

    $ oc create -f deploy/cr.yaml
  6. 检查是否已创建命名空间 test

    $ oc get namespace

    输出示例

    NAME          STATUS    AGE
    default       Active    28d
    kube-public   Active    28d
    kube-system   Active    28d
    test          Active    3s

  7. 修改 deploy/cr.yaml 文件,将 state 字段设置为 absent

    apiVersion: "test1.example.com/v1alpha1"
    kind: "Test1"
    metadata:
      name: "example"
    spec:
      state: "absent"
  8. 应用这些更改,并确认已删除命名空间:

    $ oc apply -f deploy/cr.yaml
    $ oc get namespace

    输出示例

    NAME          STATUS    AGE
    default       Active    28d
    kube-public   Active    28d
    kube-system   Active    28d

4.2.4.3.2. 在集群上测试基于 Ansible 的 Operator

熟悉了在基于 Ansible 的 Operator 内部本地运行 Ansible 逻辑之后,您可在 Kubernetes 集群(如 OpenShift Container Platform)上的 pod 内部测试 Operator。作为 pod 在集群中运行是生产环境的首选方法。

流程

  1. 构建 test1-operator 镜像并将其推送到容器镜像仓库(registry):

    $ operator-sdk build quay.io/example/test1-operator:v0.0.1
    $ podman push quay.io/example/test1-operator:v0.0.1
  2. deploy/operator.yaml 文件中会生成 Deployment 清单。此文件中的部署镜像必须从占位符 REPLACE_IMAGE 修改为之前构建的镜像。为此,请运行以下命令:

    $ sed -i 's|REPLACE_IMAGE|quay.io/example/test1-operator:v0.0.1|g' deploy/operator.yaml

    如果要在 macOS 中执行这些步骤,请使用以下命令:

    $ sed -i "" 's|REPLACE_IMAGE|quay.io/example/test1-operator:v0.0.1|g' deploy/operator.yaml
  3. 部署 test1-operator:

    $ oc create -f deploy/crds/test1_v1alpha1_test1_crd.yaml 1
    1
    只有 CRD 不存在时才需要。
    $ oc create -f deploy/service_account.yaml
    $ oc create -f deploy/role.yaml
    $ oc create -f deploy/role_binding.yaml
    $ oc create -f deploy/operator.yaml
  4. 验证 test1-operator 是否正在运行:

    $ oc get deployment

    输出示例

    NAME                     DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
    test1-operator       1         1         1            1           1m

  5. 现在,您可以查看 test1-operator 的 Ansible 日志:

    $ oc logs deployment/test1-operator

4.2.5. 使用 operator_sdk.util Ansible 集合来管理自定义资源状态

基于 Ansible 的 Operator 会自动将上一次 Ansible 运行的一般信息更新到自定义资源 (CR) status 子资源中。其中包括成功和失败任务的数量以及相关的错误消息,如下所示:

status:
  conditions:
    - ansibleResult:
      changed: 3
      completion: 2018-12-03T13:45:57.13329
      failures: 1
      ok: 6
      skipped: 0
    lastTransitionTime: 2018-12-03T13:45:57Z
    message: 'Status code was -1 and not [200]: Request failed: <urlopen error [Errno
      113] No route to host>'
    reason: Failed
    status: "True"
    type: Failure
  - lastTransitionTime: 2018-12-03T13:46:13Z
    message: Running reconciliation
    reason: Running
    status: "True"
    type: Running

基于 Ansible 的 Operator 还支持 Operator 作者通过 k8s_status Ansible 模块提供自定义状态值,该模块包含在 operator_sdk.util中。作者可以根据需要使用任意键值对从 Ansible 内部更新 status

基于 Ansible 的 Operator 默认始终包含如上所示的通用 Ansible 运行输出。如果希望您的应用程序使用 Ansible 输出来更新状态,您可以通过应用程序来手动跟踪状态。

流程

  1. 要通过应用程序手动跟踪 CR 状态,请更新 watches.yaml 文件,并将 manageStatus 字段设置为 false:

    - version: v1
      group: api.example.com
      kind: Test1
      role: Test1
      manageStatus: false
  2. 使用 operator_sdk.util.k8s_status Ansible 模块来更新子资源。例如:要使用键 test1 和值 test2 更新,可使用 operator_sdk.util,如下所示:

    - operator_sdk.util.k8s_status:
        api_version: app.example.com/v1
        kind: Test1
        name: "{{ meta.name }}"
        namespace: "{{ meta.namespace }}"
        status:
          test1: test2

    集合也可以在角色的 meta/main.yml 中声明,用于新构建的 Ansible Operator:

    collections:
      - operator_sdk.util

    在角色 meta 中声明集合可让您直接调用 k8s_status 模块:

    k8s_status:
      <snip>
      status:
        test1: test2

其他资源

4.2.6. 其他资源

4.3. 创建基于 Helm 的 Operator

本指南概述了 Operator SDK 中的 Helm Chart 支持,借助示例引导 Operator 作者通过使用现有 Helm Chart 的 operator-sdk CLI 工具来构建和运行 Nginx Operator。

4.3.1. Operator SDK 中的 Helm Chart 支持

Operator Framework 是一个开源工具包,用于以有效、自动化且可扩展的方式管理 Kubernetes 原生应用程序,即 Operator。该框架中包含 Operator SDK,可协助开发人员利用自己的专业知识来引导和构建 Operator,而无需了解 Kubernetes API 复杂性。

通过 Operator SDK 生成 Operator 项目的其中一种方案是利用现有 Helm Chart 来部署 Kubernetes 资源作为统一应用程序,而无需编写任何 Go 代码。这种基于 Helm 的 Operator 非常适合于推出时所需逻辑极少的无状态应用程序,因为更改应该应用于作为 Chart 一部分生成的 Kubernetes 对象。这听起来似乎很有局限性,但就 Kubernetes 社区构建的 Helm Chart 的增长而言,这足以满足它们的大量用例需要。

Operator 的主要功能是从代表应用程序实例的自定义对象中读取数据,并使其所需状态与正在运行的状态相匹配。对于基于 Helm 的 Operator,对象的 spec 字段是一个配置选项列表,通常在 Helm values.yaml 文件中描述。您可以不使用 Helm CLI(如 helm install -f values.yaml)来通过标志设置这些值,而是在自定义资源 (CR) 中表达这些值,因为 CR 作为原生 Kubernetes 对象能够实现应用的 RBAC 以及审核跟踪所带来的好处。

举一个名为 Tomcat 的简单 CR 示例:

apiVersion: apache.org/v1alpha1
kind: Tomcat
metadata:
  name: example-app
spec:
  replicaCount: 2

replicaCount 值(本例中为 2 )会被传播到使用以下内容的 Chart 模板中:

{{ .Values.replicaCount }}

构建并部署完 Operator 后,您可通过新建一个 CR 实例来部署新的应用实例,或使用 oc 命令列出所有环境中运行的不同实例:

$ oc get Tomcats --all-namespaces

不要求使用 Helm CLI 或安装 Tiller;基于 Helm 的 Operator 会从 Helm 项目中导入代码。您要做的只是运行一个 Operator 实例,并使用自定义资源定义 (CRD) 注册 CR。因其遵循 RBAC,所以可以更容易防止生产环境改变。

4.3.2. 安装 Operator SDK CLI

Operator SDK 配有一个 CLI 工具,可协助开发人员创建、构建和部署新的 Operator 项目。您可在工作站上安装 SDK CLI,为编写您自己的 Operator 做准备。

注意

本指南中,minikube v0.25.0+ 用作本地 Kubernetes 集群,Quay.io 用于公共 registry。

4.3.2.1. 从 GitHub 版本安装

您可以从 GitHub 上的项目下载并安装 Operator SDK CLI 的预构建发行版二进制文件。

先决条件

  • Go v1.13+
  • docker v17.03+、podman v1.2.0+ 或 buildah v1.7+
  • 已安装 OpenShift CLI (oc) v4.5+
  • 访问基于 Kubernetes v1.12.0+ 的集群
  • 访问容器 registry

流程

  1. 设置发行版本变量:

    $ RELEASE_VERSION=v0.17.2
  2. 下载发行版二进制文件。

    • Linux:

      $ curl -OJL https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu
    • macOS:

      $ curl -OJL https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin
  3. 验证所下载的发行版本二进制文件。

    1. 下载提供的 .asc 文件。

      • Linux:

        $ curl -OJL https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu.asc
      • macOS:

        $ curl -OJL https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin.asc
    2. 将二进制文件和对应的 .asc 文件放在同一个目录中,并运行以下命令验证该二进制文件:

      • Linux:

        $ gpg --verify operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu.asc
      • macOS:

        $ gpg --verify operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin.asc

      如果您的工作站上没有维护人员的公钥,则会出现以下错误:

      带有错误的输出示例

      $ gpg: assuming signed data in 'operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin'
      $ gpg: Signature made Fri Apr  5 20:03:22 2019 CEST
      $ gpg:                using RSA key <key_id> 1
      $ gpg: Can't check signature: No public key

      1
      RSA 密钥字符串。

      要下载密钥,请运行以下命令,用上一条命令输出的 RSA 密钥字符串来替换 <key_id>

      $ gpg [--keyserver keys.gnupg.net] --recv-key "<key_id>" 1
      1
      如果您尚未配置密钥服务器,请使用 --keyserver 选项指定一个密钥服务器。
  4. 在您的 PATH 中安装发行版本二进制文件:

    • Linux:

      $ chmod +x operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu
      $ sudo cp operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu /usr/local/bin/operator-sdk
      $ rm operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu
    • macOS:

      $ chmod +x operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin
      $ sudo cp operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin /usr/local/bin/operator-sdk
      $ rm operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin
  5. 验证是否已正确安装 CLI 工具:

    $ operator-sdk version

4.3.2.2. 通过 Homebrew 安装

可使用 Homebrew 来安装 SDK CLI。

先决条件

  • Homebrew
  • docker v17.03+、podman v1.2.0+ 或 buildah v1.7+
  • 已安装 OpenShift CLI (oc) v4.5+
  • 访问基于 Kubernetes v1.12.0+ 的集群
  • 访问容器 registry

流程

  1. 使用 brew 命令安装 SDK CLI:

    $ brew install operator-sdk
  2. 验证是否已正确安装 CLI 工具:

    $ operator-sdk version

4.3.2.3. 通过源代码编译并安装

可获取 Operator SDK 源代码来编译和安装 SDK CLI。

先决条件

  • Git
  • Go v1.13+
  • docker v17.03+、podman v1.2.0+ 或 buildah v1.7+
  • 已安装 OpenShift CLI (oc) v4.5+
  • 访问基于 Kubernetes v1.12.0+ 的集群
  • 访问容器 registry

流程

  1. 克隆 operator-sdk 存储库:

    $ mkdir -p $GOPATH/src/github.com/operator-framework
    $ cd $GOPATH/src/github.com/operator-framework
    $ git clone https://github.com/operator-framework/operator-sdk
    $ cd operator-sdk
  2. 检查所需的发行版本分支:

    $ git checkout master
  3. 编译并安装 SDK CLI:

    $ make dep
    $ make install

    该操作会在 $GOPATH/bin 中安装 CLI 二进制 operator-sdk

  4. 验证是否已正确安装 CLI 工具:

    $ operator-sdk version

4.3.3. 使用 Operator SDK 来构建基于 Helm 的 Operator

本流程介绍了使用 Operator SDK 中的工具和库来构建由 Helm Chart 提供技术支持的简单 Nginx Operator 的示例。

提示

最好为每个 Chart 新建一个 Operator。如果要在 Go 中编写一个成熟的 Operator,摆脱基于 Helm 的 Operator,这种做法支持更多具有原生行为的 Kubernetes API(如 oc get Nginx),也更灵活。

先决条件

  • 开发工作站已安装 Operator SDK CLI
  • 使用具有 cluster-admin 权限的账户访问基于 Kubernetes 的集群 v1.11.3+(如 OpenShift Container Platform 4.5)
  • 已安装 OpenShift CLI (oc) v4.5+

流程

  1. 创建新 Operator 项目。命名空间范围的 Operator 会监视和管理单一命名空间中的资源。命名空间范围的 Operator 因具有高灵活性而常被视为首选。这类 Operator 支持解耦升级、针对故障和监控隔离命名空间以及区别化 API 定义。

    要创建基于 Helm 的、全命名空间范围的新 nginx-operator 项目,请使用以下命令:

    $ operator-sdk new nginx-operator \
      --api-version=example.com/v1alpha1 \
      --kind=Nginx \
      --type=helm
    $ cd nginx-operator

    这会创建 nginx-operator 项目,专门用于监视 API 版本为 example.com/v1apha1 kind 为 Nginx 的 Nginx 资源。

  2. 自定义 Operator 逻辑。

    在本例中,nginx-operator 会针对每个 Nginx 自定义资源 (CR) 执行以下协调逻辑:

    • 如果尚无 Nginx 部署,请创建一个。
    • 如果尚无 Nginx 服务,请创建一个。
    • 如果被启用且不存在,请创建一个 Nginx ingress。
    • 确保部署、服务和可选的 Ingress 符合 Nginx CR 指定的所需配置(如副本数、镜像、服务类型)。

    默认情况下,nginx-operator 会监视 Vginx 资源事件,如 watches.yaml 文件中所示,并使用指定 Chart 执行 Helm 发行版本:

    - version: v1alpha1
      group: example.com
      kind: Nginx
      chart: /opt/helm/helm-charts/nginx
    1. 查阅 Nginx Helm Chart。

      创建 Helm Operator 项目后,Operator SDK 会创建一个 Helm Chart 示例,其中包含一组模板,用于简单的 Nginx 发行版本。

      本例中,针对部署、服务和 Ingress 资源提供了模板,另外还有 NOTES.txt 模板,Helm Chart 开发人员可利用该模板传达有关发型版本的实用信息。

      如果您对 Helm Charts 还不熟悉,请参阅 Helm Chart 开发者文档

    2. 了解 Nginx CR spec。

      Helm 使用名为 values 的概念来自定义 Helm Chart 的默认配置,该 chart 在 values.yaml 文件中定义。

      通过在 CR spec 中设置所需值来覆盖这些默认值。以副本数量为例:

      1. 首先,检查 helm-charts/nginx/values.yaml 文件,会发现 Chart 有一个名为 replicaCount 的值,默认设置为 1。要在部署中使用 2 个 Nginx 实例,您的 CR spec 中必须包含 replicaCount: 2

        更新 deploy/crds/example.com_v1alpha1_nginx_cr.yaml 文件,如下所示:

        apiVersion: example.com/v1alpha1
        kind: Nginx
        metadata:
          name: example-nginx
        spec:
          replicaCount: 2
      2. 同样,服务端口默认设置为 80。要改用 8080,请通过添加服务端口覆盖来再次更新 deploy/crds/example.com_v1alpha1_nginx_cr.yaml 文件:

        apiVersion: example.com/v1alpha1
        kind: Nginx
        metadata:
          name: example-nginx
        spec:
          replicaCount: 2
          service:
            port: 8080

        Helm Operator 应用整个 spec,将其视为 values 文件内容,与 helm install -f ./overrides.yaml 命令的工作方式类似。

  3. 部署 CRD。

    在运行 Operator 之前,Kubernetes 需要了解 Operator 将会监视的新自定义资源定义 (CRD)。部署以下 CRD:

    $ oc create -f deploy/crds/example_v1alpha1_nginx_crd.yaml
  4. 构建并运行 Operator。

    有两种方式来构建和运行 Operator:

    • 作为 Kubernetes 集群内的一个 pod。
    • 作为集群外的 Go 程序,使用 operator-sdk up 命令。

    选择以下任一方法:

    1. 作为 Kubernetes 集群内的一个 pod 来运行。这是生产环境的首先方法。

      1. 构建 nginx-operator 镜像并将其推送至 registry:

        $ operator-sdk build quay.io/example/nginx-operator:v0.0.1
        $ podman push quay.io/example/nginx-operator:v0.0.1
      2. deploy/operator.yaml 文件中会生成 Deployment 清单。本文件中的部署镜像需要从占位符 REPLACE_IMAGE 修改为之前构建的镜像。为此,请运行:

        $ sed -i 's|REPLACE_IMAGE|quay.io/example/nginx-operator:v0.0.1|g' deploy/operator.yaml
      3. 部署 nginx-operator 清单:

        $ oc create -f deploy/service_account.yaml
        $ oc create -f deploy/role.yaml
        $ oc create -f deploy/role_binding.yaml
        $ oc create -f deploy/operator.yaml
      4. 验证 nginx-operator 部署是否已启动并正在运行:

        $ oc get deployment

        输出示例

        NAME                 DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
        nginx-operator       1         1         1            1           1m

    2. 在集群外运行。这是开发阶段的首选方法,可加快部署和测试的速度。

      此外,还务必要确保您的计算机上存在 watches.yaml 文件中引用的 Chart 路径。watches.yaml 文件默认能够与通过 operator-sdk build 命令构建的 Operator 镜像一起使用。当使用 operator-sdk run --local 命令开发和测试您的 Operator 时,SDK 会在本地文件系统中查找该路径。

      1. 在该位置创建符号链接,以指向 Helm Chart 的路径:

        $ sudo mkdir -p /opt/helm/helm-charts
        $ sudo ln -s $PWD/helm-charts/nginx /opt/helm/helm-charts/nginx
      2. 要使用 $HOME/.kube/config 中的默认 Kubernetes 配置文件在本地运行 Operator:

        $ operator-sdk run --local

        要使用所提供的 Kubernetes 配置文件在本地运行 Operator:

        $ operator-sdk run --local --kubeconfig=<path_to_config>
  5. 部署 Nginx CR。

    应用之前修改的 Nginx CR:

    $ oc apply -f deploy/crds/example.com_v1alpha1_nginx_cr.yaml

    确保 nginx-operator 为 CR 创建部署:

    $ oc get deployment

    输出示例

    NAME                                           DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
    example-nginx-b9phnoz9spckcrua7ihrbkrt1        2         2         2            2           1m

    检查 pod,确认已创建两个副本:

    $ oc get pods

    输出示例

    NAME                                                      READY     STATUS    RESTARTS   AGE
    example-nginx-b9phnoz9spckcrua7ihrbkrt1-f8f9c875d-fjcr9   1/1       Running   0          1m
    example-nginx-b9phnoz9spckcrua7ihrbkrt1-f8f9c875d-ljbzl   1/1       Running   0          1m

    检查服务端口是否已设置为 8080:

    $ oc get service

    输出示例

    NAME                                      TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
    example-nginx-b9phnoz9spckcrua7ihrbkrt1   ClusterIP   10.96.26.3   <none>        8080/TCP   1m

  6. 更新 replicaCount 并删除端口。

    spec.replicaCount 字段从 2 改为 3,删除 spec.service 字段并应用更改:

    $ cat deploy/crds/example.com_v1alpha1_nginx_cr.yaml

    输出示例

    apiVersion: "example.com/v1alpha1"
    kind: "Nginx"
    metadata:
      name: "example-nginx"
    spec:
      replicaCount: 3

    $ oc apply -f deploy/crds/example.com_v1alpha1_nginx_cr.yaml

    确认 Operator 已更改部署大小:

    $ oc get deployment

    输出示例

    NAME                                           DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
    example-nginx-b9phnoz9spckcrua7ihrbkrt1        3         3         3            3           1m

    检查服务端口是否已设置为默认值 80:

    $ oc get service

    输出示例

    NAME                                      TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)  AGE
    example-nginx-b9phnoz9spckcrua7ihrbkrt1   ClusterIP   10.96.26.3   <none>        80/TCP   1m

  7. 清理资源:

    $ oc delete -f deploy/crds/example.com_v1alpha1_nginx_cr.yaml
    $ oc delete -f deploy/operator.yaml
    $ oc delete -f deploy/role_binding.yaml
    $ oc delete -f deploy/role.yaml
    $ oc delete -f deploy/service_account.yaml
    $ oc delete -f deploy/crds/example_v1alpha1_nginx_crd.yaml

4.3.4. 其他资源

4.4. 生成集群服务版本(CSV)

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

Operator SDK 包含 generate csv 子命令,用于使用手动定义的 YAML 清单和 Operator 源文件中所含的信息为自定义的当前 Operator 项目生成 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 generate csv --csv-version <version>

此操作采用等幂方式,仅会在提供新版本或更改 YAML 清单或源文件时才会更新 CSV 文件。Operator 作者不必直接修改 CSV 清单中的大部分字段。本指南中已经明确了需要修改的字段。例如:metadata.name 中必须包含 CSV 版本信息。

4.4.1. CSV 生成的工作方式

Operator 项目的 deploy/ 目录是部署 Operator 所需的所有清单的标准位置。Operator SDK 可使用 deploy/ 中的清单数据来编写集群服务版本(CSV)。

以下命令:

$ operator-sdk generate 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,并假设使用所有配置默认值,generate csv 子命令将:

  • 使用 YAML 清单和源文件中的可用数据新建一个 CSV,其位置和命名约定与当前存在的信息相同。

    1. 该更新机制会检查 deploy/ 中是否存在现有 CSV。如果没有找到,它会创建一个 ClusterServiceVersion 对象,这里称为 cache,并填充 Operator 元数据派生的字段,如 Kubernetes API ObjectMeta
    2. 更新机制在 deploy/ 中搜索包含 CSV 所用数据(如 Deployment 资源)的清单,并使用该数据设置 cache 中的适当 CSV 字段。
    3. 搜索完成后,每个填充的 cache 字段都会写回到 CSV YAML 文件中。

或:

  • 使用 YAML 清单和源文件中的可用数据更新当前预定义位置的现有 CSV。

    1. 该更新机制会检查 deploy/ 中是否存在现有 CSV。找到后,CSV YAML 文件内容会被放入 CSV 缓存中。
    2. 更新机制在 deploy/ 中搜索包含 CSV 所用数据(如 Deployment 资源)的清单,并使用该数据设置 cache 中的适当 CSV 字段。
    3. 搜索完成后,每个填充的 cache 字段都会写回到 CSV YAML 文件中。
注意

单个 YAML 字段(而非整个文件)会被覆盖,因为 CSV 的描述和其他未生成的部分将被保留。

4.4.2. CSV 组成配置

Operator 作者可通过填充 deploy/olm-catalog/csv-config.yaml 文件中的几个字段来配置 CSV 组成:

字段描述

operator-path (string)

Operator 资源清单文件路径。默认值:deploy/operator.yaml

crd-cr-path-list (string(, string)*)

CRD 和 CR 清单文件路径列表。默认: [deploy/crds/*_{crd,cr}.yaml]

rbac-path-list (string(, string)*)

RBAC 角色清单文件路径列表。默认: [deploy/role.yaml]

4.4.3. 手动定义的 CSV 字段

很多 CSV 字段无法使用生成的、不属于 Operator SDK 的特殊通用清单进行填充。这些字段大多由人工编写,是一些有关 Operator 和各种自定义资源定义 (CRD) 的英文元数据。

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

表 4.5. 必填

字段描述

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 的个人或组织实体,含名称电子邮件地址

spec.provider

Operator 的供应商(通常是机构),含 名称

spec.labels

供 Operator 内部使用的键值对。

spec.version

Operator 的语义版本,如 0.1.1

spec.customresourcedefinitions

Operator 使用的任何 CRD。如果 deploy/ 中存在任何 CRD YAML 文件,Operator SDK 将自动填充该字段。但 CRD 清单 spec 中没有的几个字段需要用户输入:

  • description:CRD 描述。
  • resources:CRD 利用的任何 Kubernetes 资源,如 PodStatefulSet 对象。
  • specDescriptors:用于 Operator 输入和输出的 UI 提示。

表 4.6. 选填

字段描述

spec.replaces

被该 CSV 替换的 CSV 名称。

spec.links

与被管理的 Operator 或应用程序相关的 URL(如网站和文档),各自含名称url

spec.selector

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

spec.icon

Operator 独有的 base64 编码图标,通过 mediatypebase64data 字段中设置。

spec.maturity

软件在这个版本中达到的成熟度。选项包括 planningpre-alphaalphabetastablematureinactivedeprecated

有关以上每个字段应包含哪些数据的更多详情,请参见 CSV spec

注意

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

4.4.4. 生成 CSV

先决条件

  • 使用 Operator SDK 生成一个 Operator 项目

流程

  1. 在 Operator 项目中,通过修改 deploy/olm-catalog/csv-config.yaml 文件来配置您的 CSV 组成(如果需要)。
  2. 生成 CSV:

    $ operator-sdk generate csv --csv-version <version>
  3. deploy/olm-catalog/ 目录中生成的新 CSV 中,确保正确设置所有必填的手动定义字段。

4.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
    ...
    1
    创建 relatedImages 部分并设置相关镜像列表。
    2
    指定镜像的唯一标识符。
    3
    通过摘要 (SHA) 而不是通过镜像标签指定每个镜像。
  • 在 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
    1
    使用环境变量注入 Operator 引用的镜像。
    2
    通过摘要 (SHA) 而不是通过镜像标签指定每个镜像。
    3
    另外,使用摘要(SHA)而不是镜像标签(tag)引用 Operator 容器镜像。
  • 查找 Disconnected 注解,它表示 Operator 在断开连接的环境中工作:

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

    OperatorHub 中可根据此基础架构功能来过滤 Operator。

4.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
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)而不是标签(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
    1 2
    在添加新的构架或操作系统后,您必须明确包含默认的 os.linuxarch.amd64 变体。

其他资源

4.4.6.1. Operator 的架构和操作系统支持

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

表 4.7. OpenShift Container Platform 支持的架构

架构字符串

AMD64

amd64

64-bit PowerPC little-endian

ppc64le

IBM Z

s390x

表 4.8. OpenShift Container Platform 支持的操作系统

操作系统字符串

Linux

linux

z/OS

zos

注意

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

4.4.7. 设置建议的命名空间

有些 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
    设置建议的命名空间。

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

您的 Operator 可能会使用两类自定义资源定义 (CRD):一类归 Operator 拥有,另一类为 Operator 依赖的必要 CRD。

4.4.8.1. 拥有的 CRD

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

Operator 通常会使用多个 CRD 将各个概念链接在一起,例如一个对象中的顶级数据库配置和另一对象中的副本集表示代表。这在 CSV 文件中应逐一列出。

表 4.9. 拥有的 CRD 字段

字段描述必需/可选

名称

CRD 的全名。

必填

Version

该对象 API 的版本。

必填

Kind

CRD 的机器可读名称。

必填

DisplayName

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

必填

描述

有关 Operator 如何使用该 CRD 的简短描述,或有关 CRD 所提供功能的描述。

必填

Group

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

选填

Resources

您的 CRD 可能拥有一类或多类 Kubernetes 对象。它们将在 resources 部分列出,用于告知用户他们可能需要排除故障的对象或如何连接至应用程序,如公开数据库的服务或 Ingress 规则。

建议仅列出对人重要的对象,而不必列出您编排的所有对象。例如,不要列出存储用户不会修改的内部状态的配置映射。

选填

SpecDescriptorsStatusDescriptorsActionDescriptors

这些描述符是通过对终端用户来说最重要的 Operator 的某些输入或输出提示 UI 的一种方式。如果您的 CRD 包含用户必须提供的 Secret 或 ConfigMap 的名称,您可在此处指定。这些项目在兼容的 UI 中链接并突出显示。

共有以下三类描述符:

  • SpecDescriptors:引用对象 spec 块中的字段。
  • StatusDescriptors:引用对象 status 块中的字段。
  • ActionDescriptors:引用对象上可执行的操作。

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

  • DisplayName: SpecStatusAction 的人类可读名称。
  • Description:有关 SpecStatusAction 以及 Operator 如何使用它的简短描述。
  • Path:描述符描述的对象上字段的点分隔路径。
  • X-Descriptors:用于决定该描述符拥有哪些“功能”以及要使用哪个 UI 组件。有关 OpenShift Container Platform 的标准 React UI X-Descriptors 列表的信息,请参见 openshift/console 项目。

有关描述符的更多一般信息,请参见 openshift/console 项目。

选填

以下示例描述了一个 MongoDB Standalone CRD,要求某些用户以 Secret 和配置映射的形式输入,并编排服务、有状态集、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.

4.4.8.2. 必需的 CRD

是否依赖其他必需 CRD 完全可以自由选择,它们存在的目的只是为了缩小单个 Operator 的范围,并提供一种将多个 Operator 组合到一起来解决端到端用例的办法。

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

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

表 4.10. 必需的 CRD 字段

字段描述必需/可选

名称

所需 CRD 的全称。

必填

Version

该对象 API 的版本。

必填

Kind

Kubernetes 对象类型。

必填

DisplayName

CRD 的人类可读版本。

必填

描述

概述该组件如何适合您的更大架构。

必填

必需的 CRD 示例

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

4.4.8.3. CRD 模板

Operator 用户必须了解哪个选项必填,而不是可选选项。您可为您的每个 CRD 提供模板,并以最小配置集作为名为 alm-examples 的注解。兼容 UI 会预先填充该模板,供用户进一步自定义。

该注解由一个 kind 列表组成,如 CRD 名称和对应的 Kubernetes 对象的 metadataspec

以下完整示例提供了 EtcdClusterEtcdBackupEtcdRestore 模板:

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>"}}}]

4.4.8.4. 隐藏内部对象

Operator 在内部使用自定义资源定义 (CRD) 来完成任务是常见的。这些对象并不是供用户操作的,且可能会让 Operator 用户混淆。例如,数据库 Operator 可能会有一个 Replication CRD,当用户创建带有 replication:true 的数据库对象时就会创建它。

作为 Operator 作者,您可以通过将 operators.operatorframework.io/internal-objects 注解添加到 Operator 的 ClusterServiceVersion(CSV)来隐藏用户界面中不用于用户操作的任何 CRD。

流程

  1. 在将一个 CRD 标记为 internal 之前,请确保任何管理应用程序所需的调试信息或配置都会反映在 CR 的状态或 spec 块中(如果适用于您的 Operator)。
  2. 向 Operator 的 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 设置为字符串数组。

4.4.9. 了解您的 API 服务

与 CRD 一样,您的 Operator 可使用两类 APIService:拥有的必需的

4.4.9.1. 拥有的 API 服务

当 CSV 拥有 API 服务时,它将负责描述为其提供支持的扩展 api-server 的部署及其提供的组/version/kind(GVK)。

API 服务由它提供的 group/version 唯一标识,并可以多次列出,以表示期望提供的不同类型。

表 4.11. 拥有的 API 服务字段

字段描述必需/可选

Group

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

必填

Version

API 服务的版本,如 v1alpha1

必填

Kind

API 服务应提供的类型。

必填

名称

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

必填

DeploymentName

由您的 CSV 定义的部署名称,对应您的 API 服务(对于拥有的 API 服务是必需的)。在 CSV 待定阶段,OLM Operator 会在您的 CSV InstallStrategy 中搜索具有匹配名称的 Deployment spec,如果未找到,则不会将 CSV 转换至安装就绪阶段。

必填

DisplayName

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

必填

描述

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

必填

资源

您的 API 服务拥有一类或多类 Kubernetes 对象。它们将在 resources 部分列出,用于告知用户他们可能需要排除故障的对象或如何连接至应用程序,如公开数据库的服务或 Ingress 规则。

建议仅列出对人重要的对象,而不必列出您编排的所有对象。例如,不要列出存储用户不会修改的内部状态的配置映射。

选填

SpecDescriptorsStatusDescriptorsActionDescriptors

与拥有的 CRD 基本相同。

选填

4.4.9.1.1. API 服务资源创建

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

  • Service pod 选择器从与 API 服务描述的 DeploymentName 字段匹配的 CSV 部署中复制。
  • 每次安装都会生成一个新的 CA 密钥/证书对,并且将 base64 编码的 CA 捆绑包嵌入到对应的 API 服务资源中。
4.4.9.1.2. API service serving 证书

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

该证书作为类型 kubernetes.io/tls secret 存储在部署命名空间中,名为 apiservice-cert 的卷会自动附加至 CSV 中与 API 服务描述的 DeploymentName 字段匹配的 volumes 部分中。

如果尚不存在,则具有匹配名称的卷挂载也会附加至该部署的所有容器中。这样用户便可使用预期名称来定义卷挂载,以适应任何自定义路径要求。所生成的卷挂载的默认路径为 /apiserver.local.config/certificates,具有相同路径的任何现有卷挂载都会被替换。

4.4.9.2. 所需的 API 服务

OLM 可保证所有必需的 CSV 均有可用的 API 服务,且所有预期的 GVK 在试图安装前均可发现。这允许 CSV 依赖于由它拥有的 API 服务提供的特定类型。

表 4.12. 所需的 API 服务字段

字段描述必需/可选

Group

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

必填

Version

API 服务的版本,如 v1alpha1

必填

Kind

API 服务应提供的类型。

必填

DisplayName

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

必填

描述

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

必填

4.5. 使用捆绑包镜像

您可以使用 Operator SDK 来使用捆绑格式(Bundle Format)来打包 Operator。

4.5.1. 构建捆绑包镜像

您可以使用 Operator SDK 来构建、推送并验证 Operator 捆绑包镜像。

先决条件

  • Operator SDK 版本 0.17.2
  • podman 1.4.4+ 版
  • 使用 Operator SDK 生成一个 Operator 项目

流程

  1. 从 Operator 项目目录中,使用 Operator SDK 来构建捆绑包镜像:

    $ operator-sdk bundle create \
        quay.io/<namespace>/test-operator:v0.1.0 \1
        -b podman 2
    1
    想让捆绑包镜像具有的镜像标签。
    2
    用于构建容器镜像的 CLI 工具,可以是 docker (默认)、podmanbuildah。这个示例使用 podman
    注意

    如果您的本地清单不在默认的 <project_root>/deploy/olm-catalog/test-operator/manifests 中,请使用 --directory 标志指定位置。

  2. 登录到要推送捆绑包镜像的 registry。例如:

    $ podman login quay.io
  3. 将捆绑包镜像推送到 registry:

    $ podman push quay.io/<namespace>/test-operator:v0.1.0
  4. 在远程 registry 中验证捆绑包镜像:

    $ operator-sdk bundle validate \
        quay.io/<namespace>/test-operator:v0.1.0 \
        -b podman

    输出示例

    INFO[0000] Unpacked image layers                                 bundle-dir=/tmp/bundle-041168359 container-tool=podman
    INFO[0000] running podman pull                                   bundle-dir=/tmp/bundle-041168359 container-tool=podman
    INFO[0002] running podman save                                   bundle-dir=/tmp/bundle-041168359 container-tool=podman
    INFO[0002] All validation tests have completed successfully      bundle-dir=/tmp/bundle-041168359 container-tool=podman

4.5.2. 其他资源

4.6. 使用 scorecard 验证 Operator

Operator 作者应验证其 Operator 已正确打包且没有语法错误。作为 Operator 作者,您可以使用 Operator SDK 的 scorecard 工具验证 Operator 打包并运行测试。

注意

OpenShift Container Platform 4.5 支持 Operator SDK v0.17.2。

4.6.1. 关于 scorecard 工具

要验证 Operator,Operator SDK 提供的 scorecard 工具将首先创建任何相关自定义资源(CR)和 Operator 所需的所有资源。然后,scorecard 在 Operator 部署中创建代理容器,用于记录对 API 服务器的调用并运行一些测试。执行的测试还会检查 CR 中的部分参数。

4.6.2. Scorecard 配置

Scorecard 工具使用一个配置文件来供您配置内部插件以及几个全局配置选项。

4.6.2.1. 配置文件

Scorecard 工具配置的默认位置为 <project_dir>/.osdk-scorecard.*。以下是 YAML 格式的配置文件示例:

Scorecard 配置文件

scorecard:
  output: json
  plugins:
    - basic: 1
        cr-manifest:
          - "deploy/crds/cache.example.com_v1alpha1_memcached_cr.yaml"
          - "deploy/crds/cache.example.com_v1alpha1_memcachedrs_cr.yaml"
    - olm: 2
        cr-manifest:
          - "deploy/crds/cache.example.com_v1alpha1_memcached_cr.yaml"
          - "deploy/crds/cache.example.com_v1alpha1_memcachedrs_cr.yaml"
        csv-path: "deploy/olm-catalog/memcached-operator/0.0.3/memcached-operator.v0.0.3.clusterserviceversion.yaml"

1
配置为测试两个自定义资源(CR)的基本 测试。
2
配置为测试两个 CR 的 olm 测试。

全局选项的配置方法采用以下优先级,从最高到最低依次为:

命令参数(如果可用)→ 配置文件 → 默认设置

配置文件必须为 YAML 格式。由于配置文件将来可能会扩展为允许配置所有 operator-sdk 子命令,因此 scorecard 的配置必须在 scorecard 子部分下。

注意

配置文件支持由 viper 软件包提供。如需有关 viper 配置如何工作的更多信息,请参阅 README

4.6.2.2. 命令参数

虽然大多数 scorecard 工具配置都是使用配置文件完成的,但您也可以使用以下参数:

表 4.13. Scorecard 工具参数

标记类型描述

--bundle, -b

字符串

用于捆绑包验证测试的捆绑包目录的路径。

--config

字符串

Scorecard 配置文件的路径。默认为 <project_dir>/.osdk-scorecard。文件类型和扩展名必须为 .yaml。如果没有在默认位置提供或找到配置文件,则 scorecard 退出时会出错。

--output, -o

字符串

输出格式。有效选项为 textjson。默认格式为 text,这是一种人类可读格式。json 格式使用 JSON 模式输出格式,用于稍后定义的插件。

--kubeconfig, -o

字符串

kubeconfig 文件的路径。它为内部插件设置 kubeconfig

--version

字符串

要运行的 scorecard 版本。默认和唯一有效选项为 v1alpha2

--selector, -l

字符串

用于过滤测试的标签选择器。

--list, -L

bool

如果为 true,则只输出会基于选择器过滤运行的测试名称。

4.6.2.3. 配置文件选项

Scorecard 配置文件提供以下选项:

表 4.14. Scorecard 配置文件选项

选项类型描述

bundle

字符串

等同于 --bundle 标记。Operator Lifecycle Manager(OLM)捆绑包目录路径,指定时运行捆绑包验证。

output

字符串

等同于 --output 标记。如果这个选项同时由配置文件和标志定义,则标记值将具有优先权。

kubeconfig

字符串

等同于 --kubeconfig 标记。如果这个选项同时由配置文件和标志定义,则标记值将具有优先权。

plugins

数组

插件名称的数组。

4.6.2.3.1. 基本和 OLM 插件

Scorecard 支持内部 basicolm 插件,这些插件由配置文件中的 plugins 部分配置。

表 4.15. 插件选项

选项类型描述

cr-manifest

[]string

待测试 CR 的路径。如果 olm-deployed 未设置或为 false,则此项为必需。

csv-path

字符串

Operator 的集群服务版本(CSV)的路径。对于 OLM 测试或者当 olm-deployed 设为 true 时为必需。

olm-deployed

bool

指示 OLM 已将 CSV 和相关 CRD 部署到集群中。

kubeconfig

字符串

kubeconfig 文件的路径。如果同时设置了全局 kubeconfig 和此字段,则会将此字段用于插件。

namespace

字符串

在其中运行插件的命名空间。如果未设置,则会使用由 kubeconfig 文件指定的默认设置。

init-timeout

int

Operator 初始化过程中的超时时间(以秒为单位)。

crds-dir

字符串

包含必须部署到集群中的 CRD 的目录路径。

namespaced-manifest

字符串

包含了在一个命名空间内运行的所有资源的清单文件。默认情况下,scorecard 将 deploy 目录中的 service_account.yamlrole.yamlrole_binding.yamloperator.yaml 文件组合成一个临时清单,以用作具有命名空间的清单。

global-manifest

字符串

包含全局运行(不具有命名空间)的所需资源的清单。默认情况下,scorecard 将 crds-dir 目录中的所有 CRD 组合成一个临时清单,以用作全局清单。

注意

目前,将 scorecard 与 CSV 搭配使用时不允许通过 CLI、配置文件或 CSV 注解设置多个 CR 清单。您必须在集群中停止 Operator,重新部署,并为每个经过测试的 CR 重新运行 scorecard。

其他资源

  • 您可以将 cr-manifest 或 CSV 的 metadata.annotations['alm-examples'] 设置为向 scorecard 提供 CR,但不能同时设置两者。详情请参阅 CRD 模板

4.6.3. 执行的测试

默认情况下,scorecard 工具在两个内部插件之间可以运行一组内部测试。如果为插件指定多个 CR,在每个 CR 后会完全清理测试环境,以便每个 CR 获取一个干净的测试环境。

每个测试都有一个唯一标识测试的简短名称。这在选择一个特定测试或多个测试来运行时很有用。例如:

$ operator-sdk scorecard -o text --selector=test=checkspectest
$ operator-sdk scorecard -o text --selector='test in (checkspectest,checkstatustest)'

4.6.3.1. Basic 插件

Basic 插件提供了以下基本的 Operator 测试:

表 4.16. basic 插件测试

测试描述短名称

Spec Block Exists

此测试会检查集群中创建的自定义资源,以确保所有 CR 都有一个 spec 块。此测试的最高分数为 1

checkspectest

Status Block Exists

此测试会检查集群中创建的 CR,以确保所有 CR 都有 status 块。此测试的最高分数为 1

checkstatustest

Writing Into CRs Has An Effect

此测试会读取 scorecard 代理的日志,以验证 Operator 是否正在向 API 服务器发出 PUT 和/或 POST 请求,表示它正在修改资源。此测试的最高分数为 1

writingintocrshaseffecttest

4.6.3.2. OLM 插件

olm 插件提供了以下 Operator Lifecycle Manager(OLM)集成测试:

表 4.17. olm 插件测试

测试描述短名称

OLM 捆绑包验证

此测试会验证捆绑包目录中找到的 OLM 捆绑包清单,通过捆绑包标记来指定。如果捆绑包内容包含错误,那么测试结果输出中将包括验证器日志以及验证库中的错误消息。

bundlevalidationtest

Provided APIs Have Validation

此测试会验证提供的 CR 的 CRD 是否包含一个验证部分,且 CR 中检测到的每个 specstatus 字段是否都有验证。此测试的最高分数等于 cr-manifest 选项提供的 CR 数量。

crdshavevalidationtest

Owned CRDs Have Resources Listed

此测试确保 cr-manifest 选项提供的每个 CR 的 CRD 在 CSV 的 owned CRDs 部分都有 resources 子部分。如果测试检测到未在 resources 部分中列出的已使用资源,它会在测试结束时将它们列在建议中。此测试的最高分数等于 cr-manifest 选项提供的 CR 数量。

crdshaveresourcestest

Spec Fields With Descriptors

此测试会验证自定义资源的 spec 部分中的每个字段是否都在 CSV 中列出了对应的描述符。此测试的最高分数等于 cr-manifest 选项传递的每个自定义资源的 spec 部分中的字段总数。

specdescriptorstest

Status Fields With Descriptors

此测试会验证自定义资源的 status 部分中的每个字段是否都在 CSV 中列出了对应的描述符。此测试的最高分数等于 cr-manifest 选项传递的每个自定义资源的 status 部分中的字段总数。

statusdescriptorstest

其他资源

4.6.4. 在 scorecard 中运行

先决条件

Operator 项目的以下先决条件由 scorecard 工具检查:

  • 访问运行 Kubernetes 1.11.3 或更高版本的集群。
  • 如果要使用 scorecard 检查 Operator 项目与 Operator Lifecycle Manager (OLM) 的集成,则还需要 ClusterServiceVersion (CSV) 文件。这是使用 olm-deployed 选项时的一项要求。
  • 对于不是使用 Operator SDK 生成的 Operator(非 SDK Operator):

    • 用于安装和配置 Operator 和 CR 的资源清单。
    • 支持从 KUBECONFIG 环境变量读取的配置 getter,例如 clientcmdcontroller-runtime 配置 getter。这是 scorecard 代理正常工作所需的。

流程

  1. 在 Operator 项目中定义 .osdk-scorecard.yaml 配置文件。
  2. 创建在 RBAC 文件中定义的命名空间 (role_binding)。
  3. 从 Operator 项目的根目录运行 scorecard:

    $ operator-sdk scorecard

    如果任何执行的测试都未通过,则 scorecard 返回代码为 1,如果所有选定的测试都已通过,则为 0

4.6.5. 使用 OLM 管理的 Operator 运行 scorecard

可使用集群服务版本(CSV)运行 scorecard,提供测试集群就绪和非 SDK Operator 的方法。

流程

  1. Scorecard 需要 Operator 部署 pod 中的代理容器来读取 Operator 日志。在使用 OLM 部署 Operator 之前,需要对 CSV 进行一些修改并创建一个额外的对象来运行代理。

    这一步可以手动执行或使用 bash 功能自动执行。选择以下任一方法。

    • 手动方法:

      1. 创建包含本地 kubeconfig 文件的代理服务器 secret。

        1. 使用 scorecard 代理的命名空间所有者引用生成用户名。

          $ echo '{"apiVersion":"","kind":"","name":"scorecard","uid":"","Namespace":"'<namespace>'"}' | base64 -w 0 1
          1
          <namespace> 替换为 Operator 将部署到的命名空间。
        2. 使用以下模板编写 Config 清单 scorecard-config.yaml,将 <username> 替换为上一步中生成的 base64 用户名:

          apiVersion: v1
          kind: Config
          clusters:
          - cluster:
              insecure-skip-tls-verify: true
              server: http://<username>@localhost:8889
            name: proxy-server
          contexts:
          - context:
              cluster: proxy-server
              user: admin/proxy-server
            name: <namespace>/proxy-server
          current-context: <namespace>/proxy-server
          preferences: {}
          users:
          - name: admin/proxy-server
            user:
              username: <username>
              password: unused
        3. Config 编码为 base64:

          $ cat scorecard-config.yaml | base64 -w 0
        4. 创建 Secret 清单 scorecard-secret.yaml

          apiVersion: v1
          kind: Secret
          metadata:
            name: scorecard-kubeconfig
            namespace: <namespace> 1
          data:
            kubeconfig: <kubeconfig_base64> 2
          1
          <namespace> 替换为 Operator 将部署到的命名空间。
          2
          <kubeconfig_base64> 替换为编码为 base64 的 Config
        5. 应用 secret:

          $ oc apply -f scorecard-secret.yaml
        6. 将一个指向 secret 的卷插入到 Operator 的部署中:

          spec:
            install:
              spec:
                deployments:
                - name: memcached-operator
                  spec:
                    ...
                    template:
                      ...
                      spec:
                        containers:
                        ...
                        volumes:
                        - name: scorecard-kubeconfig 1
                          secret:
                            secretName: scorecard-kubeconfig
                            items:
                            - key: kubeconfig
                              path: config
          1
          Scorecard kubeconfig 卷。
      2. 在 Operator 部署中将卷挂载和 KUBECONFIG 环境变量插入到每个容器中:

        spec:
          install:
            spec:
              deployments:
              - name: memcached-operator
                spec:
                  ...
                  template:
                    ...
                    spec:
                      containers:
                      - name: container1
                        ...
                        volumeMounts:
                        - name: scorecard-kubeconfig 1
                          mountPath: /scorecard-secret
                        env:
                        - name: KUBECONFIG 2
                          value: /scorecard-secret/config
                      - name: container2 3
                        ...
        1
        Scorecard kubeconfig 卷挂载。
        2
        Scorecard kubeconfig 环境变量。
        3
        对此容器和所有其他容器重复同一操作。
      3. 将 scorecard 代理容器插入到 Operator 的部署中:

        spec:
          install:
            spec:
              deployments:
              - name: memcached-operator
                spec:
                  ...
                  template:
                    ...
                    spec:
                      containers:
                      ...
                      - name: scorecard-proxy 1
                        command:
                        - scorecard-proxy
                        env:
                        - name: WATCH_NAMESPACE
                          valueFrom:
                            fieldRef:
                              apiVersion: v1
                              fieldPath: metadata.namespace
                        image: quay.io/operator-framework/scorecard-proxy:master
                        imagePullPolicy: Always
                        ports:
                        - name: proxy
                          containerPort: 8889
        1
        Scorecard 代理容器。
    • 自动方法:

      Community-operators 存储库有几个 bash 功能,可为您执行流程中的前面步骤。

      1. 运行以下 curl 命令:

        $ curl -Lo csv-manifest-modifiers.sh \
            https://raw.githubusercontent.com/operator-framework/community-operators/master/scripts/lib/file
      2. source csv-manifest-modifiers.sh 文件:

        $ . ./csv-manifest-modifiers.sh
      3. 创建 kubeconfig secret 文件:

        $ create_kubeconfig_secret_file scorecard-secret.yaml "<namespace>" 1
        1
        <namespace> 替换为 Operator 将部署到的命名空间。
      4. 应用 secret:

        $ oc apply -f scorecard-secret.yaml
      5. 插入 kubeconfig 卷:

        $ insert_kubeconfig_volume "<csv_file>" 1
        1
        <csv_file> 替换为 CSV 清单的路径。
      6. 插入 kubeconfig secret 挂载:

        $ insert_kubeconfig_secret_mount "<csv_file>"
      7. 插入代理容器:

        $ insert_proxy_container "<csv_file>" "quay.io/operator-framework/scorecard-proxy:master"
  2. 插入代理容器后,按照 Operator SDK 入门指南中的步骤捆绑 CSV 和 CRD,并在 OLM 上部署 Operator。
  3. 在 OLM 上部署了 Operator 后,请在 Operator 项目中定义 .osdk-scorecard.yaml 配置文件,并确保 csv-path: <csv_manifest_path>olm-deployed 选项都已设置。
  4. csv-path: <csv_manifest_path>olm-deployed 均已在 scorecard 配置文件中设置的情况下运行 scorecard:

    $ operator-sdk scorecard

4.7. 使用 Prometheus 配置内置监控

本指南介绍了 Operator SDK 通过 Prometheus Operator 提供的内置监控支持,及其对 Operator 作者的详细用途。

4.7.1. Prometheus Operator 支持

Prometheus 是一个开源系统监视和警报工具包。Prometheus Operator 会创建、配置和管理在基于 Kubernetes 的集群(如 OpenShift Container Platform)中运行的 Prometheus 集群。

默认情况下,Operator SDK 中包括帮助函数,用于在任何生成的 Go-based Operator 中自动设置指标,以便在部署了 Prometheus Operator 的集群上使用。

4.7.2. 指标帮助函数

在使用 Operator SDK 生成的基于 Go 的 Operator 中,以下函数会公开有关运行中程序的一般指标:

func ExposeMetricsPort(ctx context.Context, port int32) (*v1.Service, error)

这些指标从 controller-runtime 库 API 继承而来。默认在 0.0.0.0:8383/metrics 上提供指标。

创建一个 Service 对象并公开指标端口,之后可通过 Prometheus 访问该端口。删除领导 Pod 的 root 所有者时,Service 对象便会被垃圾回收。

以下示例出现在使用 Operator SDK 生成的所有 Operator 的 cmd/manager/main.go 文件中:

import(
    "github.com/operator-framework/operator-sdk/pkg/metrics"
    "machine.openshift.io/controller-runtime/pkg/manager"
)

var (
    // Change the below variables to serve metrics on a different host or port.
    metricsHost       = "0.0.0.0" 1
    metricsPort int32 = 8383 2
)
...
func main() {
    ...
    // Pass metrics address to controller-runtime manager
    mgr, err := manager.New(cfg, manager.Options{
        Namespace:          namespace,
        MetricsBindAddress: fmt.Sprintf("%s:%d", metricsHost, metricsPort),
    })

    ...
    // Create Service object to expose the metrics port.
    _, err = metrics.ExposeMetricsPort(ctx, metricsPort)
    if err != nil {
        // handle error
        log.Info(err.Error())
    }
    ...
}
1
在其上公开指标的主机。
2
在其上公开指标的端口。

4.7.2.1. 修改指标端口

Operator 作者可修改在其上公开指标的端口。

先决条件

  • 使用 Operator SDK 生成基于 Go 的 Operator
  • 基于 Kubernetes 的集群已部署 Prometheus Operator

流程

  • 在生成的 Operator 的 cmd/manager/main.go 文件中,在以下行中更改 metricsPort 的值:

    var metricsPort int32 = 8383

4.7.3. 服务监控器

ServiceMonitor 是 Prometheus Operator 提供的自定义资源,用于发现 Service 对象中的 Endpoints,配置 Prometheus 以监控这些 pod。

在使用 Operator SDK 生成的基于 Go 的 Operator 中,GenerateServiceMonitor() 帮助函数可以获取 Service 对象并基于该对象生成 ServiceMonitor 对象。

其他资源

4.7.3.1. 创建服务监控器

Operator 作者可使用 metrics.CreateServiceMonitor() 帮助函数来添加已创建监控服务的服务目标发现,该函数接受新创建的 Service。

先决条件

  • 使用 Operator SDK 生成基于 Go 的 Operator
  • 基于 Kubernetes 的集群已部署 Prometheus Operator

流程

  • metrics.CreateServiceMonitor() 帮助函数添加至您的 Operator 代码中:

    import(
        "k8s.io/api/core/v1"
        "github.com/operator-framework/operator-sdk/pkg/metrics"
        "machine.openshift.io/controller-runtime/pkg/client/config"
    )
    func main() {
    
        ...
        // Populate below with the Service(s) for which you want to create ServiceMonitors.
        services := []*v1.Service{}
        // Create one ServiceMonitor per application per namespace.
        // Change the below value to name of the Namespace you want the ServiceMonitor to be created in.
        ns := "default"
        // restConfig is used for talking to the Kubernetes apiserver
        restConfig := config.GetConfig()
    
        // Pass the Service(s) to the helper function, which in turn returns the array of ServiceMonitor objects.
        serviceMonitors, err := metrics.CreateServiceMonitors(restConfig, ns, services)
        if err != nil {
            // Handle errors here.
        }
        ...
    }

4.8. 配置领导选举机制

在 Operator 的生命周期中,在任意给定时间可能有多个实例在运行,例如,推出 Operator 升级程序。这种情况下,需要使用领导选举机制来避免多个 Operator 实例争用。这样可确保只有一个领导实例处理协调,其他实例均不活跃,但却会做好准备,随时接管领导实例的的工作。

有两种不同的领导选举实现可供选择,每种机制都有各自的利弊权衡问题:

leader-for-life
领导 pod 只在删除垃圾回收时放弃领导权。这种实现可以避免两个实例错误地作为领导运行,一个也被称为“裂脑(split brain)”的状态。但这种方法可能会延迟选举新的领导。例如,当领导 pod 位于无响应或分区的节点上时, pod-eviction-timeout 会规定领导 pod 从节点上删除和停止所需要的时间,默认值为 5m。详情请参见 Leader-for-life Go 文档。
Leader-with-lease
领导 pod 定期更新领导租期,并在无法更新租期时放弃领导权。当现有领导 Pod 被隔离时,这种实现方式可更快速地过渡至新领导,但在某些情况下存在脑裂的可能性。详情请参见 Leader-with-lease Go 文档。

Operator SDK 默认启用 Leader-for-life 实现。请查阅相关的 Go 文档来了解这两种方法,以考虑对您的用例来说有意义的利弊得失。

以下示例演示了如何使用这两个选项。

4.8.1. 使用 Leader-for-life 选举机制

实现 Leader-for-life 选举机制时,调用 leader.Become() 会在 Operator 重试时进行阻止,直至通过创建名为 memcached-operator-lock 的配置映射使其成为领导:

import (
  ...
  "github.com/operator-framework/operator-sdk/pkg/leader"
)

func main() {
  ...
  err = leader.Become(context.TODO(), "memcached-operator-lock")
  if err != nil {
    log.Error(err, "Failed to retry for leader lock")
    os.Exit(1)
  }
  ...
}

如果 Operator 不在集群内运行,则只会返回 leader.Become() 而无任何错误,以跳过该领导选举机制,因其无法检测 Operator 的名称。

4.8.2. 使用 Leader-with-lease 选举机制

Leader-with-lease 实现可使用 Manager Options 来启用以作为领导选举机制:

import (
  ...
  "sigs.k8s.io/controller-runtime/pkg/manager"
)

func main() {
  ...
  opts := manager.Options{
    ...
    LeaderElection: true,
    LeaderElectionID: "memcached-operator-lock"
  }
  mgr, err := manager.New(cfg, opts)
  ...
}

当 Operator 没有在集群中运行时,Manager 会在启动时返回一个错误,因为它无法检测到 Operator 的命名空间,以便为领导选举机制创建配置映射。您可通过设置 Manager 的 LeaderElectionNamespace 选项来覆盖该命名空间。

4.9. Operator SDK CLI 参考

本指南记录 Operator SDK CLI 命令及其语法:

$ operator-sdk <command> [<subcommand>] [<argument>] [<flags>]

4.9.1. build

operator-sdk build 命令编译代码并构建可执行文件。构建 完成后,会使用本地容器引擎构建镜像。之后必须推送至远程 registry。

表 4.18. build 参数

参数描述

<image>

要构建的容器镜像,如 quay.io/example/operator:v0.0.1

表 4.19. build 标记

标记描述

--enable-tests (bool)

通过在镜像中添加测试二进制文件来启用集群内测试。

--namespaced-manifest (string)

用于测试的命名空间资源清单的路径。默认值:deploy/operator.yaml

--test-location (string)

测试位置。默认值: ./test/e2e

-h, --help

使用方法帮助输出。

如果设定了 --enable-testsbuild 命令还会构建测试二进制文件,将其添加到容器镜像中,并生成一个 deploy/test-pod.yaml 文件,允许用户在群集上作为 pod 运行测试。

例如:

$ operator-sdk build quay.io/example/operator:v0.0.1

输出示例

building example-operator...

building container quay.io/example/operator:v0.0.1...
Sending build context to Docker daemon  163.9MB
Step 1/4 : FROM alpine:3.6
 ---> 77144d8c6bdc
Step 2/4 : ADD tmp/_output/bin/example-operator /usr/local/bin/example-operator
 ---> 2ada0d6ca93c
Step 3/4 : RUN adduser -D example-operator
 ---> Running in 34b4bb507c14
Removing intermediate container 34b4bb507c14
 ---> c671ec1cff03
Step 4/4 : USER example-operator
 ---> Running in bd336926317c
Removing intermediate container bd336926317c
 ---> d6b58a0fcb8c
Successfully built d6b58a0fcb8c
Successfully tagged quay.io/example/operator:v0.0.1

4.9.2. completion

operator-sdk completion 命令生成 shell completion,以便更迅速、更轻松地发出 CLI 命令。

表 4.20. completion 子命令

子命令描述

bash

生成 bash completion。

zsh

生成 zsh completion。

表 4.21. completion 标记

标记描述

-h, --help

使用方法帮助输出。

例如:

$ operator-sdk completion bash

输出示例

# bash completion for operator-sdk                         -*- shell-script -*-
...
# ex: ts=4 sw=4 et filetype=sh

4.9.3. print-deps

operator-sdk print-deps 命令打印 Operator 所需的最新 Golang 软件包和版本。默认以列示格式打印。

表 4.22. print-deps 标记

标记描述

--as-file

Gopkg.toml 格式打印软件包和版本。

例如:

$ operator-sdk print-deps --as-file

输出示例

required = [
  "k8s.io/code-generator/cmd/defaulter-gen",
  "k8s.io/code-generator/cmd/deepcopy-gen",
  "k8s.io/code-generator/cmd/conversion-gen",
  "k8s.io/code-generator/cmd/client-gen",
  "k8s.io/code-generator/cmd/lister-gen",
  "k8s.io/code-generator/cmd/informer-gen",
  "k8s.io/code-generator/cmd/openapi-gen",
  "k8s.io/gengo/args",
]

[[override]]
  name = "k8s.io/code-generator"
  revision = "6702109cc68eb6fe6350b83e14407c8d7309fd1a"
...

4.9.4. generate

operator-sdk generate 命令调用特定生成器以便根据需要生成代码。

4.9.4.1. crds

generate crds 子命令在 deploy/crds/__crd.yaml 下生成自定义资源定义(CRD)或更新它们(如果已存在)。生成的 OpenAPI V3 validation YAML 为 validation 对象。

表 4.23. generate crds 标记

标记描述

--crd-version(字符串)

要生成的 CRD 版本。默认: v1beta1

-h--help

关于 generate crds 的帮助

例如:

$ operator-sdk generate crds
$ tree deploy/crds

输出示例

├── deploy/crds/app.example.com_v1alpha1_appservice_cr.yaml
└── deploy/crds/app.example.com_appservices_crd.yaml

4.9.4.2. csv

csv 子命令会编写一个集群服务版本(CSV)清单,用于 Operator Lifecycle Manager (OLM)。它还会选择性地将 CRD 文件写入 deploy/olm-catalog/<operator_name>/<csv_version>

表 4.24. generate csv 标记

标记描述

--csv-channel (string)

软件包清单中的频道,应在此频道下注册 CSV。

--csv-config (string)

CSV 配置文件的路径。默认值:deploy/olm-catalog/csv-config.yaml

--csv-version (string)

CSV 清单的语义版本。必需。

--default-channel

使用传递到 --csv-channel 的频道作为软件包清单的默认频道。仅在设置了 --csv-channel 时有效。

--from-version (string)

CSV 清单的语义版本,用作新版本基础。

--operator-name

生成 CSV 时使用的 Operator 名称。

--update-crds

使用最新 CRD 清单更新 deploy/<operator_name>/<csv_version> 中的 CRD 清单。

例如:

$ operator-sdk generate csv \
    --csv-version 0.1.0 \
		--update-crds

输出示例

INFO[0000] Generating CSV manifest version 0.1.0
INFO[0000] Fill in the following required fields in file deploy/olm-catalog/operator-name/0.1.0/operator-name.v0.1.0.clusterserviceversion.yaml:
	spec.keywords
	spec.maintainers
	spec.provider
	spec.labels
INFO[0000] Created deploy/olm-catalog/operator-name/0.1.0/operator-name.v0.1.0.clusterserviceversion.yaml

4.9.4.3. k8s

k8s 子命令在 pkg/apis/ 下针对所有 CRD API 运行 Kubernetes code-generators。目前,k8s 只会运行 deepcopy-gen 来为所有自定义资源 (CR) 类型生成所需的 DeepCopy() 函数。

注意

每次需要更新自定义资源类型的 API(specstatus)时,便必须运行该命令。

例如:

$ tree pkg/apis/app/v1alpha1/

输出示例

pkg/apis/app/v1alpha1/
├── appservice_types.go
├── doc.go
└── register.go

$ operator-sdk generate k8s

输出示例

Running code-generation for Custom Resource (CR) group versions: [app:v1alpha1]
Generating deepcopy funcs

$ tree pkg/apis/app/v1alpha1/

输出示例

pkg/apis/app/v1alpha1/
├── appservice_types.go
├── doc.go
├── register.go
└── zz_generated.deepcopy.go

4.9.5. new

使用 operator-sdk new 命令可创建新的 Operator 应用程序,并根据输入的 <project_name> 生成(或构建)默认项目目录布局。

表 4.25. new 参数

参数描述

<project_name>

新项目的名称。

表 4.26. new 标记

标记描述

--api-version

CRD API 版本格式为 <group_name>/<version>,如 app.example.com/v1alpha1。与 ansiblehelm 类型一同使用。

--generate-playbook

生成 Ansible playbook 框架。与 ansible 类型一同使用。

--header-file <string>

包含所生成 Go 文件标题的文件路径。复制到 hack/boilerplate.go.txt

--helm-chart <string>

使用现有 Helm Chart: <url>、<repo> /<name> 或本地路径初始化 Helm Operator。

--helm-chart-repo <string>

用于所请求 Helm Chart 的 Chart 存储库 URL。

--helm-chart-version <string>

Helm Chart 的特定版本。默认:最新版本。

--help, -h

使用方法和帮助输出。

--kind <string>

CRD kind,如 AppService。与 ansiblehelm 类型一同使用。

--skip-git-init

不要将目录初始化为 Git 存储库。

--type

要初始化的 Operator 类型:goansiblehelm。默认: go

注意

从 Operator SDK v0.12.0 开始,删除了 --dep-manager 标签以及对基于 dep 的项目的支持。现在,Go 项目被构建为使用 Go 模块。

Go 项目使用方法示例

$ mkdir $GOPATH/src/github.com/example.com/

$ cd $GOPATH/src/github.com/example.com/
$ operator-sdk new app-operator

Ansible 项目使用方法示例

$ operator-sdk new app-operator \
    --type=ansible \
    --api-version=app.example.com/v1alpha1 \
    --kind=AppService

4.9.6. add

使用 operator-sdk add 命令可为项目添加控制器或资源。该命令必须从 Operator 项目根目录运行。

表 4.27. add 子命令

子命令描述

api

pkg/apis 下为新自定义资源(CR)添加一个新的 API 定义,并在 deploy/crds/ 下生成自定义资源定义(CRD)和 CR 文件。如果 pkg/apis/<group>/<version> 中已存在 API,则该命令不会覆盖,且会返回错误。

controller

pkg/controller/<kind>/ 下添加新控制器。控制器希望使用 pkg/apis/<group>/<version> 下应该已经通过 operator-sdk add api --kind=<kind> --api-version=<group/version> 命令定义的 CR 类型。如果 pkg/controller/<kind> 中已存在该 Kind 的控制器软件包,则该命令不会进行覆盖,并且会返回错误。

crd

添加 CRD 和 CR 文件。<project_name>/deploy 路径必须已经存在。需要 --api-version--kind 标记来生成新的 Operator 应用程序。

  • 生成的 CRD 文件名: <project_name>/deploy/crds/<group>_<version>_<kind>_crd.yaml
  • 生成的 CR 文件名: <project_name>/deploy/crds/<group>_<version>_<kind>_cr.yaml

表 4.28. add api 标记

标记描述

--api-version (string)

CRD API 版本格式为 <group_name>/<version>,如 app.example.com/v1alpha1

--kind (string)

CRD Kind(如 AppService)。

例如:

$ operator-sdk add api \
    --api-version app.example.com/v1alpha1 \
    --kind AppService

输出示例

Create pkg/apis/app/v1alpha1/appservice_types.go
Create pkg/apis/addtoscheme_app_v1alpha1.go
Create pkg/apis/app/v1alpha1/register.go
Create pkg/apis/app/v1alpha1/doc.go
Create deploy/crds/app_v1alpha1_appservice_cr.yaml
Create deploy/crds/app_v1alpha1_appservice_crd.yaml
Running code-generation for Custom Resource (CR) group versions: [app:v1alpha1]
Generating deepcopy funcs

$ tree pkg/apis

输出示例

pkg/apis/
├── addtoscheme_app_appservice.go
├── apis.go
└── app
    └── v1alpha1
        ├── doc.go
        ├── register.go
        └── types.go

$ operator-sdk add controller \
    --api-version app.example.com/v1alpha1 \
    --kind AppService

输出示例

Create pkg/controller/appservice/appservice_controller.go
Create pkg/controller/add_appservice.go

$ tree pkg/controller

输出示例

pkg/controller/
├── add_appservice.go
├── appservice
│   └── appservice_controller.go
└── controller.go

$ operator-sdk add crd \
    --api-version app.example.com/v1alpha1 \
    --kind AppService

输出示例

Generating Custom Resource Definition (CRD) files
Create deploy/crds/app_v1alpha1_appservice_crd.yaml
Create deploy/crds/app_v1alpha1_appservice_cr.yaml

4.9.7. test

operator-sdk test 命令可在本地测试 Operator。

4.9.7.1. local

local 子命令在本地运行使用 Operator SDK 测试框架构建的 Go 测试。

表 4.29. test local 参数

参数描述

<test_location> (string)

端到端(e2e)测试文件的位置,例如 ./test/e2e/

表 4.30. test local 标记

标记描述

--kubeconfig (string)

集群的 kubeconfig 位置。默认值:~/.kube/config

--global-manifest (string)

全局资源清单的路径。默认值:deploy/crd.yaml

--namespaced-manifest (string)

按测试的、命名空间资源的清单路径。默认将 deploy/service_account.yamldeploy/rbac.yamldeploy/operator.yaml 合并到一起。

--namespace (string)

如果非空,则为在其中运行测试的单个命名空间,如 operator-test。默认值: ""

--go-test-flags (string)

要传递到 go test 的额外参数,例如 -f "-v -parallel=2"

--up-local

使用 go run 在本地运行 Operator,而非作为集群中的镜像运行。

--no-setup

禁用测试资源创建。

--image (string)

使用与命名空间清单中指定的镜像不同的 Operator 镜像。

-h, --help

使用方法帮助输出。

例如:

$ operator-sdk test local ./test/e2e/

输出示例

ok  	github.com/operator-framework/operator-sdk-samples/memcached-operator/test/e2e	20.410s

4.9.8. run

operator-sdk run 命令提供可在各种环境中启动 Operator 的选项。

表 4.31. run 参数

参数描述

--kubeconfig (string)

Kubernetes 配置文件的文件路径。默认值: $HOME/.kube/config

--local

Operator 通过构建 Operator 二进制文件在本地运行,该二进制文件可使用 kubeconfig 文件来访问 Kubernetes 集群。

--namespace (string)

Operator 监视是否发生变化的命名空间。默认值:default

--operator-flags

本地 Operator 可能需要的标记。示例:--flag1 value1 --flag2=value2。仅限与 --local 标记一起使用。

-h, --help

使用方法帮助输出。

4.9.8.1. --local

--local 标记通过构建 Operator 二进制文件来启动本地机器上的 Operator,该二进制文件可使用 kubeconfig 文件来访问 Kubernetes 集群。

例如:

$ operator-sdk run --local \
  --kubeconfig "mycluster.kubecfg" \
  --namespace "default" \
  --operator-flags "--flag1 value1 --flag2=value2"

以下示例使用默认 kubeconfig,即默认的命名空间环境变量,并为 Operator 传递标记。要使用 Operator 标记,您的 Operator 必须知道如何处理该选项。例如,对于理解 resync-interval 标记的 Operator 来说:

$ operator-sdk run --local --operator-flags "--resync-interval 10"

如果您计划使用与默认命名空间不同的命名空间,请使用 --namespace 标记来更改 Operator 监视要创建自定义资源 (CR) 的位置:

$ operator-sdk run --local --namespace "testing"

要实现这一目的,您的 Operator 必须负责处理 WATCH_NAMESPACE 环境变量。这可通过使用 Operator 中的 utility 函数 k8sutil.GetWatchNamespace 来完成。

4.10. 附录

4.10.1. Operator 项目构建布局

Operator-sdk CLI 会为每个 Operator 项目生成大量软件包。以下部分描述每个生成的文件和目录的基本概要。

4.10.1.1. 基于 Go 的项目

使用 operator-sdk new 命令生成的基于 Go 的 Operator 项目(默认类型)包含以下目录和文件:

文件/文件夹用途

cmd/

包含 manager/main.go 文件,该文件是 Operator 的主程序。这会实例化一个新的管理器,它会在 pkg/apis/ 下注册所有自定义资源定义(CRD),并启动 pkg/controllers/ 下的所有控制器。

pkg/apis/

包含定义 CRD API 的目录树。用户需要编辑 pkg/apis/<group>/<version>/<kind>_types.go 文件,为每个资源类型定义 API,并在控制器中导入这些软件包以监视这些资源类型。

pkg/controller

pkg 包含控制器实现。用户需要编辑 pkg/controller/<kind> /<kind>_controller.go 文件,以定义控制器处理指定 kind 资源类型的协调逻辑。

build/

包含用于构建 Operator 的 Dockerfile 和构建脚本。

deploy/

包含各种 YAML 清单,用于注册 CRD、设置 RBAC 和将 Operator 部署为部署。

Gopkg.toml
Gopkg.lock

描述该 Operator 外部依赖项的 Go Dep 清单。

vendor/

Golang vendor 文件夹,其中包含满足此项目导入内容的外部依赖项的本地副本。Go Dep 可直接管理 vendor。

4.10.1.2. 基于 Helm 的项目

使用 operator-sdk new --type helm 命令生成的基于 Helm 的 Operator 项目(默认类型)包含以下目录和文件:

文件/文件夹用途

deploy/

包含各种 YAML 清单,用于注册 CRD、设置 RBAC 和将 Operator 部署为 Deployment。

helm-charts/<kind>

包含使用 helm create 命令初始化的 Helm Chart。

build/

包含用于构建 Operator 的 Dockerfile 和构建脚本。

watches.yaml

包含 group/version/kind(GVK)和 Helm Chart 位置。

第 5 章 红帽 Operator

5.1. Cloud Credential Operator

用途

Cloud Credential Operator 将云供应商凭证作为 Kubernetes 自定义资源定义 (CRD) 进行管理。

project

openshift-cloud-credential-operator

CRD

  • credentialsrequests.cloudcredential.openshift.io

    • Scope: Namespaced
    • CR: credentialsrequest
    • Validation: Yes

Configuration objects

不需要配置。

备注

  • Cloud Credential Operator 使用来自 kube-system/aws-creds 的凭证。
  • Cloud Credential Operator 基于 credentialsrequest 创建 secret。

5.2. Cluster Authentication Operator

用途

Cluster Authentication Operator 在集群中安装并维护 Authentication 自定义资源,并可以通过以下方式查看:

$ oc get clusteroperator authentication -o yaml

project

cluster-authentication-operator

5.3. Cluster Autoscaler Operator

用途

Cluster Autoscaler Operator 使用 cluster-api 供应商管理 OpenShift Cluster Autoscaler 的部署。

project

cluster-autoscaler-operator

CRD

  • ClusterAutoscaler:这是一个单一的资源,用于控制集群自动扩展实例的配置。Operator 只响应受管命名空间中名为 defaultClusterAutoscaler 资源,即 WATCH_NAMESPACE 环境变量的值。
  • MachineAutoscaler:此资源针对一个节点组,并管理注解来为那个组启用和配置自动扩展, minmax 的值。目前只能将 MachineSet 对象作为目标。

5.4. Cluster Image Registry Operator

用途

Cluster Image Registry Operator 管理 OpenShift Container Platform registry 的单个实例。它管理 registry 的所有配置,包括创建存储。

在初始启动时,Operator 会基于集群中检测到的配置创建默认的 image-registry 资源实例。这代表了根据云供应商要使用的云存储类型。

如果没有足够的信息来定义完整的 image-registry 资源,则会定义一个不完整的资源,Operator 将更新资源状态以提供缺失的内容。

Cluster Image Registry Operator在openshift-image-registry命名空间中运行,并管理该位置中的 registry 实例。registry的所有配置和工作负载资源都位于该命名空间中。

project

cluster-image-registry-operator

5.5. Cluster Monitoring Operator

用途

Cluster Monitoring Operator 管理并更新 OpenShift Container Platform 上部署的基于 Prometheus 的集群监控堆栈。

project

openshift-monitoring

CRD

  • alertmanagers.monitoring.coreos.com

    • Scope: Namespaced
    • CR: alertmanager
    • Validation: Yes
  • prometheuses.monitoring.coreos.com

    • Scope: Namespaced
    • CR: prometheus
    • Validation: Yes
  • prometheusrules.monitoring.coreos.com

    • Scope: Namespaced
    • CR: prometheusrule
    • Validation: Yes
  • servicemonitors.monitoring.coreos.com

    • Scope: Namespaced
    • CR: servicemonitor
    • Validation: Yes

Configuration objects

$ oc -n openshift-monitoring edit cm cluster-monitoring-config

5.6. Cluster Network Operator

用途

Cluster Network Operator 在 OpenShift Container Platform 集群上安装并升级网络组件。

5.7. OpenShift Controller Manager Operator

用途

OpenShift Controller Manager Operator 在集群中安装和维护 OpenShiftControllerManager 自定义资源,并可使用以下方法查看:

$ oc get clusteroperator openshift-controller-manager -o yaml

自定义资源(CRD) openshiftcontrollermanagers.operator.openshift.io 可以在具有以下内容的集群中查看:

$ oc get crd openshiftcontrollermanagers.operator.openshift.io -o yaml

Project(项目)

cluster-openshift-controller-manager-operator

5.8. Cluster Samples Operator

用途

Cluster Samples Operator 管理存储在 openshift 命名空间中的示例镜像流和模板。

在初始启动时,Operator 会创建默认样本配置资源来启动镜像流和模板的创建。配置对象是一个集群范围内的对象,它带有一个键 cluster 和类型 configs.samples

镜像流是基于 Red Hat Enterprise Linux CoreOS (RHCOS) 的 OpenShift Container Platform 镜像流,指向 registry.redhat.io 上的镜像。同样,模板也被归类为 OpenShift Container Platform 模板。

Cluster Samples Operator 部署包含在 openshift-cluster-samples-operator 命名空间中。在开始时,内部 registry 中的镜像流导入逻辑和 API 服务器使用安装 pull secret 与 registry.redhat.io 进行身份验证。如果管理员更改了用于示例镜像流的 registry,则管理员可在 openshift 命名空间中创建额外的 secret。如果创建,这些 secret 包含用于简化镜像导入所需的 dockerconfig.json 的内容。

Cluster Samples Operator 的镜像包含关联的 OpenShift Container Platform 发行版本的镜像流和模板定义。Cluster Samples Operator 创建示例后,它会添加一个注解,表示其兼容的 OpenShift Container Platform 版本。Operator 使用此注解来确保每个示例与兼容发行版本匹配。清单(inventory)以外的示例会与跳过的示例一样被忽略。

只要版本注解没有修改或删除,则允许对 Operator 管理的任何样本进行修改。但是,在升级中,当版本注解改变时,这些修改可能会被替换,因为样本会使用更新的版本进行更新。Jenkins 镜像是安装后镜像有效负载的一部分,并直接标记到镜像流中。

Samples Operator 配置资源包含一个终结器(finalizer),它会在删除时清除以下内容:

  • Operator 管理的镜像流
  • Operator 管理的模板。
  • Operator 生成的配置资源。
  • 集群状态资源。

删除样本资源后,Samples Operator 会使用默认配置重新创建资源。

project

cluster-samples-operator

5.9. Cluster Storage Operator

用途

Cluster Storage Operator 设置 OpenShift Container Platform 集群范围内的存储默认设置。它确保了为 OpenShift Container Platform 集群存在一个默认存储类。

project

cluster-storage-operator

Configuration

不需要配置。

备注

  • Cluster Storage Operator 支持 Amazon Web Services (AWS) 和 Red Hat OpenStack Platform (RHOSP)。
  • 创建的存储类可以通过编辑其注解来实现非默认设置,但只要 Operator 运行,存储类就无法被删除。

5.10. Cluster Version Operator

用途

project

cluster-version-operator

5.11. Console Operator

用途

Console Operator 在集群中安装和维护 OpenShift Container Platform web 控制台。

project

console-operator

5.12. DNS Operator

用途

DNS Operator 部署并管理 CoreDNS,以为 pod 提供名称解析服务。它在 OpenShift Container Platform 中启用了基于 DNS 的 Kubernetes 服务发现。

Operator 根据集群的配置创建可正常工作的默认部署。

  • 默认集群域是 cluster.local
  • CoreDNS Corefile 和 Kubernetes 插件配置还不被支持。

DNS Operator 把 CoreDNS 做为一个 Kubernetes 守护进程集进行管理。它会使用一个带有静态 IP 的服务向外界公开这个功能。CoreDNS 在集群中的所有节点上运行。

project

cluster-dns-operator

5.13. etcd 集群 Operator

用途

etcd 集群 Operator 自动执行 etcd 集群扩展,启用 etcd 监控和指标,并简化灾难恢复流程。

project

cluster-etcd-operator

CRD

  • etcds.operator.openshift.io

    • Scope: Cluster
    • CR: etcd
    • Validation: Yes

Configuration objects

$ oc edit etcd cluster

5.14. Ingress Operator

用途

Ingress Operator 配置并管理 OpenShift Container Platform 路由。

project

openshift-ingress-operator

CRD

  • clusteringresses.ingress.openshift.io

    • Scope: Namespaced
    • CR: clusteringresses
    • Validation: No

Configuration objects

  • Cluster config

    • 类型名:clusteringresses.ingress.openshift.io
    • 实例名称: default
    • 查看命令:

      $ oc get clusteringresses.ingress.openshift.io -n openshift-ingress-operator default -o yaml

备注

Ingress Operator 在 openshift-ingress 项目中设置路由,并为路由创建部署:

$ oc get deployment -n openshift-ingress

Ingress Operator 使用来自 network/cluster 状态的 clusterNetwork[].cidr 来决定受管入口控制器(路由器)应该在其中操作的模式(IPv4、IPv6 或双堆栈)。例如,如果 clusterNetwork 只包含 v6 cidr,则 ingress 控制器以 IPv6 模式操作。

在以下示例中,Ingress Operator 管理的 ingress 控制器将以 IPv4 模式运行,因为只有一个集群网络存在,网络是 IPv4 cidr

$ oc get network/cluster -o jsonpath='{.status.clusterNetwork[*]}'

输出示例

map[cidr:10.128.0.0/14 hostPrefix:23]

5.15. Kubernetes API Server Operator

用途

Kubernetes API Server Operator 管理并更新在 OpenShift Container Platform 上部署的 Kubernetes API 服务器。Operator 基于 OpenShift library-go 框架,并使用 Cluster Version Operator (CVO) 安装。

project

openshift-kube-apiserver-operator

CRD

  • kubeapiservers.operator.openshift.io

    • Scope: Cluser
    • CR: kubeapiserver
    • Validation: Yes

Configuration objects

$ oc edit kubeapiserver

5.16. Kubernetes Controller Manager Operator

用途

Kubernetes Controller Manager Operator 管理并更新在 OpenShift Container Platform 上部署的 Kubernetes Controller Manager。Operator 基于 OpenShift library-go 框架,并通过 Cluster Version Operator (CVO) 安装。

它包含以下组件:

  • Operator
  • Bootstrap 清单解析器
  • 基于静态 pod 的安装程序
  • 配置观察

默认情况下,Operator 通过 metrics 服务公开 Prometheus 指标数据。

project

cluster-kube-controller-manager-operator

5.17. Kubernetes Scheduler Operator

用途

Kubernetes Scheduler Operator 管理并更新在 OpenShift Container Platform 上部署的 Kubernetes 调度程序。Operator 基于 OpenShift Container Platform library-go 框架,它与 Cluster Version Operator (CVO) 一起安装。

Kubernetes Scheduler Operator 包含以下组件:

  • Operator
  • Bootstrap 清单解析器
  • 基于静态 pod 的安装程序
  • 配置观察

默认情况下,Operator 通过 metrics 服务公开 Prometheus 指标数据。

project

cluster-kube-scheduler-operator

Configuration

Kubernetes 调度程序的配置是以下合并的结果:

  • 默认配置
  • 从 spec schedulers.config.openshift.io 获得的配置。

所有这些都是稀疏配置,无效的 JSON 片断会在结尾进行合并,以便形成有效的配置。

5.18. Machine API Operator

用途

Machine API Operator 管理用于扩展 Kubernetes API 的特定目的自定义资源定义(CRD)、控制器和 RBAC 对象的生命周期。它声明集群中机器的所需状态。

project

machine-api-operator

CRD

  • MachineSet
  • 机器
  • MachineHealthCheck

5.19. Machine Config Operator

用途

Machine Congig Operator 管理并应用基本操作系统和容器运行时的配置和更新,包括内核和 kubelet 之间的所有配置和更新。

有四个组件:

  • machine-config-server:为加入集群的新机器提供 Ignition 配置。
  • machine-config-controller:协调机器升级到 MachineConfig 对象定义的配置。提供用来控制单独一组机器升级的选项。
  • machine-config-daemon:在更新过程中应用新机器配置。验证并验证机器的状态到请求的机器配置。
  • machine-config:提供安装、首次启动和更新一个机器的完整机器配置源。

project

openshift-machine-config-operator

5.20. Marketplace Operator

用途

Marketplace Operator 是一个将非集群 Operator 放置到集群中的机制。

project

operator-marketplace

5.21. Node Tuning Operator

用途

Node Tuning Operator 可以帮助您通过编排 Tuned 守护进程来管理节点级别的性能优化。大多数高性能应用程序都需要一定程度的内核级性能优化。Node Tuning Operator 为用户提供了一个统一的、节点一级的 sysctl 管理接口,并可以根据具体用户的需要灵活地添加自定义性能优化设置。

Operator 将为 OpenShift Container Platform 容器化 Tuned 守护进程作为一个 Kubernetes 守护进程集进行管理。它保证了自定义性能优化设置以可被守护进程支持的格式传递到在集群中运行的所有容器化的 Tuned 守护进程中。相应的守护进程会在集群的所有节点上运行,每个节点上运行一个。

在发生触发配置集更改的事件时,或通过接收和处理终止信号安全终止容器化 Tuned 守护进程时,容器化 Tuned 守护进程所应用的节点级设置将被回滚。

在版本 4.1 及更高版本中,OpenShift Container Platform 标准安装中包含了 Node Tuning Operator。

project

cluster-node-tuning-operator

5.22. Operator Lifecycle Manager Operators

用途

Operator Lifecycle Manager(OLM)可帮助用户安装、更新和管理所有 Kubernetes 原生应用程序(Operator)以及在 OpenShift Container Platform 集群中运行的关联服务的生命周期。它是 Operator Framework 的一部分,后者是一个开源工具包,用于以有效、自动化且可扩展的方式管理 Operator。

图 5.1. Operator Lifecycle Manager 工作流

OLM 工作流

OLM 默认在 OpenShift Container Platform 4.5 中运行,辅助集群管理员对集群上运行的 Operator 进行安装、升级和授予访问权。OpenShift Container Platform Web 控制台提供一些管理界面,供集群管理员安装 Operator,以及为特定项目授权以便使用集群上的可用 Operator 目录。

开发人员通过自助服务体验,无需成为相关问题的专家也可自由置备和配置数据库、监控和大数据服务的实例,因为 Operator 已将相关知识融入其中。

CRD

Operator Lifecycle Manager (OLM) 由两个 Operator 组成,分别为:OLM Operator 和 Catalog Operator。

每个 Operator 均负责管理 CRD,而 CRD 是 OLM 的框架基础:

表 5.1. 由 OLM 和 Catalog Operator 管理的 CRD

资源短名称所有者描述

ClusterServiceVersion (CSV)

csv

OLM

应用程序元数据:名称、版本、图标、所需资源、安装等。

InstallPlan

ip

Catalog

为自动安装或升级 CSV 而需创建的资源的计算列表。

CatalogSource

catsrc

Catalog

定义应用程序的 CSV、CRD 和软件包存储库。

Subscription

sub

Catalog

用于通过跟踪软件包中的频道来保持 CSV 最新。

OperatorGroup

og

OLM

将部署在同一命名空间中的所有 Operator 配置为 OperatorGroup 对象,以便在一系列命名空间或集群范围内监视其自定义资源 ( CR)。

每个 Operator 还负责创建以下资源:

表 5.2. 由 OLM 和 Catalog Operator 创建的资源

资源所有者

部署

OLM

ServiceAccounts

(Cluster)Roles

(Cluster)RoleBindings

CustomResourceDefinitions (CRD)

Catalog

ClusterServiceVersions

OLM Operator

集群中存在 CSV 中指定需要的资源后,OLM Operator 将负责部署由 CSV 资源定义的应用程序。

OLM Operator 不负责创建所需资源;用户可选择使用 CLI 手动创建这些资源,也可选择使用 Catalog Operator 来创建这些资源。这种关注点分离的机制可以使得用户逐渐增加他们选择用于其应用程序的 OLM 框架量。

OLM Operator 使用以下工作流:

  1. 观察命名空间中的集群服务版本(CSV),并检查是否满足要求。
  2. 如果满足要求,请运行 CSV 的安装策略。

    注意

    CSV 必须是 Operator 组的活跃成员,才可运行该安装策略。

Catalog Operator

Catalog Operator 负责解析和安装集群服务版本(CSV)以及它们指定的所需资源。另外还负责监视频道中的目录源中是否有软件包更新,并将其升级(可选择自动)至最新可用版本。

要跟踪频道中的软件包,您可以创建一个 Subscription 对象来配置所需的软件包、频道和 CatalogSource 对象,以便拉取更新。在找到更新后,便会代表用户将一个适当的 InstallPlan 对象写入命名空间。

Catalog Operator 使用以下工作流:

  1. 连接到集群中的每个目录源。
  2. 监视是否有用户创建的未解析安装计划,如果有:

    1. 查找与请求名称相匹配的 CSV,并将此 CSC 添加为已解析的资源。
    2. 对于每个受管或所需 CRD,将其添加为已解析的资源。
    3. 对于每个所需 CRD,找到管理相应 CRD 的 CSV。
  3. 监视是否有已解析的安装计划并为其创建已发现的所有资源(用户批准或自动)。
  4. 观察目录源和订阅并根据它们创建安装计划。

Catalog Registry

Catalog Registry 存储 CSV 和 CRD 以便在集群中创建,并存储有关软件包和频道的元数据。

package manifest 是 Catalog Registry 中的一个条目,用于将软件包标识与 CSV 集相关联。在软件包中,频道指向特定 CSV。因为 CSV 明确引用了所替换的 CSV,软件包清单向 Catalog Operator 提供了将 CSV 更新至频道中最新版本所需的信息,逐步安装和替换每个中间版本。

其他资源

如需更多信息,请参阅有关了解 Operator Lifecycle Manager(OLM) 的章节。

5.23. OpenShift API Server Operator

用途

OpenShift API Server Operator 在集群中安装和维护 openshift-apiserver

project

openshift-apiserver-operator

CRD

  • openshiftapiservers.operator.openshift.io

    • Scope: Cluster
    • CR: openshiftapiserver
    • Validation: Yes

5.24. Prometheus Operator

用途

Kubernetes 的 Prometheus Operator 为 Kubernetes 服务以及 Prometheus 实例的部署和管理提供简单的监控定义。

安装后,Prometheus Operator 会提供以下功能:

  • 创建和销毁:使用这个 Operator,可以方便地在 Kubernetes 命名空间、特定应用程序或团队中启动一个 Prometheus 实例。
  • 简单配置:设置 Prometheus 的基本配置,如版本、持久性、保留策略以及原生 Kubernetes 资源的副本。
  • 使用标识(label)实现目标服务:可以基于Kubernetes 标识查询自动产生监控目标配置,因此用户不需要了解 Prometheus 的配置语言。

project

prometheus-operator

法律通告

Copyright © 2021 Red Hat, Inc.
The text of and illustrations in this document are licensed by Red Hat under a Creative Commons Attribution–Share Alike 3.0 Unported license ("CC-BY-SA"). An explanation of CC-BY-SA is available at http://creativecommons.org/licenses/by-sa/3.0/. In accordance with CC-BY-SA, if you distribute this document or an adaptation of it, you must provide the URL for the original version.
Red Hat, as the licensor of this document, waives the right to enforce, and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent permitted by applicable law.
Red Hat, Red Hat Enterprise Linux, the Shadowman logo, the Red Hat logo, JBoss, OpenShift, Fedora, the Infinity logo, and RHCE are trademarks of Red Hat, Inc., registered in the United States and other countries.
Linux® is the registered trademark of Linus Torvalds in the United States and other countries.
Java® is a registered trademark of Oracle and/or its affiliates.
XFS® is a trademark of Silicon Graphics International Corp. or its subsidiaries in the United States and/or other countries.
MySQL® is a registered trademark of MySQL AB in the United States, the European Union and other countries.
Node.js® is an official trademark of Joyent. Red Hat is not formally related to or endorsed by the official Joyent Node.js open source or commercial project.
The OpenStack® Word Mark and OpenStack logo are either registered trademarks/service marks or trademarks/service marks of the OpenStack Foundation, in the United States and other countries and are used with the OpenStack Foundation's permission. We are not affiliated with, endorsed or sponsored by the OpenStack Foundation, or the OpenStack community.
All other trademarks are the property of their respective owners.