ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

DevOps全链路实战 | 第 7 天:Harbor 镜像版本管理与 Tag 策略配置

DevOps全链路实战 | 第 7 天:Harbor 镜像版本管理与 Tag 策略配置 第 7/18 天引言在前面六天的实战中我们完成了全链路架构设计、K8s 集群部署、Harbor 私有镜像仓库搭建、GitLab CE 自托管部署、GitLab Runner 配置以及 GitLab CI 流水线搭建。流水线已经能通过 Kaniko 将构建好的容器镜像推送到 Harbor 仓库。然而随着团队规模扩大和发布频率提升一个关键问题浮出水面镜像 Tag 该怎么管如果每次构建都用latest线上回滚时无从追溯如果每个开发分支都随意打 Tag仓库很快会变成垃圾场。今天我们将深入 Harbor 镜像版本管理设计一套科学的 Tag 策略配置 Harbor 的 Tag 保留规则Tag Retention与垃圾回收机制确保镜像仓库在长期运行中保持整洁、可追溯、可回滚。核心概念镜像 Tag 的本质与挑战Docker 镜像 Tag 不是版本号很多团队误把 Docker Tag 当作语义化版本号SemVer使用但实际上 Tag 只是一个指向镜像 manifest 的可变标签。同一个 Tag如v1.2.0可以被覆盖推送多次底层 digestSHA256才是镜像的真正唯一标识。 代码示例# 查看镜像的 digest不可变唯一标识docker inspect –format‘{{index .RepoDigests 0}}’ harbor.stellardata.top/app/frontend:v1.2.0# 输出示例: harbor.stellardata.top/app/frontendsha256:a1b2c3d4e5…# 同一个 Tag 推送两次后 digest 不同docker pull harbor.stellardata.top/app/frontend:v1.2.0docker image inspect –format‘{{.Id}}’ harbor.stellardata.top/app/frontend:v1.2.0# 每次重新构建后 .Id 会变化常见 Tag 策略对比策略示例优点缺点latestapp:latest简单不可追溯无法回滚语义版本app:1.2.0语义清晰需手动维护版本号Git Commitapp:a1b2c3d自动化唯一不可读构建号app:build-42自动递增跨分支可能冲突混合策略app:1.2.0-a1b2c3d兼具语义与唯一性Tag 较长在 CI/CD 流水线中最佳实践是采用混合策略主版本号 Git Commit 短哈希 构建时间戳既保证可读性又保证唯一性同时配合 Harbor 的不可变 Tag 功能防止覆盖。实战步骤Tag 策略设计与 Harbor 配置第一步设计生产级 Tag 命名规范我们定义一套适用于 GitLab CI 的 Tag 生成方案。在.gitlab-ci.yml中动态生成镜像 Tag 代码示例# .gitlab-ci.yml 片段 — 构建阶段的 Tag 生成逻辑variables:HARBOR_REGISTRY: “harbor.stellardata.top”IMAGE_NAME: “app/frontend”# 短 commit hash (前 8 位)SHORT_SHA: “${CI_COMMIT_SHORT_SHA}”# 构建日期 (用于时间排序)BUILD_DATE: “${CI_PIPELINE_CREATED_AT}”build_image:stage: buildimage:name: gcr.io/kaniko-project/executor:v1.23.0-debugentrypoint: [“”]script:# 生成多维度 Tag: 语义版本-commit hash– TAG_VERSION“CI_COMMIT_REF_NAME−{CI\_COMMIT\_REF\_NAME}-CI_COMMIT_REF_NAME−{CI_COMMIT_SHORT_SHA}”– /kaniko/executor–context“${CI_PROJECT_DIR}”–dockerfile“${CI_PROJECT_DIR}/Dockerfile”–destination“HARBOR_REGISTRY/{HARBOR\_REGISTRY}/HARBOR_REGISTRY/{IMAGE_NAME}{TAG_VERSION}”–destination“HARBOR_REGISTRY/{HARBOR\_REGISTRY}/HARBOR_REGISTRY/{IMAGE_NAME}{CI_COMMIT_SHORT_SHA}”–destination“HARBOR_REGISTRY/{HARBOR\_REGISTRY}/HARBOR_REGISTRY/{IMAGE_NAME}:latest”–build-arg“BUILD_DATE${BUILD_DATE}”–build-arg“GIT_COMMIT${CI_COMMIT_SHA}”–cachetrue–cache-repo“HARBOR_REGISTRY/{HARBOR\_REGISTRY}/HARBOR_REGISTRY/{IMAGE_NAME}:cache”rules:– if: $CI_COMMIT_BRANCH “main”variables:TAG_VERSION: “prod-${CI_COMMIT_SHORT_SHA}”– if: $CI_COMMIT_BRANCH “develop”variables:TAG_VERSION: “dev-${CI_COMMIT_SHORT_SHA}”上面的配置同时推送三个 Tag完整的分支-commitTag 用于精确引用纯 commit hash Tag 用于快速查找latest标记最新构建。这样无论是 Argo CD 做 GitOps 部署还是人工排查问题都能快速定位到具体镜像。第二步在 Harbor 中启用 Tag 不可变Immutable TagHarbor 企业版以及开源版 v2.4支持将特定 Tag 标记为不可变防止构建流水线覆盖已发布的镜像版本。这在生产环境中至关重要。 代码示例# 通过 Harbor REST API 设置 Tag 不可变规则# 规则匹配 prod- 前缀的 Tag 设为不可变curl -X POST“https://harbor.stellardata.top/api/v2.0/projects/app/repositories/frontend/immutablerules”-H “Authorization: Basic $(echo -n ‘admin:Harbor12345’ | base64)”-H “Content-Type: application/json”-d {“tag_matching”: “prod-*”,“repo_matching”: “**”,“tag_excluding”: “”,“repo_excluding”: “”,“disabled”: false}’# 验证不可变规则已生效curl -s “https://harbor.stellardata.top/api/v2.0/projects/app/repositories/frontend/immutablerules”-H “Authorization: Basic $(echo -n ‘admin:Harbor12345’ | base64)” | python3 -m json.tool设置后任何尝试用相同 Tag 覆盖推送prod-*前缀镜像的操作都会被 Harbor 拒绝返回 HTTP 409 Conflict。这从仓库层面杜绝了”Tag 漂移”问题。第三步配置 Tag 保留策略Tag Retention随着持续构建镜像数量会无限增长。如果不做清理磁盘空间很快耗尽。Harbor 的 Tag Retention 功能可以按规则自动保留若干版本的 Tag其余的自动删除。 代码示例#!/usr/bin/env python3“”Harbor Tag Retention 策略配置脚本为指定项目创建保留规则– prod-* Tag: 保留最近 30 个– dev-* Tag: 保留最近 10 个– 其他: 保留最近 5 个“”import requestsimport base64import jsonHARBOR_URL “https://harbor.stellardata.top”USERNAME “admin”PASSWORD “Harbor12345”PROJECT_ID 3 # app 项目 IDauth base64.b64encode(f{USERNAME}:{PASSWORD}.encode()).decode()headers {“Authorization”: fBasic {auth}, “Content-Type”: “application/json”}# 创建保留策略retention_policy {“algorithm”: “or”,“rules”: [{“action”: “retain”,“scope_selectors”: {“repositories”: [{“kind”: “doublestar”, “decoration”: “repoMatches”, “pattern”: “**”}]},“tag_selectors”: [{“kind”: “doublestar”, “decoration”: “matches”, “pattern”: “prod-*”}],“params”: {“latest”: 30}},{“action”: “retain”,“tag_selectors”: [{“kind”: “doublestar”, “decoration”: “matches”, “pattern”: “dev-*”}],“params”: {“latest”: 10}},{“action”: “retain”,“tag_selectors”: [{“kind”: “doublestar”, “decoration”: “matches”, “pattern”: “**”}],“params”: {“latest”: 5}}],“trigger”: {“kind”: “Schedule”, “settings”: {“cron”: “0 0 3 * * *”}, “references”: []}}resp requests.post(f{HARBOR_URL}/api/v2.0/retentions,headersheaders,json{“scope_selectors”: {}, “rules”: retention_policy[“rules”],“trigger”: retention_policy[“trigger”]})print(fRetention policy created: {resp.status_code})print(json.dumps(resp.json(), indent2) if resp.status_code in (200, 201) else resp.text)上面的 Python 脚本通过 Harbor v2.0 REST API 创建了三条保留规则生产镜像保留 30 个版本、开发镜像保留 10 个版本、其余保留 5 个版本。定时任务每天凌晨 3 点执行清理。算法使用or逻辑意味着只要满足任一规则 Tag 就会被保留不会被误删。第四步配置垃圾回收Garbage CollectionTag Retention 删除的只是 Tag 引用底层的 Blob 数据并不会立即释放。需要配合 Harbor 的垃圾回收机制才能真正回收磁盘空间。 代码示例# 在 Harbor 部署目录执行垃圾回收需先停止 Harborcd /opt/harbordocker-compose stop# 执行垃圾回收不带 –dry-run 为真实执行docker run -it –name gc –rm-v /data/harbor/registry:/storage-e “REGISTRY_REDIS_ADDRredis:6379”goharbor/registry-photon:v2.12.0 garbage-collect–dry-run /etc/registry/config.yml# 确认无误后执行真实回收docker run -it –name gc –rm-v /data/harbor/registry:/storage-e “REGISTRY_REDIS_ADDRredis:6379”goharbor/registry-photon:v2.12.0 garbage-collect/etc/registry/config.yml# 重启 Harbordocker-compose up -d对于在线垃圾回收Harbor v2.0 支持可以在 Web 界面”配置管理 → 垃圾回收”中设置定时任务无需停机 代码示例# Harbor values.yaml 中的 GC 配置Helm 部署方式harbor:gc:enabled: trueschedule: “0 0 4 * * *” # 每天凌晨 4 点执行forceSecureGc: false # 不强制停止 Harborpersistence:persistentVolumeClaim:registry:size: 200GistorageClass: “nfs-client”第五步验证 Tag 策略与镜像溯源部署完成后我们需要验证整套 Tag 策略是否按预期工作。模拟一次完整构建并检查 Harbor 中的镜像版本记录 代码示例# 1. 模拟 GitLab CI 构建推送main 分支docker tag app/frontend:local harbor.stellardata.top/app/frontend:prod-a1b2c3d4docker push harbor.stellardata.top/app/frontend:prod-a1b2c3d4# 2. 查看 Harbor 仓库中的所有 Tagcurl -s “https://harbor.stellardata.top/api/v2.0/projects/app/repositories/frontend/artifacts?with_tagtrue”-H “Authorization: Basic $(echo -n ‘admin:Harbor12345’ | base64)”| python3 -c import sys, jsondata json.load(sys.stdin)for artifact in data:digest artifact[‘digest’][:19]tags [t[‘name’] for t in artifact.get(‘tags’, [])]push_time artifact.get(‘push_time’, ‘N/A’)print(f’ Digest: {digest}… Tags: {tags} Pushed: {push_time})# 3. 验证不可变 Tag 规则 — 尝试覆盖推送应被拒绝docker tag nginx:latest harbor.stellardata.top/app/frontend:prod-a1b2c3d4docker push harbor.stellardata.top/app/frontend:prod-a1b2c3d4# 预期输出: error: tag prod-a1b2c3d4 is immutable# 4. 查看保留策略执行日志curl -s “https://harbor.stellardata.top/api/v2.0/retentions/1/tasks”-H “Authorization: Basic $(echo -n ‘admin:Harbor12345’ | base64)”| python3 -m json.tool | head -50通过以上验证我们可以确认每次构建都会生成包含 commit hash 的唯一 Tag生产 Tag 不可被覆盖超出保留数量的旧 Tag 会被自动清理垃圾回收会定期释放磁盘空间。这构成了一个闭环的镜像版本管理体系。常见问题Q1Tag 保留策略执行后磁盘空间没有释放Tag Retention 只删除 Tag 引用不删除底层 Blob。必须执行垃圾回收才能释放空间。如果使用在线 GC请确认 Harbor 版本 ≥ v2.0 且gc.forceSecureGc设置为false。离线 GC 需要先停止 Harbor 再执行否则可能导致数据不一致。Q2不可变 Tag 规则误拦截了正常推送检查 Tag 匹配模式。prod-*会匹配所有以prod-开头的 Tag如果 CI 流水线在开发阶段也使用该前缀就会被拦截。建议区分前缀prod-*生产、staging-*预发布、dev-*开发并为每种环境设置不同的不可变规则和保留数量。Q3Argo CD GitOps 如何配合 Tag 策略做回滚Argo CD 通过追踪 Git 仓库中的镜像 Tag 来决定部署版本。当需要回滚时只需在 Git 中将部署清单的镜像 Tag 改回之前的 commit hash Tag如prod-a1b2c3d4Argo CD 会自动检测到变更并执行回滚。由于我们保留了 30 个生产版本90 天内的任意版本都可以快速回滚。也可以配合 Argo CD Image Updater 自动选择最新通过扫描的镜像 Tag。Q4多架构镜像multi-arch的 Tag 如何管理使用docker buildx构建多架构镜像时同一个 Tag 会指向一个 manifest list其中包含不同架构amd64/arm64的子镜像。Harbor v2.0 完整支持 manifest list保留策略和不可变规则同样适用于多架构镜像的 Tag。建议在 CI 中统一使用 buildx 构建确保同一个 Tag 在所有架构下行为一致。总结今天我们围绕 Harbor 镜像版本管理这个核心主题完成了一套生产可用的 Tag 策略设计Tag 命名规范采用分支名-commit hash的混合策略兼顾可读性与唯一性在 GitLab CI 中自动生成不可变 Tag通过 Harbor REST API 将prod-*前缀的 Tag 设为不可变从仓库层面防止 Tag 覆盖Tag 保留策略使用 Python 脚本通过 Harbor API 配置自动清理规则生产保留 30 版、开发保留 10 版、其余保留 5 版垃圾回收配置在线/离线 GC 定时任务真正释放磁盘空间验证溯源通过 REST API 查询镜像版本记录验证不可变规则与保留策略的执行效果这套方案让镜像仓库在持续高频构建的压力下依然保持整洁有序每个镜像版本都可追溯、可回滚、可审计为后续 Argo CD GitOps 部署提供了可靠的镜像版本基础。下期预告明天我们将进入 GitOps 的核心环节——第 8 天Argo CD 部署与 GitOps 配置仓库创建。将安装 Argo CD 到 K8s 集群创建 GitOps 配置仓库结构打通从 Git 到集群的自动化部署通道。敬请期待系列大纲全链路架构总览从代码提交到灰度发布的完整管道设计K8s 集群与网络基础kubeadm 离线部署与 Cilium 网络插件Harbor 私有镜像仓库部署与验证Helm 安装与镜像推送GitLab CE 自托管部署代码仓库与项目管理平台GitLab Runner 配置K8s Executor 与 RBAC 权限设置GitLab CI 流水线搭建.gitlab-ci.yml 与 Kaniko 无守护进程构建Harbor 镜像版本管理与 Tag 策略配置今天Argo CD 部署与 GitOps 配置仓库创建CI 与 CD 联动从代码提交到部署的全自动闭环Prometheus 部署kube-prometheus-stack 与 ServiceMonitor 指标采集Grafana 看板搭建K8s 标准面板与自定义业务看板告警规则与 Alertmanager钉钉/邮件通知渠道配置Argo Rollouts 安装与基础概念CRD 与 Rollout 资源定义金丝雀发布实战setWeight 流量分割与 pause 步骤AnalysisTemplate 指标分析与自动回滚机制全链路端到端演示代码提交→构建→灰度→监控→告警完整流程生产化加固要点Harbor/GitLab/Argo CD 高可用方案供应链安全闭环Trivy 扫描 cosign 签名 Kyverno 验签
返回列表