深色模式
OLM 与 Operator 生命周期:订阅、CSV 与声明式升级
摘要:本文面向生产 SRE / 平台工程师,系统讲解 Operator Lifecycle Manager(OLM)的生命周期管理模型:它如何把"安装一个 Operator"变成声明式的
Subscription,如何通过CatalogSource→Subscription→InstallPlan→ClusterServiceVersion链路完成安装与升级,以及生产落地的权限、依赖与回滚注意点。覆盖版本:OLM(operator-framework),经典 OLM 1.x 模型;OLM v1 重构见文末版本说明。
适用版本与前提
- OLM:本文以经典 OLM(
github.com/operator-framework/operator-lifecycle-manager)的 Subscription/CSV 模型为准(来源:OLM 官方文档)。 - 集群:已安装 OLM(
operator-sdk olm install或社区 manifests),且具备相应 RBAC。 - 前提:理解 CRD / Operator 基本概念(见本分类前几篇),以及
kubectl基本操作。
版本相关
OLM 正在经历 v1 重构(OLM v1 / operator-controller),其模型(以 ClusterExtension、Catalog 等 CRD 取代经典 Subscription/CSV 思路)与本文描述的经典模型有显著差异。本文内容针对经典 OLM,若你的集群使用 OLM v1,请以其官方文档为准。具体版本边界请以 operator-framework 的 release notes 与文档为准([未实测],本文未逐一验证 v1 字段)。
背景与问题
当一个 Operator 进入生产,问题从"怎么写"变成"怎么管":
- 几十个 Operator 怎么统一安装、升级、卸载?逐个
kubectl apply既不可审计也容易漂移。 - Operator 之间有依赖(如 A 依赖 B 提供的 CRD),如何保证依赖先就位?
- 如何像 Linux 包管理器一样做 OTA(Over-the-Air)升级与频道(channel)选择?
- 如何防止两个 Operator 争抢同一个 API(都声明拥有某个 CRD)导致集群不稳定?
OLM 的答案:把 Operator 当作"打包好的扩展",用一组 CRD 做声明式生命周期管理(来源:OLM 官方文档 - Introduction)。
OLM 的核心 CRD
CatalogSource:Operator 从哪来
CatalogSource 定义 Operator 清单的来源。经典 OLM 主流用 grpc 类型指向一个 index image(基于 opm 构建的目录镜像),也可使用 file-based catalog;旧的 app registry 类型已不推荐。OLM 通过 catalog 感知"有哪些 Operator、有哪些版本、版本间如何升级"。
Subscription:订阅声明
Subscription 是用户与 OLM 交互的主要入口,声明"我要安装/跟踪哪个 Operator 的哪个频道":
yaml
apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
name: prometheus-operator
namespace: operators
spec:
channel: stable # 跟踪的更新频道
name: prometheus-operator
source: operatorhubio-catalog # 引用的 CatalogSource 名
sourceNamespace: olm
installPlanApproval: Automatic # 或 Manual
# startingCSV: prometheus-operator.v0.70.0 # 可选:从指定版本开始1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
关键字段(来源:OLM 文档模型):
channel:更新频道(如stable/alpha),决定"最新版本"沿哪条升级路径走。source/sourceNamespace:指向CatalogSource。installPlanApproval:Automatic(自动批准安装/升级)或Manual(需人工审核InstallPlan)。startingCSV:可选,指定从某个具体版本开始(便于灰度到特定版本)。
OperatorGroup:作用域边界
OperatorGroup 定义该 Operator 能 watch 哪些命名空间、把其能力"广告"到哪些租户命名空间。一个 namespace 内的 Subscription 必须落在某个 OperatorGroup 的作用域中,否则无法正确安装。它是多租户隔离与能力发现的关键。
ClusterServiceVersion(CSV):Operator 的"包元数据"
CSV 描述一个 Operator 版本的完整元数据:版本号、安装模式(InstallModes:单租户/多租户等)、所需权限(RBAC)、拥有的 CRD(owned)与依赖的 CRD(required)、自定义资源描述符(驱动 UI 表单)、以及部署该 Operator 的 Deployment 清单。OLM 依据 CSV 创建 Operator 的 RBAC、Deployment 与 CRD。
InstallPlan:依赖解析与落地
当 Subscription 解析出目标版本后,OLM 生成 InstallPlan,它负责:
- 依赖解析:确保 required CRD / 依赖 Operator 已存在或可安装。
- 对象创建:按计划创建 CRD、ServiceAccount、ClusterRole、Deployment 等。
- 审批:
installPlanApproval: Manual时需人工将 InstallPlan 置为Approved才执行。
OTA 升级与频道
OLM 的升级模型借鉴了包管理器的"频道 + 图"思路:
- 每个 Operator 在 catalog 中声明版本间的升级边(channel 内的升级图)。
- Subscription 跟踪频道内"最新"的 CSV;当 catalog 更新(新版本发布)且频道可达,OLM 自动生成新 InstallPlan 完成升级。
startingCSV+ 手动审批可实现可控灰度:先让一个 Subscription 升级到目标版本,观察无误后再放宽频道/自动审批。
心智模型
把 OLM 想成集群内的"apt/yum":CatalogSource 是软件源,Subscription 是"装这个包并随 stable 频道更新",CSV 是包的元数据与依赖,InstallPlan 是实际安装动作。区别是它管理的是 Operator 这种集群扩展,而非 OS 软件包。
生产实践
- 默认用 Manual 审批:生产环境建议
installPlanApproval: Manual,让升级经过人工审核 InstallPlan,避免某个 Operator 自动升级引入破坏性变更。 - OperatorGroup 限定作用域:多租户集群里用 OperatorGroup 控制 Operator 能 watch 的命名空间,降低爆炸半径与权限暴露。
- 依赖与冲突:在 CSV 的
required中声明依赖 CRD/Operator,让 OLM 保证依赖先就位;OLM 会阻止两个争抢同一 API 的 Operator 共存,保护集群稳定(来源:OLM 文档 - 集群稳定性)。 - 可发现性:OLM 会把已安装 Operator 的能力广告到租户命名空间,租户可通过
kubectl get csv -n <tenant>发现可用服务。
常见失败模式
- Subscription 卡在 Pending/InstallPlan 未批准:Manual 模式下忘记批准 InstallPlan;或 CSV 依赖的 CRD 缺失无法解析。bash
kubectl get subscription -n operators kubectl get installplan -n operators kubectl describe installplan <name> # 看失败原因1
2
3 - OperatorGroup 作用域不匹配:Subscription 所在 namespace 不在任何 OperatorGroup 作用域,导致 Operator 无法安装。
- catalog 源不可用:CatalogSource 指向的 index image 拉取失败或 grpc 连接异常,Subscription 永远解析不出新版本。
- API 冲突:两个 Operator 都
owned同一 CRD,OLM 拒绝安装第二个以保护稳定性(这是预期行为,需统一治理)。
故障排查
bash
# 看 OLM 自身组件是否健康
kubectl get pods -n olm
# 看目标 Operator 的 CSV 状态
kubectl get csv -n operators
kubectl describe csv <operator>.vX.Y.Z -n operators
# 看 Subscription 与 InstallPlan
kubectl describe subscription <name> -n operators
kubectl get installplan -n operators -o yaml
# OLM 操作日志
kubectl logs deploy/olm-operator -n olm1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
回滚与清理
- OLM 的"回滚"是声明式的:把 Subscription 的频道切回旧频道、或通过
startingCSV指向旧版本,OLM 会生成降级 InstallPlan(前提是 catalog 中该版本仍可达且支持降级边,[版本相关],并非所有 Operator 都声明降级路径)。 - 卸载:删除 Subscription → OLM 清理 CSV/RBAC/Deployment;删除 CRD 需谨慎,会级联删除该类型的所有 CR 实例。
- 清理 OLM 自身:
operator-sdk olm uninstall([未实测] 具体命令随工具版本变化,请以当前 operator-sdk / OLM 文档为准)。
生产危险
删除 Subscription 或 CSV 会触发 OLM 清理该 Operator 创建的 RBAC 与 Deployment;若该 Operator 管理有状态服务(数据库/消息队列),其管理的子资源(含数据卷)可能随之被回收。卸载前务必确认数据已备份、业务已迁移。
安全与合规
- OLM 会按 CSV 声明的权限创建 ClusterRole/ServiceAccount;应审计 CSV 请求的权限范围,避免 Operator 索取超出其职责的高权限(如
cluster-admin)。 - 使用受信任的 CatalogSource(官方 OperatorHub、内部签名 index),避免引入未审计的第三方 Operator。
性能、容量与成本
- 每个 Operator 是一个常驻 Deployment,消耗 CPU/内存;集群中 Operator 数量多时需要统一治理与配额(ResourceQuota / LimitRange)。
- CatalogSource 的 grpc 目录会定期轮询更新,过多 catalog 会带来一定控制面开销;生产建议收敛 catalog 数量。
OLM 现状与 OLM v1
版本相关
经典 OLM(基于 Subscription/CSV)长期是社区主流,但 operator-framework 已推进 OLM v1(operator-controller) 重构,目标是更简单的模型、更好的声明式与扩展性(以 ClusterExtension、Catalog 等新 CRD 为核心)。两者的安装、升级与字段差异较大。本文描述经典模型;若你的环境已迁移到 OLM v1,请参考 OLM 官方文档的 v1 章节([未实测],本文未逐一验证 v1 字段与命令)。
FAQ
Q:OLM 和直接用 Helm/Kubebuilder 部署 Operator 有什么区别? A:Helm/Kubebuilder 关注"怎么构建与部署一个 Operator";OLM 关注"怎么在集群里声明式地安装、升级、依赖管理与多 Operator 治理"。二者互补,可在 OLM 之上分发 Helm/Kubebuilder 构建的 Operator。
Q:能不能不用 OLM? A:可以。小规模或 GitOps 场景(Argo CD / Flux)直接用 manifest 管理 Operator 生命周期也常见。OLM 的价值在"多 Operator 依赖治理 + OTA 升级 + 多租户能力发现"。