Velero 镜像标签策略(Image Tagging Policy)完整指南:SemVer 版本标签、latest 与 main 标签的发布机制与实践
【免费下载链接】veleroBackup and migrate Kubernetes applications and their persistent volumes项目地址: https://gitcode.com/GitHub_Trending/ve/velero
导读:本文以仓库文档 site/content/docs/v0.9.0/image-tagging.md 为骨架,系统讲解 Velero(前身 Ark)的镜像标签管理策略——正式发布的 SemVer 版本标签、随最新发布版本漂移的
latest标签、以及随主干分支最新提交更新的main(开发版)标签。同时结合当前仓库中的 Makefile、CI 发布脚本hack/docker-push.sh、构建信息注入代码与安装命令源码,从"标签从哪来、怎么打、默认用哪个、如何覆盖"四个层面还原完整链路,帮助读者在部署、升级、自建镜像时正确选择并校验镜像标签。
一、镜像标签策略是什么
容器镜像标签(tag)是定位某个具体镜像版本的标识,决定了集群中实际运行的 Velero 服务端、node-agent(旧称 restic 守护进程)与 restore-helper 容器镜像内容。标签策略则定义了哪类标签对应哪类构建产物、标签何时漂移、以及使用者应该如何选择。
关联文档开篇即点明主题:本策略文档描述的是 Velero/Ark 的镜像标签策略。其核心规则可以归纳为三条:
| 标签类型 | 格式 | 语义 |
|---|---|---|
| 正式发布版本 | registry/ark:<SemVer> | 与仓库中某个 git tag 一一对应,内容不可变 |
| 最新发布版 | registry/ark:latest | 指向最近一次正式发布的版本,随发布而漂移 |
| 开发版 | registry/ark:main | 跟随main分支最新提交,持续滚动更新 |
说明:v0.9.0 时代项目尚以Ark命名,镜像托管于 Google Container Registry 的
gcr.io/heptio-images命名空间下;当前仓库中同一文档的 最新版本 已随项目更名为Velero,镜像也迁移至 Docker Hub 的velero/velero仓库。本文在讲解策略本身时以文档原始表述为准,并会在 第五节 说明演进细节。
二、正式发布版本:SemVer 版本标签
文档给出的正式版本标签格式为:
gcr.io/heptio-images/ark:<SemVer>即发布时使用的镜像标签与仓库中的 git tag 完全一致。Ark/Velero 遵循 Semantic Versioning(语义化版本)标准进行版本管理,github.com/heptio/ark(后为github.com/velero-io/velero)仓库中的每个 git tag 都对应一个匹配的镜像,例如gcr.io/heptio-images/ark:v0.8.0。
这一"仓库 tag 与镜像 tag 一一对应"的约定在当前仓库的发布工具链中得到了完整印证:
- Makefile 中
VERSION ?= main,镜像标签通过IMAGE_TAGS ?= $(IMAGE):$(VERSION)生成,即镜像标签名直接取自构建时的版本号; - hack/docker-push.sh 的头部注释明确写道:该脚本由 CI/CD 系统调用,为所有推送到 main 分支的提交以及所有 git tag 构建并推送镜像。当 CI 以 tag 事件触发(
triggeredBy == "tags")时,VERSION="$TAG",即直接用 git tag 作为镜像版本号; - 当前站点文档中也能看到真实的使用示例,如 site/content/docs/main/backup-restore-windows.md 中提到的
velero/velero:v1.16.0,以及 site/content/docs/main/upgrade-to-1.18.md 中通过 Helm values 指定的velero=velero/velero:v1.18.0。
SemVer 标签的实践意义
由于 SemVer 标签指向不可变的构建产物,它是生产环境中唯一推荐长期固定的标签:升级时可通过明确指定vX.Y.Z获得可预期、可回滚的行为。仓库历史文档也给出了基于kubectl set image的升级示例(见 site/content/docs/v1.0.0/upgrade-to-1.0.md):
kubectl -n velero set image deployment/velero velero=gcr.io/heptio-images/velero:v1.0.0 kubectl -n velero set image daemonset/restic restic=gcr.io/heptio-images/velero:v1.0.0三、latest 标签:跟随最新发布版本
文档规定latest标签的语义为:
gcr.io/heptio-images/ark:latestlatest标签跟随最近一次正式发布的 Ark/Velero 版本——注意,是"最近一次发布",而非"最近一次提交"。
该语义在当前仓库的 CI 发布脚本中落实得非常严谨。在 hack/docker-push.sh 中定义了highest_release()函数:
- 按语义化版本降序遍历所有 git tag(
git tag -l --sort=-v:refname); - 跳过包含
beta、alpha、rc的预发布标签; - 命中的第一个正式版本即被标记为"最高版本",只有它才能获得
TAG_LATEST=true。
脚本注释中还特别解释了为什么不能用"最近创建"的 tag 作为latest:语义版本最高的标签未必是最新创建的——例如当 v1.3.0 已存在、随后为旧系列补发了 v1.2.2 时,latest仍然应该是 v1.3.0。这体现了latest的准确语义:它是"最高正式版本",而不是"时间上最新的发布"。
得到TAG_LATEST=true后,Makefile 才会把latest追加进镜像标签集合:
TAG_LATEST ?= false ifeq ($(TAG_LATEST), true) IMAGE_TAGS ?= $(IMAGE):$(VERSION) $(IMAGE):latest else IMAGE_TAGS ?= $(IMAGE):$(VERSION) endiflatest 标签的实践意义
latest便于开发测试环境总是获取最新正式版,但由于它会随版本发布漂移,生产集群一旦固定引用latest,下次滚动更新就可能静默引入破坏性变更(如 API 组/CRD 变化)。因此生产环境应优先使用具体版本标签,仅将latest用于演示与快速验证。
四、开发版本:main 标签
文档规定开发版镜像标签为:
gcr.io/heptio-images/ark:mainmain标签跟随落在main分支上的最新一次提交,即主干分支最新代码的持续构建产物。
当前仓库中该约定同样有据可查:
- 关联文档的现代版本 site/content/docs/main/image-tagging.md 中维持完全相同的语义:
velero/velero:main跟随 main 分支最新提交; - hack/docker-push.sh 注释确认 CI 会"为所有 main 分支提交"构建并推送镜像;当 CI 以分支事件触发时,
VERSION="$BRANCH",main 分支的构建自然被打上main标签; - Makefile 中
VERSION ?= main也表明:本地/未指定版本时,默认版本号即为main,与标签策略保持一致。
值得注意的是,CI 脚本对其他分支也有一套衍生规则:当构建来源是release-*这类发布分支时,版本号会被追加-dev后缀(VERSION=${VERSION}-dev),从而与正式发布标签区分开;而 PR 触发的构建只验证容器能否构建、不推送镜像。这些细节从侧面印证了"只有 main 分支对应main标签,其余非正式产物都有独立命名"的隔离原则。
main 标签的实践意义
main标签对应未经完整发版流程验证的主干代码,适合在开发、联调、尝鲜新功能(如提前验证 site/content/docs/main/backup-restore-windows.md 中提到的全平台镜像)时使用,不推荐用于生产。由于它持续滚动,即使容器环境完全相同,不同时间拉取的main镜像内容也可能不同。
五、从 Ark 到 Velero:镜像标签的演进
v0.9.0 文档诞生于项目仍叫Ark的阶段,因此文中镜像地址为gcr.io/heptio-images/ark:*。对照当前仓库可以梳理出两条清晰的演进线:
1. 项目更名:Ark → Velero
文档标题从 "Ark's image tagging policy" 变为 "Velero's image tagging policy",git 仓库从github.com/heptio/ark迁移为github.com/velero-io/velero。v0.11.0 文档(site/content/docs/v0.11.0/image-tagging.md)仍使用gcr.io/heptio-images/velero:v0.11.0,到了 v1.0.0(site/content/docs/v1.0.0/image-tagging.md)仍沿用gcr.io/heptio-images命名空间,但从 v1.10(site/content/docs/v1.10/image-tagging.md)开始改为velero/velero:v1.0.0。
2. 镜像仓库迁移:GCR → Docker Hub
当前仓库 Makefile 中REGISTRY ?= velero,默认镜像名由IMAGE ?= $(REGISTRY)/$(BIN)组合而成,即velero/velero(Docker Hub 官方命名空间)。这一默认值在运行时同样生效,见下文源码分析。
六、源码级解读:默认镜像到底怎么来
标签策略不仅约束发布流程,也决定了velero install时默认拉取的镜像。仓库源码把这条链路实现得相当完整。
1. 构建期注入版本信息
Dockerfile 通过ARG接收VERSION、REGISTRY、GIT_SHA、GIT_TREE_STATE等构建参数,并用 Go linker 的-X标志写入编译产物:
LDFLAGS="-X ${PKG}/pkg/buildinfo.Version=${VERSION} -X ${PKG}/pkg/buildinfo.GitSHA=${GIT_SHA} -X ${PKG}/pkg/buildinfo.GitTreeState=${GIT_TREE_STATE} -X ${PKG}/pkg/buildinfo.ImageRegistry=${REGISTRY}"这些值的载体是 pkg/buildinfo/buildinfo.go 中定义的Version、GitSHA、GitTreeState、ImageRegistry四个包级变量——它们专为"避免循环依赖而独立成包",供任何模块在运行时读取当前二进制对应的构建信息。
2. 运行期拼装默认镜像
intel/velero/images.go(internal/velero包)中的DefaultVeleroImage()将上述信息拼装为最终镜像引用:
func imageRegistry() string { if buildinfo.ImageRegistry == "" { return "velero" // 构建时未指定则默认 Docker Hub 的 velero 命名空间 } return buildinfo.ImageRegistry } func ImageTag() string { if buildinfo.Version == "" { return "latest" // 未注入版本时回退到 latest } return buildinfo.Version } func DefaultVeleroImage() string { return fmt.Sprintf("%s/%s:%s", imageRegistry(), "velero", ImageTag()) }可以推断其设计意图:发布构建(带版本号)默认镜像即velero/velero:vX.Y.Z;而本地未注入版本信息的开发构建则回退为velero/velero:latest——两个回退值正好对应了标签策略中的"发布版"与"最新版"两类标签,使默认行为与标签策略保持一致。
3. 安装命令中的覆盖入口
pkg/cmd/cli/install/install.go 为velero install提供了--image标志:
flags.StringVar(&o.Image, "image", o.Image, "Image to use for the Velero and node agent pods. Optional.")其默认值正是velero.DefaultVeleroImage()(见 install.go),随后该值被写入 Velero Deployment 与 node-agent DaemonSet 的容器镜像(pkg/install/deployment.go、pkg/install/daemonset.go)。
因此,实际部署时可以通过--image覆盖默认镜像,例如:
velero install \ --provider aws \ --image velero/velero:v1.16.0 \ --plugins velero/velero-plugin-for-aws:v1.4.0 \ --bucket velero-demo \ --secret-file ./credentials-velero \ --backup-location-config region=us-east-2这正是 site/content/docs/main/migration-case.md 中跨集群迁移场景的用法——两个集群可分别指定各自的镜像版本完成备份与恢复。
七、镜像标签实践清单
综合文档与仓库源码,给出选择镜像标签时的实操建议:
- 生产环境:固定使用 SemVer 标签(如
velero/velero:v1.16.0),镜像内容不可变,升级路径可控; - 验证最新正式版:可使用
latest,但要意识到它指向"最高语义版本"而非"最新创建的标签",且会随发布漂移(具体判定逻辑见 hack/docker-push.sh 中的highest_release(),alpha/beta/rc预发布版本永远不会成为latest); - 开发联调:可使用
main标签跟踪主干最新提交,但镜像内容持续变化,不要固化在生产清单中; - 自建镜像:构建时向 Dockerfile 传入
VERSION、REGISTRY、GIT_SHA、GIT_TREE_STATE四个参数(参照 Makefile 与 hack/docker-push.sh),运行时用velero version类命令核对 pkg/buildinfo/buildinfo.go 注入的版本与 Git SHA,确认镜像与预期构建一致; - 校验默认镜像:未显式指定时,
velero install使用的默认镜像由 internal/velero/images.go 决定——发布构建对应velero/velero:<Version>,开发构建回退为velero/velero:latest;需要验证或修改时通过--image标志显式控制即可。
结语
镜像标签策略虽然只有短短一页文档,却牵动着发布流水线、构建信息注入、安装默认值与日常升级操作的全链路。理解SemVer、latest、main三种标签各自的语义与漂移规则,再对照仓库中的发布脚本与源码实现,就能在部署与升级 Velero 时做到"知道自己在拉什么、拉到的到底是什么"。
【免费下载链接】veleroBackup and migrate Kubernetes applications and their persistent volumes项目地址: https://gitcode.com/GitHub_Trending/ve/velero
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考