如何管理越来越多的 operator?OLM 给你答案

如何管理越来越多的 operator?OLM 给你答案

作者 | 匡大虎、阚俊宝

导读:OLM(Operator Lifecycle Manager) 作为 Operator Framework 的一部分,可以帮助用户进 Operator 的自动安装,升级及其生命周期的管理。同时 OLM 自身也是以 Operator 的形式进安装q } 1 *部署,可以说它的工作方式是以 Operators 来管理 Operators,而它面k V n q u G L [向 Operator 提供了声明式 (declarative) 的自动化管理能力也完全符合 Kubernetes 交互的设计理念。本文我们将: W d M ,来了解一下 OLM 的基本架构和安装使用。

On s ~ t h l }LM 组件模型定义

OLM 的出现是为了帮? j J ] A 0 . P助没有如大数据,云监控等领域知识的用户能够自助式地部署并管理像 etcd、大数据分析或监控服务等复杂的分布式应用。因此从它的设计目标来说,OLM 官方希望实现面向云原生应用N s 1 I提供以下几个方向上的通用管理能力,包括:

  • 生命周期管理:管理 operator 自身以及监控资源模型的升级和生命周期;

  • 服务发现:发现在集群中存在哪些 operator,这些 operators 管理了哪些资源模型以及又有哪些 operators 是可以被安装在集群中的;

  • 打包能力:提供一种标准模式用于 operator 以及依赖组件的分发,安装和升级;

  • 交互能力:在完成了上述能力的标准化后,还k ( 3 W W需要提供一种规范化的方式(如 CLI)与集群中用户定义的其他云服务进行交互。

上述在设计上的目标可以归结为下面几个方向上的需求:

  • 命名空间部署:opk P 7 & ^ c L :erator 和其管理资源模型必须被命名空间K : M 6 M # T N限制部署,这也是在多租环境X ( L R R * c C ~下实现逻辑隔离和使用 RBAC 增强访问控制的必要手段;

  • 使用自定义资源(CR)定义:使用 CR 模型是定义用户和 opero v = Jator 读写交互的首选方式;同时在一个 operator 中也是通过 CRDs 声明其自身或被其他 operator 管理的资源模型;operator 自身的行为模式配置也应当由 CRD 中的 fields 定义;

  • 依赖解析p M Q u:opera] r E , y ? ttor 在实现上只需要关心自身和其管理资源的打包,而不需关注与运行集群的连接;同时在依赖上使用动态库定义,这里以 vault-operator 为例,其部署的同时需要创建一个 etH x - u ^ ` ucd 集群作为其后{ V m }端存储;这时我们在 v( T m + ? m * Uault-operator 中不应该直接包含J J m + G etcd operator 对应容] Z ( a器,而是应该通过依赖声明的方法让 OLM 解析对应依赖。为此在 operators 中需要有一套依赖相关的定义规范;

  • 部署的幂等性:依赖解q V K J l m D析和资源安装可以重复执行,同时在应用安装过程中的问题是可恢复的;

  • 垃圾收集:原则上尽可能依赖 Kubernetes 原生的垃圾收集能力,在删除 OL2 ] W $ e w p rM 自( o 5 f X身的扩展模型 ClusterService 时需要同时清理其运行中的关联资源;同时需要保证其他 ClusterServi^ ] L ~ H rce 管理的资源不被删除;

  • 支持标签和资源发现。

基于上述设计目标,OLM 在实现中面向 OperatoE s , s &r 定义了如下模型和组件。

首先,OLM 自身包含两个 Operator:OLM Operator 和 C- A : I }atalog Operator。它们分别管理了如下几个 OLM 架构中扩展出的基础 CRD 模型:

如何管理越来越多的 operator?OLM 给你答案

在 OperaQ n x n * etor 安装管理的生命周期中 Deployment,Serviceaccount,RBAC 相关的角色和角色绑定是通过 OLM operator 创建的;Catalog OpB I _ { z s t 9erator 负责 CRDs 和 CSVs 等资= L l J [ [ 3 d X源的创建。

在介绍 OLM 的两个 Operator 之前,我们先来看下 ClusterServiceVersion 的定义,作为) q X ! I S w OLM 工作流程中的基本元素,u R Y W ^ $ 7 S它定义了在 OLM 管理下用户业务应用的元数据和运行时刻信息的集合,包括了:

  • 应用元数据(名称,描述,版本定义,链接,图标,标签等),在下一章的实战示例中我们会看到具体的定义;

  • 安装策略,包括 Operatorv 7 x z 安装过程中所需的部署集合和 service accouA u w [ d * =nts,RBAC 角色和绑定等权限集合;

  • CRDs:包括 CRD 的类型A T ^ o d,所属服务,Operator 交互的其他 K8s 原生资源和 spec,status 这些包含了模型语义信息的 fields 字段描述符等。

在对 ClusterSerG F + K H ( ; b #viceVersion 的概念有了基本了解后,我们来看下$ b , - , L S OLM O F Dperator。

首先 OLM Operator 的工作会基于 ClusterServiceV/ r D ( 0ersion,一旦 CSV 中声明的依赖资源都已经在目标集群中注册成功,OLM Operator 就会负责去安装这些资源对应的应用实例。注意这里 OLM Operai q n s Z e 5 v Otor 并不会去关注 CSV 中声明q d 2 R j r Q T的依赖资源对应的 CRD 模型的创建注册等工作,这些动作可以由用; / @ 7户的手工 kubectl 操作或是由 Catalog Opetator 来完成。这样的设计也给了用户一个逐步适应 OLM 架构并. k o o | t z c最终应用起H ~ F N : K N来的熟悉过程。另外,OQ b ;LM Operator 对依赖资源对应自定义模型的监听可以是全局 all namespaces 的,也可以只限定在指定的 namespace 下。

接着我们来认识一下 Catalog Operator,& T * ( g q x & 3它主要负责解析 CSV 中声明的依赖资源定义,同时它通过s w ) ~ # f +监听 catalob v G n wg 中X 3 J n { ( ( & T安装包对应 channels 的版本定义完成 CSV 对应的版本更新。

用户可以通过创建 Subscript: W ^ 2 tion 模型来设置 channel 中所需安装包和更新的拉取源,当一个d N . % *可用更新被发现时,一个用户对O X m s / t = X H应的 InstallPlan 模型会在相应的 namespah 7 3 d E + = V 2ce 被创建出来。当然用户也可以手动创建 InstallPlan,InstallPlan 实例中会包含目标 CSV 的定义和相关的 approval 审批策略,Catalo- ; ^ m Dg Operator 会创建相应的执行计划去创& R = : Q 2 $ /建 CSV 所需的依赖资源模型。一旦用户完成审批,Catalog Operator 就会创建 InstallPlan 中的相关资源,此时刚才提及的 OLM Operator 关注的依赖资源条件得到满足,CSV 中定义的 Operator 实例会由 OLM Operator 完成创建。

OLM 结构介绍

在上一小节中我们了解了 OLM 的基本1 u w % 3 N l I -组件模型和相关定义,本小节我们就来介绍一下它的基本架构,如下图所示:

如何管理越来越多的 operator?OLM 给你答案

首先在 Operator Framework 中提供了两个重要的元 Ope$ E J C /rator 和相应的扩展资源(如上节中介绍的 ClQ F ! _ ( : QusterServiceVersion,InstallPlan 等),用于进行用户应用 Operator 的生命周期管理。在自定义的 CSV 模型中定义了用户部署 Operator 的各类资源组合,包括 Operator 是如何部署的,OT 5 m Operator 对应管理的自定义资源类型是什么以及使用了哪些 K8s 原生资源等。

在上节的定义中我们也了解到 OLM Operator 在安装B 9 i e Q对应的 Operator 实例前要求其管理B a w } I i ! r的自定义资源模型已经被注册在目标安装集群中,而这个动作可以来自于集群管理员手动 kubectl 方式的创建,也可以利用 Catalog Operator 完成,Catalog Operator 除了可以完成目标CRD模型的注册,还负责资源模型版本的自动升级工作。其工作流程包括:

  • 保证 CRDs 和 CSVs 模型的 cache 和 index 机制,用于对应模型的版本控制和注册等动作;

  • 监听用户创建的f ~ $ I未解析 InstallPlans:

    • 寻找满足依赖条件的 CSV 模型并将其加入到已解析资源中;
    • 将所有被目标 Operator 管理或依赖的 CRD 模型2 k z y 3 U ! }加入到解析j s P资源中;
    • 寻找并管理每种依赖 CRD 对应 CS@ W @ M * o VV 模型;
  • 监听所有被解 M b Z ^ b析的 InstallPlan,[ d m # / ? 1在用户审批或自动审批完成后创建所有对应的依赖C @ V n K [ D (资源;

  • 监听 CataologSources 和 Subscriptions 模型并基于其变更创建对应的 Iy 0 !nstallPlans。

一旦 OLM Operator 监$ q { 8 _ K X 1听到 CSV 模板中安装所需依赖资源已经注册或是变更,就会启动应用 Operator 的安装和升级工作,并最终启动 Operator 自身的工作流, x U }程,在 Kubernetes 集群中创建和管理对应的自w @ Y S } I }定义资源实例模型。

OLM 的安装

在了解了 OLM 的基础架构后,我们首先来看下 OLM 的安装。在社区代码中我们找到 OLM 各项部署资源对应的模板,用户可以方便的通过修改相应I l r 8 ] 1 k部署参数完成定制化的 OLM 安装。

在官方的发布公告中我们可以找到最新的发布版本和各版本对应的安装说明。

这里p I z j 0 d l以 0.13.0 版本为例,通过以下命令执行自动g ! n L I e X X化安装脚本:

curl -L https://github.com/operator-framework/oper# y ) ? N E l aator-lifecycle-manager/releaseu n o $ V _ Zs/download/0.13.0/install.sh -o install.sh
chmod +x install.sh
./install.sh; & T [ D 2 L 0.13.0

手动安装 OLM 所需部署模板命令:

kubectl apply -f https://github.com/operator-framework/operator-lifecycle-manager/releases/download/0.13.0/crds.yaml
kubectl apply -f https://github.com/ol C +perator-framework/operator-lifecycle-C q U z = Pmanager/releases/download/0.13.0/olm.yaml

在通过 clone OLM 代码8 & A , f仓库到本地后a = S +,用户可以执行 make run-local 命令启动 minikube,Q & e z ; F b ! _并通过 minikube 自带 docker daemon 在本地 buu O S } L . v q #ild OLM 镜像,同时该命令会 E m基于仓库 deploy 目录下的 local-values.yaml 作为配置文件构建运行本地 OLM,通过 kubectl -n local get deployments 可以验证 OLM 各组件是否I / N .已经成功安装运行。

另外@ M 9针对用户y u O K r的定制化} Z ^ Z I t % h安装需求,OLM 支持通过配置如下模板指定参数来生成定制化的部署模板并安装。下面是其支持配置的模板参数:

# sets theA U o w N T E apiversion to use for rbac-resouH i | $ w ? srces. Change to `authorization.open3 h dshift.io` for openshift
rbacApiVersion: rbac.autho2 S 7rization.k8s.io
# namespace is the namesH ^ K c L Lpace= K 5 the operators will _run_
namespace: olm
# watchedNamespaces is a comma-separated list of namespaces the opek S b  d 7 Frators will _watch_ for OLM red % 7 B Q # d UsourcesJ 4 T v w -.
# Omit to enable OLM in all namespaces
way m D E tchedNamespaces: olm
# catalog_namespace is the namespace where the catalog operator will look for global catalogs.
# entries in global catalogs can be resolved in any watcr 6 X + U 2hed namespace
catalog_namespace: olm
# operator_namespace is the namespace where the operator runs
operator_namespace: operators
# OZ g * M y x o hLM operator run configuration
olm:
# OLM opeD x x A r ) 4rator doesn't d( a 6o any leader election (yet), set to 1
replicaCount:/ # l - & 1
# The image to run! R z I t X { 1. If not building a local image, use# / - 7 M sha256 image references
image:
ref: quay.io/operator-framework/olm:local
pullPolicy: IfNotPresent
service:
# port for rea1 V a n  @diness/j S @ B $ Uliveness probes
internalPort: 8080
# catR 8 z Xalog operator run conf+ } *iguration
catalog:
# Catalog operator2 l I doesn't do any leader election (ye( p n ` N $t), set to 1
replicaCount: 1
#- R n @ e The image to run. If not building a local image, use sha2s O p j56 image refer` o ? r ~ences
image:
ref: quay.io/operator-framework/olm:local
pullPolicy: IfNotPresent
service:
# port for readiness/liveness probes
internalPort: 8080

用户可以通过以下方式进行模板的定制化开发和在指定集群中的安装:

  • 创建名称如 my-values.yaml 的配置模板,用户可以参考上述模板配置t W M - @ Y { z所需参数;
  • 基于上述配置好的 my-values.yaml 模板,使用 package_release.sh 生成指定部署模板;y X L [ 5
# 第一个参数为系统兼容的h$ T y b j : .elm chart目标版本
# 第二个参数为模板指定的输出目录
# 第三个参T | 5 8 b G ) 1 )数为指定! s k 1 @的配置文件路径
./scripts/package_release.sh 1.0.0-myolm ./my-olm-deployment my-values.yaml
  • 部署指定目录下的模板文件,执行 kubectl apply -f ./my-olm-deployment/templates/

最后,用户可以通过环境变量 GLOBAL_CATALOG_5 l sNAMESPACE 定义 catalogC h 6 2 N + a operator 监听全局 catalogs 的指定 namespace,默认情况下安装过程会创建 olm 命名空间并部署 catalog oy 6 n S )perator。

依赖解析和升级管理

如同 apt/dkpg 和 yum/rpm 对于系i ? | %统组件包的管理一样,OLM 在管理 Operatork N c 版本时也会遇到依赖解析和正在运行的 operator 实例的升级管理等问题。为了保证所有 operators 在运行时刻的可用性,OLM 在依赖解析和升级管理流程中需要保证:

  • 不去安装未注册依赖 AP@ y % # x S & l CIs 的 Operator 实例;
  • 如果对s Z d于某个 Operator 的升级操作会破坏其关联组件的依赖条件时,不去进行该升级操作。

下面我们通过一些示例来了解下当前 OLM 是如何处理版本迭代下的依赖解析:

首先介绍一下 CRD 的升级,当一个待升级的 CRD 只属于单个 CSV 时,OLM 会立即对 CRD 进行升级;当 CRD 属于多个 CSV 时,CRD& P m K & H 的升级需要满足下列条件:

  • 所有当前 CRD 使用的服务版本需要包含在新的 CRD 中;
  • 所有关联了 CRD 已有服务版本的 CR(Custom Resource)实例可以通过新 CRD schema 的校验。

当你需要添加一个新版本的 CRD 时U a H z $,官方推荐的步骤是:

  1. 假如当前我们D N T 1有一个正在使用的 CRD,它的版本是 v1alpha1,此时你希望添加一个新版本 v1beta1 并且将其置为新的 storage 版本,如下:
versions:
- name: v1alpha1
served: true
storage: false
- name: v1. G 9 c , | nbeta1
served: tM r ! I X ,rue
storage: true
  1. p e O % D , Y _ Y果你的 CSV 中需要使用新版本的 CRD,我们需要保证 CSV 中的 owne1 l , s % V # _d 字段所引用的 CRD 版本是新的,如下所示/ ` h j F F & P 4
customresourcedefinitions:
owned:
- name: cluste6 p 7 rr.example.com
version: v1beta1
kind: cluster
displayName: Cluster
  1. 推送更新后的 CRD 和 CSV 到指定的仓库目录中。

当我们需要弃用或是删除一个 CRD 版本时,OLM 不允许立即删除一个正在使 w ( T W用中的 CRD 版本,而是需要首先通过将 CRD{ t ) z k 5 D 中的 serverd 字段置为 false 来弃用该版本,然后这个不被使用的^ S c F C 7 G R版本才会在接下来的 CRD 升级过程中被删除。官方推荐的删除或弃用一个 CRD 指定版本的步骤如下:

  1. 将过期r % 0 I Z Y t b的弃用 CRD 版本对应的 serverd 字段标记为 false, 表示不再使用该版本同时会在下次升级时删除此版本,如:
versions:
- nam2 ) A a 6e: v1alpha1
served: false
sto, R : jrage: true
  1. 如果当前即将过期的 CRD 版本中 sto% D @ @ + _ R crage 字段为 true,需要将其置为 false 同时将新版本的 storage 对应字段置为 true,比如:
versions:
- name: v1alpha1
served: false
st@ , }oraE N q D w ^ s 3ge: false
- name: v1beta1
served: true
storage: true
  1. 基于上述修` 3 V * b * Q改更新 CRD 模型;

  2. 在随后的升级过程中,不在服务的过期版本将会从 CRD 中完成删除,CRD 的版本终态为:
versions:
- name: v1beta1
served: true
storage: true

注意在删除指定版本的 CRD 过程中,我们需要保* a Y H k , % 8 o证该版本同时在 CRD status 中的 storedVersion 字段队列中被删除。当 OLM 发现某 storedversq 4 X L sion 在新版本 CRD 中不会再使用时会帮助我们完成相应的删除q 1 E &动作。另外我们需要保证 CSV 中关联引用的 CRD 版本在老版本被删除时及时更新。

下面我们来看a { ( x 6 { S i 8一下两个会引发升级失败的示例以及 OLM 的依赖解析逻辑:

示例 1:假如我们有 A 和 B 两个不同类型的 CRD。

  • 使用 A 的 Operator 依赖 B
  • 使用 B 的 Operator 有一个订阅(Subscription)
  • 使用 B 的 Operator 升级到了新版本 C 同时弃用了老版本 B

这样的升级得到的结果是 B 对应的 C- L { b U E ` C cRDw w ` f v b 版本没有了对应使用它的 Operato= A ! ` E & Ar 或 APIService,同时依赖它的 A 也将无法工作。

示例 2:假如我们9 n & z W # 5 B有 A 和 B 两个自定义 APl = / n j (I。

  • 使用 A 的 Operator 依赖 B
  • 使用 B 的 Operator 依赖 A
  • 使用 A 的 Operator 希望升级到 A2 版本同时弃用老版本 A,新的 Az ` M - R -2 版本依赖 B2
  • 使用 B 的 Operator 希望升级到 B2 版本同时弃用老版本 B,新的 B2 版本依赖 A2

此时如果我们只尝试升级 A 而没有同步地升级 B,即使系统可) l [ %以找到适用的升级B { - Q H E S版本,也无法完成对应 Operator 的版本升级。

为了避免上述版本迭代中可能遇到的问题z ( g 4 n z H | 2,OLM 所采用的依赖解析逻辑如下。

假设我们有运行在某一个 namespace 下的一组 operator:

  • 对于该 namespace 下的每一个 subscription 订阅,如果该 subscription 之前没有被检查过,OLM 会寻找订阅对应 source/# R k F U {package/channel 下的最新版本 CSV,并临时性地创建一个匹配新版本的 operator;如果9 w c 0 ?是已知订阅,OLM 会查询对应 source/package/channel 的更新;

  • 对于 CSV 中所依赖的每一个 API 版本,OLM 都会按照 sources 的优先级挑选一个对应的 ope} 7 = @ q E qrator,如果找到同样会临时性地添加该依赖版本的新 operator,如果没有找到对应的 operator 的话也会添加该依赖 API;

  • 此时如果有不满足 source 依赖条件的 API,系统会对被依v f * 0 |赖的 operator 进行降级(回退到上一个版本);为了满足最终的依赖条件,这个降级过程会持续进行,最坏的情况下该 namespace 下的所有 operator 仍旧K ) ` P保持原先版本;

  • 如果有新的 operator 完成解析并满足了依赖条件,它会在集群中最终创建出来;同时会有一个相关的 subscription 去订阅发现它的 channel/packaa z # / 3ge 或是 source 以继续查看是否有新版本y e o Z ` D . R的更新。

在了解了 OL* z o a VM 的依赖解析和升级管理的基本原理后,我们来看下 OLM 升级相关的工作流程 q b R G 4 O j。首先从上文中我们已经有所了解,ClusterServiceVersion(CSx T 3 _ xV),Cate A / h # H 7alogSource 和 Subscription 是 OLM 框架中和升级紧密s R f c A y =相关的三种扩展模型。在 OLM 的生态系统中,我们通过 CaK G {talogSource 来存储如 CVS 这样的 operator 元数据& u e i;OLM 会基于 CatalogSources,使用下 Operator 仓库相关 API 去查询可用或可升级的 operators;而在 CatalogSource 中,opeS ? q V ; 4rators 通S H Vchannels 来标识封装好的不^ g K o [ { 1同版本安装包。

当用户希望升级某个 operato: q r 1 # 3 jr( ! G B 时,可以通过 Subscription 来订阅具体需要安装哪个 channel 中指定版本的软件包。如果订阅中指定的包还没有被安装在目标集= t C #群中时,OLM 会安装在 catU j v $ G K = zalog/package/channel 等下载源的最新版本 operator。

在一个 CSV 定义中,我们可以通过 rej @ ( F 8places 字段声明需要替换的 oL Z 2 l j s Sperator,OLM 在收到请求后会从不同的 ch_ U H : q } hannels 中寻找能够被安装的 CSV 定义并最终将它们构建出一个 DAG(有向无环图),在这个过程中 channels 可以被认为是更新 DAG 的入口。在升级过程中,如果 OLM 发现在可升级的最新版本和当前版本之间还有未安装的中间版本,系统会自动构建出一条升级路径并保证路径上中间I n N 7 s ; K 3版本的安装。比如当前我们有一个正在运行的 operator,它的运行版本是 0.1.1,此时 OLM 在收到` / $更新请求后通过订阅的 channel 找到了 0.1.3 的最新可升级版本,同时还找到P , | 9 5 dZ ~ ! 0.1.2 这个中间版本,此时 OLM 会首先安装 0.1.2 版本 CSV 中对应的 operator 替换当前版本,并最终安装 0.1.3 替换安装成功后的 0.1.2 版本。

当然在某些状况下,比如我们遇到了一个存在严重安全漏洞的中间版本时,这样迭代升级每个版本的方式并不是一种合理和安全的方式。此时我们可以通过 skips 字段定制化安装路径以跳过指定的中间版本,如下所示:

as Q  * $ K T &piVa u Zersion: operators.coreos.com/v1alpha1
kind: ClusterServiceVersion
metadata:
nak & M c 6 E % Fme: etcdoperator.v0.9.2
namespace: placeholder
annotations:
spec:
displayName: etcd
dea p R Q | ) = 1 lscription: Etcd Operator
replaces: etcdoperator.v0.9.0
skips:
- etcdoperator.v0.9.1

如果需要忽略多个版本的安装,我们可以在 CSV 中使用如下定义:

olm.] 1 DskipRange: <semver range>

其中版本范围的定义可参考 semver,一个 skipRange 的 CSV 示例如下:

apiVersion: operatorS % $s.coreos.com/v1alpha1
kinde 8 S t m / [ ; 4: ClusterServiceVersion
metadata:
name: elasticsearch-operator.v4.1.2
nam6 ? 0 7 A % (espace: placeholder
annotations:
olm.skipR: x ]ange: '&@ 2 U 1 H L c c 7gt;=4.1.0 <4.1.2'

operator-registry

在 OLM 中,我们可以通过对 Cat` l . 3alogSource 模型来定义 IU p ` 3 cnst0 X = s 6 L = RallPlan 从哪里完成安装包的自动下载和依赖解析,同时 Subscription 通过对 channel 的订阅也可以从 CatalogSource 来拉取最新版本的安装包。本小节中我们以官方社区的 operator-registry 为~ y @ ] a例介绍一下 CatalogSource 的安装和基本使用方法。

operator-registry 主要由下列三部分组成:

  • initializer:H @ N ] E F p =负责接收用户上传的以目录为结构的 operator manifests,同时将数据导入到数据库中;
  • registry-server:包含存取 operator manifests 相关的 sqlite 数据库服务,同时对外暴露 gRPC 协议接口的服务;
  • configmap-server:负责向 registry-server 提供解析好的 operator manifest 相关 configmap(包含 operator bundle 相关的标签或 CRDH x z g 和 Cx Z v 9 [ h z SV 等配置元数据),并存入 sqlite 数据库中。

关于 operator manifes 的格式定义,在 operato+ [ t , 4 G v Qr-re0 Z p qgistry 中把在上传目录中包含的每# # J )一个 CSP e 4 ; 4V 定义单元称为一个“bundle”,每个典型的 bundle 由单个 CSV(ClusterServiceVersion)和包含其相关接口定义的单个或多个 CRD 组成,如下所示:

 # bundle示例
0.6.1
├── etcdcluster.cr| ( P ? Ed.yaml
└── etcdope$  O ] 5 rator.cz m . V # s g =lus| ] P E 6 ^ sterserviceversion.yaml

当导H | 7 I x i - b入 manifests 到数据库时会包含如下的格式校验:

  • 每个 package 安装包都需要至少定义一个 channel;
  • 每一个 CSV 需要关联一个安装包中存在的s 2 _ channel;
  • 每一个 bundle 目录中有且仅有一个对应的 CSV 定义;
  • 如果 CSV 中包含相关 CRD 定义,该 CRD 必须也存在于 bundle 所在目录中;
  • 如果一个| $ X CSV 在 replaces 定义中被其他 CSV 取代,则对应的新旧 CSV 均需要存在于 package 中。

对于 manifests 中& = y不同软件包对应的 bundle 目录格式,原则上最好要保持一个清晰的目录结构,这里我们来看官方的一个 manifest 示例,其他 manifest 示例请见:

manifests
├── etcd
│   ├── 0.6.1
│   │   ├── etcy } c ) = 3 0 ;dcluster.crd.yamlI H ` s t
│   │   └── etcdoperator.clu9 Z $ 8 W Nsterserviceversion.yaml
│   ├── 0.9.0
│   │   ├── etcdbackup.crd.yaml
│   │   ├── etcdcluster.crd.yaml
│   │   ├── etcdoO 3 @  W 0 T Zperator.v0.9.0.clusterserviceversion.yaml
│   │   └── etcdrestore.i , 7 . , k d {crd.yaml
│   ├── 0.9.2
│   │   ├── etcdbr _ { G ? P 0ackup.crd.yaml
│   │   ├── etcdcluster.crd.yaml
│   │   ├── etcdoperator.v0.9.2| m T 1 t q h.clusterser X ( p 6 = @ V Evicevey s ) p t c  q mrsion.yaml
│   │   └── etcdrestorf q ~ 4 ( _ K X Oe.cB c 7 | - D ?rd.yaml
│   └── etcd.package.yaml
└── prometheus
├── 0.14.0
│   ├── alertmanager.crd.yaml
│   ├── prometheus.crd.yam1 j % w Il
│   ├── promh D & *etheuZ  m 6 Wsopr : S 4erator.0.14.0.clK 4 T aus3 $ ) J r M I I Pterser& q p Qviceversion.yaml
│   ├# s . n = k U── prometheusrule.crd.yaml
│   └── servicemonitor.crd.yaml
├── 0.15.0
│   ├── alertmanager.crd.yaml
│   ├── prometheus.crd.yaml
│   ├── prometheusoperator.0.15.0.M } U : n y yclusterserviceversion.yaml
│   ├Y V 8 ] E $ q── pr3 a / L .ometheus1 h % N mrule.crd.yaml
│   └── ser* h w Avicemonitor.crd.yaml
├── 0.22.2
│   ├── alertmanager.crd.yaml
│   ├── promE g K [ = , H  ;etheus.crd.yaml
│   ├── prometheusoperator.0.22.2.clusterserviceversion.yaml
│   ├( ]  J q Q 6── prometheusrule.crd.yaml
│   └── servicemonitor.crd.yaml
└── prometheus; Y U 3 G &.package.yaml

通过官方提供的 Dockerfile 我们可以构建出一个包含了 initia% z ) g ( H Pli] 7 nzer 和 registry-server 的y * 3 b , $ `最小集 operator-r4 ] xegistry 镜像9 O F 9 4

下面我们K G 3 w来看下 operator-registry 与 OLM 的集成,这里我们需要创建一个 CatalogSource 对象并指定使用我们 operator-registry 对应镜像,如下所示:

apiVersionn g X }: operators.coreos.com/v1alpha1
kind: CataloN 5 M @ t [ b 1gSource
metadata:
name: example-manifests
namespace: default
spD n / { X +ec:
sourceType: grpc
image: exam6 L ! q Kple-registry:latest

当上面的 examA u cpz V u E B , E [ ole-N , 7 )manifest 完成启动后,我们可以通过 pod 日志查看相应的 gRPC 后端服务是否已建立:

$ kubectl logs exam% S m 5 (ple-manifests-wfi J * H oh5h -n dk u + q g t mefault
time="2019-03-18T10:2$ T ^ $ o d f n0:14Z" level=info msg="ser$ - ; Q 3 ^ving registry"; b p dS = * ( H * w Q Tatabase=bundles.db port=50051

同时一旦 catalog 完成加载,OLM 中 package-servo T s t f 8 Ser 组件就会开始读取目录中定义好的 Operators 软件包,通过下面的命令我} G ~ p们可以 Watch 当前可用的 Operator package:

$ watch kubi E 5ectl get packagemanifests
[...]
NAME                     AGE
prometheus               13m
etcd                     27m

同时我们可以使用下面的命令+ | n查看一个指定 Operator packag[ 8 9 ^ C Y Ne 使用的默认 channel:

$ kubectl get packagemanifests etcd -o jsonpath='{.status.defaultChannel}'
alpha

通过上面获取到的 Operator 软件包名称,channel 和运行 catalog 的命名空间等信息,我们可1 z | L ~ $ 2以通过创建上文介绍过的 OLM 订阅对象(z H A @ # ?Subscription)启动从指定 catalog 源中安装或升级 Operator,一个 Subscription 示例如q 6 ] 1 e l g #下所示:

apiVersion^ a _ 0 - l e 1 k: opera% : z 8 i P + i .tors.coreos.com/v1alU 0 Epha1
kind: Subscription
metadata:
name: etcd-sub. ! R dscription
namespace: default
specS L g $ 2 = ~ w:
channel: alpha
name: etcd
source: example-manifests
sourceNamespace: default

另外通过支持 gRPC 协议的命令行通讯工具 gRPCurl,我们可以在本地u 6 / W ( V 向指定的 catalog 服务端发送请求,从而方便地进行软件包目录信息的查看。

小结

本章我们介绍了 Operator LifF n X * R ? Q :ecycle Manager 的基本架构和使用方法,通过本章的学习,我们对 OLM 的 z d V e ~ 9 S R工作原理、架构设计都有了较为清晰的认识。= 6 F L i同时通过一些示例代码,加深了读者对 OLM 应用实践的认识,为工o g 3 Z 1 1作实战中通过 Operator Fv G N i J h Eramework 实现产品能力扩展提供了指导基础。

作者简介

匡大虎D : L T & Z y阿里云高级技术专家,从事 Kubernetes 和容器相关产品的开发。尤其关注云原生安全,是阿- y O + Z - F B p 8 ] y云容器服务云原生安全F G U y核心成员。G ( = - 2 X

阚俊宝阿里云容器服务技术专家,专注 Kubernetes、Docker、云存储领域,是阿里云 CSI 项目的核心维护者/ . K

赠书福利

9 月 11 日 17:00 前在阿里巴巴公众号留言区欢迎7 L h O _ ? J x 大家一起探讨B H ~ J P Y $ T交流,精选留言点赞t K T 2 * * ^ 6 8前 3 名各送出《云原生应用管理:原理与实践》一书!

“阿里巴巴云原生关注微服务、Serverless、容器、Service Mesh 等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,做最懂云原生开发者的公众号。$ $ h 5