news 2026/9/12 15:38:09

Loki Operator 发布流程全解:从 bundle 生成到 OperatorHub 上架

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Loki Operator 发布流程全解:从 bundle 生成到 OperatorHub 上架

Loki Operator 发布流程全解:从 bundle 生成到 OperatorHub 上架

【免费下载链接】lokiLike Prometheus, but for logs.项目地址: https://gitcode.com/GitHub_Trending/lok/loki

本指南系统讲解 Grafana Loki Operator(位于 operator/ 目录)的社区版本发布机制:如何通过make bundle-all生成 OLM bundle、如何借助 release-please 自动化版本号提升与 CHANGELOG 生成、如何将镜像发布到制品仓库,以及如何自动向两个 OperatorHub 社区仓库提交上架 PR。读完本文,你将完整掌握 Loki Operator 从一次代码合并到在 Kubernetes 生态中可被 OLM 安装的端到端发布链路,并理解每一环背后的工作流设计与配置细节。

发布流程总体设计

发布一个 Loki Operator 社区版本,需要依次完成以下四件事(对应 release.md 中 "Design" 一节的描述):

  1. 提升 Loki Operator 版本号并生成 bundle 清单:执行make bundle-all
  2. 更新 CHANGELOG.md到新版本;
  3. 创建 release tag 与 GitHub release
  4. 向 [k8s-operatorhub/community-operators] 与 [redhat-openshift-ecosystem/community-operators-prod] 两个仓库各开一个 PR,提交新版本 bundle 的内容。

其中第 2、3 步由 GitHub 官方维护的release-pleaseaction 自动化完成;第 4 步则由一个在 release tag 创建时触发的 workflow 自动执行。第 1 步(bundle 生成)目前仍是人工操作,是整条链路中唯一没有自动化的环节。

值得强调的是,Loki Operator 与 Loki 主项目共享同一个仓库,但Operator 的 release-please 流程与 Loki 自身的发布流程是相互独立的:Operator 的配置单独存放在 operator/release-please-config.json,且 workflow 只监听operator/**路径的变更。

第 1 步:用 make bundle-all 生成 bundle 清单

bundle 是什么

bundle 是 OLM(Operator Lifecycle Manager)生态中 Operator 的标准打包格式,包含 ClusterServiceVersion(CSV)清单、CustomResourceDefinition(CRD)以及元数据注解。Loki Operator 针对不同发行渠道维护了三个 bundle 变体(见 operator/Makefile 中的VARIANT变量):

变体镜像仓库通道适用场景
communitydocker.io/grafanaalpha通用社区分发(默认)
community-openshiftdocker.io/grafanaalpha带 OpenShift 兼容注解的社区包
openshiftquay.io/openshift-loggingstableOpenShift 官方渠道(随 OpenShift Logging 发行)

bundle-all目标会依次生成以上三个变体(operator/Makefile):

.PHONY: bundle-all bundle-all: ## Generate both bundles. $(MAKE) bundle $(MAKE) bundle VARIANT=community-openshift $(MAKE) bundle VARIANT=openshift

bundle 生成的具体动作

单个bundle目标(operator/Makefile)做三件事:

.PHONY: bundle bundle: manifests $(KUSTOMIZE) $(OPERATOR_SDK) ## Generate variant bundle manifests and metadata, then validate generated files. cd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG) cd $(BUNDLE_DIR) && cp ../../PROJECT . && $(KUSTOMIZE) build ../../$(MANIFESTS_DIR) | $(OPERATOR_SDK) generate bundle $(BUNDLE_BUILD_GEN_FLAGS) && rm PROJECT $(OPERATOR_SDK) bundle validate $(BUNDLE_DIR)
  1. 通过kustomize edit set image controller=$(IMG)把 CSV 中的控制器镜像地址替换为当前版本镜像;
  2. operator-sdk generate bundleconfig/manifests/<variant>生成 bundle 清单,输出到./bundle/<variant>目录(如 operator/bundle/community/);
  3. operator-sdk bundle validate校验生成的 bundle 是否符合 OLM 规范。

版本号由VERSION变量控制(当前仓库默认值为0.11.0,见 operator/Makefile)。发布前需要先在 PR 中把该版本号提升为目标版本,例如升级到0.11.10.12.0,同时保证提交信息规范(见下文 "Releasing" 一节),这也是原文档强调 "be careful with the commit message" 的原因。

第 2、3 步:release-please 自动化版本发布

release-please 的工作原理

release-please 通过解析 git 历史中的Conventional Commit提交信息来驱动整个发布流程:

  • 扫描到可发布单元(releasable unit,即以featfixdeps为前缀的提交)后,自动创建 release PR(其中包含版本号提升与 CHANGELOG 生成);
  • release PR 被合并后,release-please 自动创建 GitHub release;
  • 随后继续等待下一个可发布单元,再开启下一轮 release PR。

Operator 的 release-please workflow 位于 .github/workflows/operator-release-please.yml,其触发条件与关键参数如下:

on: push: paths: - 'operator/**' branches: - main

只有当operator/**路径下有合并到main的提交时才会运行;使用 GitHub App(loki-gh-app)签发的 token 调用googleapis/release-please-action(v5.0.0),并指定:

  • path: operator:只关注operator子目录;
  • config-file: operator/release-please-config.json:使用独立的 manifest 配置。

operator/release-please-config.json 详解

operator/release-please-config.json 是理解整个发布策略的关键,其完整内容如下:

{ "bump-minor-pre-major": true, "bump-patch-for-minor-pre-major": true, "include-component-in-tag": true, "draft": true, "tag-separator": "/", "packages": { "operator": { "component": "operator", "release-type": "go", "pull-request-title-pattern": "chore(${component}): Community release ${version}", "changelog-path": "CHANGELOG.md" } } }

结合原文档的说明,各配置项的含义如下:

  • include-component-in-tag+tag-separator: "/":release tag 采用operator/vX.Y.Z格式(组件名 + 斜杠 + 版本号)。这个 tag 前缀也是后续 OperatorHub 发布 workflow 的触发过滤器;
  • release-type: "go":按 Go 模块语义处理版本提升,作用于 operator/ 目录;
  • pull-request-title-pattern:release PR 的标题固定为chore(operator): Community release <version>格式——注意,这个标题格式正是下一节 "防止未更新 manifests 就合并" 检查工作流的匹配依据;
  • changelog-path: "CHANGELOG.md":生成的变更日志写入 operator/CHANGELOG.md。从该文件可以看到 release-please 的实际输出风格:每个版本一节,包含⚠ BREAKING CHANGESFeaturesBug Fixes分组,且 security/deps 类提交也会被归类记录。

为什么使用 bump-minor-pre-major 与 bump-patch-for-minor-pre-major

由于 Operator 目前仍处于v1.0.0之前的阶段(pre-major),配置开启了bump-minor-pre-majorbump-patch-for-minor-pre-major,效果是:

  • 合并featfixdeps提交 → 只提升patch版本(如v0.10.1v0.10.2);
  • 合并feat!fix!(带感叹号的破坏性变更提交)→ 提升minor版本(如v0.10.xv0.11.0)。

由此,在未引入破坏性变更的前提下,当前仅监听main分支的 release-please 可以支撑两种发布场景:

  • Case 1(patch 发布):从v0.Y.x的 diff 发布v0.Y.x+1。该场景在破坏性特性合并进main之前一直有效;
  • Case 2(minor 发布):从v0.Y.x的 diff 发布新版本v0.Y+1.0

为什么启用 draft

Operator 与 Loki 主项目共享同一个 GitHub 仓库,直接由 release-please 创建的 release 会被标记为仓库的latest,导致 "Loki 最新版本" 被误显示为 Operator 的版本。release-please 本身没有提供关闭latest标记的选项,因此配置了"draft": true,让 release-please 只创建草稿 release,再由后续步骤发布:

.github/workflows/operator-release-please.yml 中的publishReleasejob 在镜像构建完成后执行:

gh release edit "$RELEASE_NAME" --draft=false --latest=false

即把草稿转为正式 release,同时明确不设为 latest,从而与 Loki 主项目的发布记录区分开。

publishImages:构建并推送 Operator 镜像

当 release-please 判定需要发布(release_created输出为 true)时,publishImagesjob 通过复用工作流 .github/workflows/operator-reusable-image-build.yml 构建并推送 Operator 镜像,传入参数包括:

  • dockerfile: operator/Dockerfile(见 operator/Dockerfile);
  • registry: us-docker.pkg.devorganization: grafanalabs-global/dockerhub-loki-prod-mirrorimage_name: loki-operator
  • tag由 release-please 输出的major.minor.patch三部分拼接而成。

镜像最终推送到 Google Artifact Registry(GAR)的地址为us-docker.pkg.dev/grafanalabs-global/dockerhub-loki-prod-mirror/loki-operator:<version>,之后由gar-image-mirror服务将其镜像同步到 Docker Hub 的docker.io/grafana/loki-operator

从复用工作流源码可以看到构建细节(.github/workflows/operator-reusable-image-build.yml):

  • 使用 QEMU + Docker Buildx 进行多架构构建,platforms: "linux/amd64,linux/arm64,linux/arm"
  • 构建上下文按镜像名推断:loki-operator-bundle使用operator/bundle/openshift,其余(含loki-operator)使用operator目录;
  • 该复用工作流同时支持两套仓库体系:登录 GAR(us-docker.pkg.dev)或从 Vault 拉取凭据登录quay.io(OpenShift 渠道使用)。

第 4 步:向 OperatorHub 社区仓库发布

触发机制

发布工作流 .github/workflows/operator-publish-operator-hub.yml 监听 GitHubrelease 发布事件,并校验 tag 前缀:

on: release: types: [published] jobs: operator-hub-prod-release: if: startsWith(github.event.release.tag_name, 'operator/') ...

当 tag 以operator/开头(即 release-please 创建的operator/vX.Y.Z)时,会并发调用两次复用工作流 .github/workflows/operator-reusable-hub-release.yml,分别面向:

  • redhat-openshift-ecosystem/community-operators-prod(OpenShift 生产渠道);
  • k8s-operatorhub/community-operators(通用社区渠道)。

复用工作流做了哪些事

.github/workflows/operator-reusable-hub-release.yml 依次完成以下动作:

  1. 签发 GitHub App token:使用loki-operator-hub-publisher这个专用 GitHub App,保证后续以受信任的 bot 身份操作;

  2. 提取版本号:从 tagoperator/vX.Y.Z中通过${TAG:10}切片去掉operator/v前缀,得到纯版本号写入环境变量;

  3. 同步 fork:用gh repo sync grafanabot/$INPUTS_REPO --source <org>/<repo> --force先把 grafanabot 名下的 fork 同步到最新,避免拉取完整上游仓库(浅克隆会导致 push 报 "shallow update not allowed");

  4. 检出两个仓库:分别 checkout grafanabot fork 的 operatorhub 仓库(工作目录)与grafana/loki主仓库(tmp/目录);

  5. 复制 bundle 清单:将新版本目录创建到 operatorhub 仓库的operators/loki-operator/<version>/下,内容来自./tmp/operator/bundle/community${OCP_DIR}/*

    mkdir operators/loki-operator/${VERSION} cp -R ./tmp/operator/bundle/community${OCP_DIR}/* operators/loki-operator/${VERSION} rm -f "operators/loki-operator/${VERSION}/bundle.Dockerfile"

    注意这里同时做了两件重要的适配:一是按目标渠道选择communitycommunity-openshift变体;二是删除 bundle.Dockerfile(OperatorHub 社区目录不需要它);

  6. 添加 OpenShift 支持版本注解(仅 OpenShift 仓库):使用fjogeleit/yaml-update-actionoperators/loki-operator/<version>/metadata/annotations.yaml中写入annotations['com.redhat.openshift.versions'],当前值为v4.12。这正是原文档所说 "Adding the ocp supported version annotation to the metadata.yaml" 的实现;

  7. 创建 PR:以 grafanabot 身份(CLA 已批准)新建分支update-loki-operator-to-<version>,提交并gh pr create --repo <org>/<repo> --base main,PR 标题为Update the loki-operator to <version>

防止未更新 manifests 就合并 release-please PR

由于第 1 步(make bundle-all生成 bundle)尚未自动化、与 release-please 相互独立,存在"release-please PR 先合并、bundle 后补"的时序风险。为此仓库设置了专门的守卫工作流 .github/workflows/operator-check-prepare-release-commit.yml。

该工作流只针对 release-please PR 运行(通过两个条件限定):

if: | github.event.pull_request.head.ref == 'release-please--branches--main--components--operator' && contains(github.event.pull_request.title, 'chore( operator): Community release')

其逻辑是:先从 PR 标题chore( operator): Community release <semver>中提取目标版本号,再用gh search commitsmain分支搜索提交信息为chore(operator): Prepare community release v<semver>的提交;若找不到,则以退出码 1 使检查失败,阻止 PR 合并。也就是说,人工提交的"版本提升 + bundle 生成"准备提交必须先于 release-please PR 存在。原文档也指出:一旦第 1 步实现自动化,这个守卫工作流就可以移除。

Releasing:一次完整发布的操作清单

综合以上设计,一次真实的 Loki Operator 社区发布按以下步骤执行(对应原文档 "Releasing" 一节):

  1. 创建版本提升 PR:先手动提交一次包含版本号提升与 bundle 生成的变更,提交信息务必为chore(operator): Prepare community release v<version>(例如 v0.6.1 的准备工作),并合并到main
  2. 在 release-please PR 上重新触发operator-publish-operator-hub检查:确保守卫工作流通过;
  3. 合并 release-please PR:合并后 release-please 自动创建 release(草稿态),标题形如chore(operator): Community release v<version>
  4. 镜像发布publishImagesjob 构建多架构镜像并推送到 GAR,随后由gar-image-mirror同步到 Docker Hub 的docker.io/grafana/loki-operator
  5. OperatorHub PR 自动创建operator-publish-operator-hubworkflow 检测到operator/前缀的正式 release 后,自动向k8s-operatorhub/community-operatorsredhat-openshift-ecosystem/community-operators-prod两个仓库各开一个包含新版本 bundle 的 PR。

全链路小结

把整条发布流水线串起来看,Loki Operator 的发布由四类 GitHub Actions 工作流协同完成:

工作流触发时机职责
operator-release-please.ymloperator/**合并到main生成 CHANGELOG、创建草稿 release、调度镜像构建与正式发布
operator-reusable-image-build.yml被 release workflow 调用多架构构建并推送 Operator 镜像到 GAR / quay.io
operator-check-prepare-release-commit.ymlrelease-please PR 上校验 "Prepare community release" 准备提交已存在
operator-publish-operator-hub.ymltag 以operator/开头的 release 发布触发向两个 OperatorHub 社区仓库的上架 PR

其中唯一的人工环节是第 1 步:更新 operator/Makefile 中的VERSION并执行make bundle-all重新生成 operator/bundle/ 下的清单,随后以约定的提交信息合入main。其余版本号计算、CHANGELOG 生成、release 创建、镜像发布与 OperatorHub 上架全部由自动化流水线接管,既保证了与 Loki 主项目发布记录的清晰隔离(operator/tag 前缀 + draft +--latest=false),也保证了每次上架内容的规范性与可追溯性。

【免费下载链接】lokiLike Prometheus, but for logs.项目地址: https://gitcode.com/GitHub_Trending/lok/loki

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 15:37:37

pytest 快速上手全指南:5 分钟跑通你的第一个 Python 测试框架

pytest 快速上手全指南&#xff1a;5 分钟跑通你的第一个 Python 测试框架 【免费下载链接】pytest The pytest framework makes it easy to write small tests, yet scales to support complex functional testing 项目地址: https://gitcode.com/GitHub_Trending/py/pytest…

作者头像 李华
网站建设 2026/9/12 15:36:48

Arria GX高速收发器物理层配置原理与实战调试指南

1. 项目概述&#xff1a;为什么Arria GX高速收发器配置值得花时间深挖Arria GX系列FPGA——特别是EP1AGX60DF1152C6和EP1AGX90DF1152C6这两款经典型号——在2008至2015年间是工业级高速串行通信的主力平台。它不像Stratix系列那样面向超高端市场&#xff0c;也不像Cyclone系列那…

作者头像 李华
网站建设 2026/9/12 15:36:20

C++哈希表的实现思路剖析讲解

前言 哈希又称散列&#xff0c;是一种组织数据的方式。从译名来看&#xff0c;有散乱排列的意思。本质就是通过哈希函数把关键字Key跟存储位置建立一个哈希映射关系&#xff0c;查找时通过这个哈希函数计算出Key存储的位置&#xff0c;进行快速查找。 1.直接定址法 当关键字的…

作者头像 李华
网站建设 2026/9/12 15:36:09

uni-app微信小程序商城源码:分销拼团拍卖一体化实现

简介&#xff1a;这是一套面向微信生态电商开发者的「智信分销拼团拍卖商城」小程序全栈源码&#xff0c;适用于希望快速搭建多模式营销平台的中小企业、个体商户及小程序开发者。资源完整覆盖分销&#xff08;多级佣金体系&#xff09;、拼团&#xff08;社交裂变成团逻辑&…

作者头像 李华
网站建设 2026/9/12 15:36:05

Django 2026技术趋势与现代化组件解析

1. Django生态现状与2026年技术趋势展望作为Python生态中最成熟的Web框架&#xff0c;Django在2026年依然保持着强劲的发展势头。根据PyPI最新统计&#xff0c;Django的月下载量已突破1.2亿次&#xff0c;较2023年增长40%。这种增长主要来自三个方面&#xff1a;传统企业级应用…

作者头像 李华
网站建设 2026/9/12 15:35:36

WinForms迁移Blazor WASM实战:MWGA项目解析

1. 项目背景与核心价值WinForms作为.NET生态中历史悠久的桌面应用框架&#xff0c;至今仍在企业级应用中广泛存在。根据2023年StackOverflow开发者调查&#xff0c;仍有27%的.NET开发者在使用WinForms维护遗留系统。但随着Web技术的普及&#xff0c;这些应用面临着现代化改造的…

作者头像 李华