news 2026/9/25 5:20:46

ExternalDNS 发布流程全指南:镜像发布、版本规范与 Helm Chart 发布

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ExternalDNS 发布流程全指南:镜像发布、版本规范与 Helm Chart 发布
  • 云原生

【免费下载链接】external-dns

Configure external DNS servers dynamically from Kubernetes resources

项目地址:https://gitcode.com/gh_mirrors/ex/external-dns
点击查看免费下载

本篇技术指南以 ExternalDNS 项目官方发布文档为主体,结合仓库内scripts/下真实可运行的发布脚本,系统讲解 ExternalDNS 的版本周期、语义化版本约定、从创建 GitHub Release 到镜像晋升registry.k8s.io、再到更新 kustomize 清单与发布 Helm Chart 的完整操作链路。读完本文,你可以掌握 ExternalDNS 维护者视角下的整条发布流水线,也能理解"git tag 与 kustomize 清单存在镜像滞后"这一关键陷阱及其规避方法。

发布周期(Release Cycle)

ExternalDNS没有固定、定期的发布计划。维护团队采取"按需发布"策略:只要认为某个时机适合发布新版本(积累了足够的功能、修复或社区呼声),就会执行一次发布。

  • 想了解下一个版本大概何时发布,可以在 Kubernetes 社区的external-dnsSlack 频道(#external-dns)中询问维护者。
  • 与之相对的是Staging 预发布周期:每周都会产出一个 staging 镜像,上传到官方 staging 镜像仓库gcr.io/k8s-staging-external-dns/external-dns。
  • 需要注意 staging 镜像与master分支之间存在时间差:合并到master的变更并不会立即出现在 staging 镜像中,CI 构建与镜像推送需要一定时间。

查询最近 staging 镜像

发布文档给出了一个用curl + jq + grep查询最近 10 个 staging 镜像的示例命令:

export EXT_DNS_VERSION="v0.23.0" curl -sLk https://gcr.io/v2/k8s-staging-external-dns/external-dns/tags/list | jq | grep "$EXT_DNS_VERSION" | tail -n 10

命令原理:https://gcr.io/v2/<镜像名>/tags/list是 GCR 的 Docker Registry HTTP API v2 标签列表端点,返回 JSON;jq用于格式化输出,grep过滤出与目标版本(如v0.23.0)相关的标签,tail -n 10只保留最近 10 条。注意这里用EXT_DNS_VERSION环境变量承载目标版本号,而 scripts/version-updater.sh 在发布完成后也会同步更新 docs/release.md 中该变量的值(sed -i -e "s/EXT_DNS_VERSION=\"${PREV_TAG}\"/EXT_DNS_VERSION=\"${NEW_TAG}\"/g"),保证文档中的示例始终指向当前最新版本。

版本号约定(Versioning Convention)

自0.7.6之后的版本遵循以下递增规则:

版本段何时递增
Patch(补丁)需要合并 bugfix 时。例如某个 provider 需要修复才能让更新功能恢复工作;文档的更新或改进也归入此类
Minor(次版本)在既有 provider 中实现新功能,或引入新的 provider 时
Major(主版本)引入破坏性变更(breaking changes)时

语义化版本纪律(Semantic Versioning Discipline)

ExternalDNS 遵循语义化版本(Semantic Versioning)原则,但刻意停留在0.x阶段:

  • 0.x→ 未到稳定版,API 可能变更;
  • 1.x→ 目前尚未提上日程。

版本化与发布ExternalDNS 选择停留在0.x版本体系内。项目追求稳定性,但保留在必要时于 minor 版本中引入破坏性变更的权利。

这意味着使用者需要关注每个 minor 版本的 release notes,因为0.x体系下的 minor 升级也可能带来不兼容变化——这也是 scripts/releaser.sh 会把Breaking Changes单独列为 changelog 首个章节的原因(见下文"release notes 自动生成")。

如何发布一个新的镜像(How to release a new image)

前置条件(Prerequisite)

  1. 安装 GitHub CLI(gh,即 https://github.com/cli/cli),发布流程用它来自动化创建 release。
  2. 必须是项目的官方 maintainer才有权限执行发布。

八步发布流程

发布文档给出完整操作步骤,结合仓库脚本可进一步拆解如下:

  1. 运行scripts/releaser.sh创建新的 GitHub Release(同时打 git tag)。 也可以直接在 GitHub UI 中创建 release,并使用"自动生成 release notes"功能。关于脚本内部逻辑,见下文"releaser.sh:release notes 自动生成"小节。

  2. 触发 Kubernetes CI/CD 系统 Prow。 上一步完成后,Prow(https://prow.k8s.io)会基于该 git tag 构建新镜像并上传到gcr.io/k8s-staging-external-dns/external-dns。请到 Prow 上确认构建与推送成功。

  3. 在 k8s.io 仓库中创建 PR,按 sha256 digest 晋升 staging 镜像。 晋升时使用sha256 摘要(由 scripts/get-sha256.sh 计算),而不是 tag。该 PR 合并后,镜像即在registry.k8s.io上以 release tag 形式可用。发布文档以 https://github.com/kubernetes/k8s.io/pull/8466 作为参考实例。

  4. 验证镜像可按 tag 拉取:

    docker run registry.k8s.io/external-dns/external-dns:v0.x.0 --version
  5. 仅在镜像可拉取之后,从默认分支(master)切出新分支,运行scripts/version-updater.sh更新kustomize/清单与文档中的镜像 tag。

  6. 提交并合并 version-updater PR。

  7. 开一个 issue,指派给 chart maintainer,触发对应的 Helm chart 发布(流程见下文)。

  8. version-updater PR 合并后,本次发布完成。

顺序是硬性要求:第 4 步验证成功之前不能执行第 5 步,否则 kustomize 清单会宣传一个尚未在registry.k8s.io上线的镜像。

get-sha256.sh:计算镜像 sha256 摘要

scripts/get-sha256.sh 是第 3 步晋升 PR 所需摘要的计算工具,用法为scripts/get-sha256.sh <镜像>[:tag]:

#!/bin/bash IMAGE=$1 echo -n "image: " crane digest "${IMAGE}" # 输出镜像 digest echo "architecture" crane manifest "${IMAGE}" | jq -r '.manifests.[] | .platform.architecture, .digest'

它依赖 Google 开源的镜像工具crane:crane digest直接输出镜像的 sha256 摘要(用于 k8s.io 晋升 PR 的digest字段),crane manifest配合jq输出该多架构镜像各 platform 的架构与 digest,便于核对架构清单是否完整。

version-updater.sh:同步镜像 tag 到仓库清单

scripts/version-updater.sh 对应第 5 步,用法为scripts/version-updater.sh <旧tag> <新tag>,脚本实际改动三类文件并一次性提交:

  • kustomize/kustomization.yaml:将newTag更新为新版本(当前仓库中该文件为newTag: v0.23.0,对应镜像registry.k8s.io/external-dns/external-dns,见 kustomize/kustomization.yaml);
  • 所有文档与docs/snippets/中出现external-dns:${PREV_TAG}的 Markdown 文件(用git grep -l定位),统一替换镜像 tag;
  • docs/release.md 中的EXT_DNS_VERSION环境变量值。

最终提交信息为chore(release): updates kustomize & docs with ${NEW_TAG}。

releaser.sh:release notes 自动生成与 DRY RUN

scripts/releaser.sh 是发布流程第 1 步的核心工具,它根据Conventional Commits(约定式提交)规范自动把已合并 PR 归类、生成 release notes,并调用gh release create创建 release。几个值得注意的机制:

  • 无参数运行 = DRY RUN:脚本在$# -ne 1时不会真正创建 release,而是用占位版本v0.x.0生成一份 changelog 预览并提示To create a release: ./releaser.sh v0.x.0,方便在正式发布前检查内容。
  • 按约定式提交前缀分节:用正则锚定 PR 标题的行首-列表标记,分别归入:
    • BREAKING_RE(- type(scope)!:或- type!:)→## :warning: Breaking Changes
    • feat:→## :rocket: Features
    • fix:→## :bug: Bug fixes
    • docs:→## :memo: Documentation
    • 其余(含chore(deps)归入 deps)→ 折叠进## :package: Others
  • scope 重排:label_by_scope用sed把feat(aws): add X重排为[aws] add X,让每个条目带上 provider 或模块范围标签,便于读者快速定位影响面。
  • chart-only 变更被排除:Helm chart 有独立的发布周期,脚本用CHART_RE='charts?|helm'过滤掉 chart-only 的 PR(输出到 stderr 提示"released separately"),避免与镜像 changelog 混在一起。
  • changelog 附带镜像拉取命令:generate_changelog会为每个版本追加docker pull registry.k8s.io/external-dns/external-dns:<version>,并注明"该拉取命令仅在镜像已发布后可用"。
  • 版本参数:传入./releaser.sh v0.x.0时,脚本将生成的 changelog 通过管道喂给gh release create "${VERSION}" -t "${VERSION}" -p -F -(-p先创建为 prerelease,-F -从 stdin 读取 release body)。

Git tag 与 kustomize 清单的已知滞后(known lag)

发布文档特别强调了一个容易踩坑的固有时间差:镜像晋升(image promotion)与仓库内清单更新无法在 release tag 的同一个 commit 内完成。原因在于 CI 必须先有 git tag 才能构建并晋升镜像;而 kustomize/文档必须等到镜像在registry.k8s.io上真正可拉取后,才能宣传该 tag。

因此,在发布进行中的不同时间点,各来源的镜像 tag 状态如下:

来源清单中的镜像 tag
Gitrelease tag(如v0.18.0)在后续 commit 落地之前,仍指向上一个release 的镜像
version-updater PR 合并后的master与新 release 镜像一致
chart 发布后的Helm chartappVersion与新 release 镜像一致

由此得出两条实践结论:

  • 不要把 git tag 上的 kustomize 树当作该版本镜像的权威来源(此时它指向的还是旧镜像);
  • 优先使用 Helm chart,或master上发布后的 version-updater commit 中的安装清单来固定新 tag 的镜像。

如何发布一个新的 Chart 版本(How to release a new chart version)

Helm chart 的发布以ExternalDNS 镜像发布为触发条件,或按需发布;通常由"发布 chart"的 issue 来驱动(即上文第 7 步创建的 issue,指派给 chart maintainer)。

步骤

  1. 创建 PR 更新Chart.yaml:

    • 将appVersion更新为 ExternalDNS 新版本号;
    • 在version中约定本次 chart 的发布版本号;
    • 在annotations中记录变更说明。 以当前仓库 charts/external-dns/Chart.yaml 为例:version: 1.22.0、appVersion: 0.22.0,即 chart 版本与镜像应用版本是两个独立递增的维度,chart 的version通常按自身节奏走 minor/patch。
  2. 验证 chart linting 通过(Helm 会校验 chart 结构与元数据,确保Chart.yaml、模板、values schema 均合法)。

  3. 合并 PR,触发 GitHub Action 执行 chart 发布(将 chart 打包为 tgz 并发布)。

chart-release.sh:chart 发布的底层实现

chart 发布动作由 scripts/chart-release.sh 在 CI 中执行,调用方式为scripts/chart-release.sh <version> <release-notes-file>,依赖cr(chart-releaser)、gh与jq。它解决了一个已知痛点:GitHub release 一旦发布即为不可变,而 chart-releaser 默认流程要求先发布 release 再附 asset,二者冲突。该脚本的绕行方案是:

  1. cr package charts/external-dns打包 chart 到.cr-release-packages/external-dns-<version>.tgz;
  2. 用gh api -X POST repos/<repo>/releases创建draft(草稿)release,tag 命名规则为external-dns-helm-chart-${VERSION},并写入 release notes;
  3. 在草稿状态下gh release upload上传 chart 资产(带--clobber覆盖残留的失败上传),随后gh api -X PATCH将 draft 置为draft=false完成发布;
  4. 最后cr index重建 Helm 仓库索引并推送(--release-name-template "external-dns-helm-chart-{{ .Version }}"),整个流程对关键步骤都做了带指数退避的retry重试。

这与发布文档第 7 步的职责划分一致:镜像发布与 chart 发布分离,chart 由专门维护者(charts/OWNERS 中标注的 approver/reviewer)负责,镜像 changelog 中也明确排除 chart-only 变更。

小结:一条完整的 ExternalDNS 发布流水线

将以上流程串起来,一次典型的 ExternalDNS 发布长这样:

  1. 维护者在master上合并足够多的功能与修复;
  2. 运行./scripts/releaser.sh vX.Y.Z(先无参数 DRY RUN 预览 changelog,再带版本号正式创建 release);
  3. Prow 基于新 tag 构建镜像并推送到 staging registry;
  4. 用scripts/get-sha256.sh取镜像 sha256 digest,在 k8s.io 仓库提晋升 PR,镜像落地registry.k8s.io;
  5. docker run registry.k8s.io/external-dns/external-dns:vX.Y.Z --version验证可拉取;
  6. 运行scripts/version-updater.sh更新 kustomize 与文档,合并 PR;
  7. 开 issue 触发 chart 维护者走Chart.yaml更新 → lint → 合并 → GitHub Action 用scripts/chart-release.sh发布 chart。

全程贯穿两条纪律:先验证镜像可拉取再宣传 tag,以及0.x 版本体系下 minor 升级也可能引入破坏性变更——前者靠流程顺序保证,后者靠 releaser.sh 对 Breaking Changes 的独立分节来显性化。想进一步研究相关实现,可在仓库中查看 scripts/releaser.sh、scripts/get-sha256.sh、scripts/version-updater.sh、scripts/chart-release.sh、kustomize/kustomization.yaml 与 charts/external-dns/Chart.yaml。

  • 云原生

【免费下载链接】external-dns

Configure external DNS servers dynamically from Kubernetes resources

项目地址:https://gitcode.com/gh_mirrors/ex/external-dns
点击查看免费下载
上一篇:【亲测免费】 BMF开源多媒体处理框架快速指南及问题解答
下一篇:如何配置kohya_ss分布式推理:多节点负载均衡终极指南 🚀

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

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