Harbor OVA 版垃圾回收(Garbage Collection)功能验证指南与实现原理
【免费下载链接】harborAn open source trusted cloud native registry project that stores, signs, and scans content.项目地址: https://gitcode.com/GitHub_Trending/ha/harbor
本指南以 Harbor OVA 虚拟机的垃圾回收(Garbage Collection,GC)验证流程为核心,完整覆盖从部署 OVA、推送与删除镜像、到通过重启触发 GC 并核对磁盘空间的每一步实操细节,同时结合 Harbor 源码(GC 控制器与 GC Job 实现)深入解释 GC 的 mark/sweep 工作原理。读完本文,你将掌握如何在 OVA 环境中验证 Harbor 的 GC 功能、如何判定回收是否成功,以及 GC 在底层是如何识别并删除无引用数据块的。
背景:OVA 版 Harbor 与垃圾回收
Harbor 是一个开源的云原生镜像仓库,支持内容签名与漏洞扫描。OVA(Open Virtual Appliance)是 Harbor 针对 vSphere 环境提供的虚拟设备交付形态,将 Harbor 的整套组件(core、registry、jobservice、postgresql、redis 等)打包进一台虚拟机,可通过 vCenter 直接部署,适合在 ESXi 环境中快速落地。关于 OVA 部署方式的更多用例,可参考 tests/testcases/Group5-OVA-install-config 目录下的网络配置(5-01)、重启(5-02)、HTTPS(5-04)、LDAP 集成(5-05)等测试用例。
在 Harbor 中,用户在 UI 或通过 Docker CLI 删除镜像后,磁盘空间并不会立即释放。删除操作只是移除了镜像在 Harbor 数据库中的元数据(tag 引用),而实际存储在 registry 存储后端(如/data卷)中的 blob(配置层、镜像层、manifest)仍然占用空间。垃圾回收(Garbage Collection,Harbor 内部任务类型GARBAGE_COLLECTION,见 src/jobservice/job/known_jobs.go)就是用于扫描并清理这些无引用的数据块,从而回收磁盘空间。
因此,验证 OVA 版 Harbor 的 GC 功能是否正常,是部署后运维检查中的重要一环,也是 5-03-OVA-garbage-collection.md 这一测试用例的核心目的:确认 OVA 版 Harbor 能够通过垃圾回收释放已删除镜像占用的空间。
环境准备
在执行本验证流程前,需要准备以下环境,缺一不可:
- 一个 Harbor 的 OVA 二进制文件:用于在 vSphere 中部署 Harbor 虚拟机;
- vCenter 环境:至少包含一台 ESX 主机,且网络支持 DHCP(OVA 默认通过 DHCP 获取 IP);
- 一台装有 Docker CLI 的 Linux 主机:作为 Docker 客户端,用于
docker login和docker push。
注意:GC 验证会涉及对 Harbor VM 的电源操作(关机、开机)和 vSphere 控制台操作,请确保具备 vCenter 的相应权限,并在非生产或测试环境中执行。
完整验证流程
验证的整体思路是:先部署一个未开启 GC的 Harbor,推送一批镜像并删除,记录/data卷的磁盘占用;然后修改 OVA 虚拟机设置开启 GC,重启虚拟机触发一次 GC,再次检查/data卷占用是否下降,并核对 GC 日志有无报错;最后再重复一轮推送、删除与重启,确认 GC 在第二次重启后依然有效。
第一步:部署未开启 GC 的 Harbor OVA
在 vCenter 中部署 Harbor OVA 虚拟机,部署过程中将 "Garbage Collection" 选项设置为false(即初始不启用垃圾回收)。这一步是后续对比的关键:只有在 GC 关闭的状态下,删除镜像后空间不会被回收,才能通过重启开启 GC 来验证回收效果。
第二步:创建项目并推送镜像
在 Harbor 的 Web UI 中创建一个项目(Project)。
在 Docker 客户端主机上使用管理员账号登录 Harbor:
docker login <harbor_host>按提示输入 admin 用户名与密码。
向刚创建的项目推送若干镜像:
docker tag <image>:<tag> <harbor_host>/<project>/<image>:<tag> docker push <harbor_host>/<project>/<image>:<tag>镜像总大小建议至少 500MB。只有保证足够的镜像体积,GC 前后通过
df -h看到的磁盘占用差异才会明显、可判定。
第三步:删除镜像并记录磁盘占用
在 Harbor 的 Web UI 中删除第二步推送的镜像(此时 GC 未开启,存储中的数据块不会被清理)。
在 vSphere 中打开 Harbor 虚拟机的控制台,以 root 用户登录,执行:
df -h /data记录输出中的Used(已使用)空间数值。这是 GC 执行前的基线数据。
第四步:关机并开启 GC 选项
- 关闭 Harbor 虚拟机(Power off)。
- 右键点击虚拟机,选择 "Edit Settings"(编辑设置)。
- 将 "Garbage Collection" 选项设置为true。
- 重新开机(Power on)。
这是 OVA 版 Harbor 触发 GC 的方式:通过虚拟机配置选项在启动时执行一次垃圾回收。因此每次希望执行 GC 时,都需要在关机状态下修改该项并重启,这也是本用例第 15 步要验证"第二次重启后 GC 依然有效"的原因。
第五步:等待服务就绪并核对空间
虚拟机开机后,等待一段时间,直到通过浏览器可以访问 Harbor 服务(确认服务已就绪)。
再次通过 vSphere 控制台以 root 登录虚拟机,执行:
df -h /data将此时
/data卷的 Used 数值与第三步记录的值进行对比。
第六步:检查 GC 日志
查看/data目录下垃圾回收的日志文件,确认执行过程中没有错误:
# 以 root 身份在 Harbor VM 控制台执行 ls -lt /data | head # 根据日志文件时间与内容检查是否有 error预期 GC 日志中应无 error 级别的错误。
第七步:重复验证(第二次 GC)
- 重复第三步至第四步前半段:在 UI 中删除若干新推送的镜像(保证有新产生的"待回收"数据),再次执行关机、Edit Settings 确认 "Garbage Collection" 仍为 true、开机。
- 重复第五、六步的检查,确认 GC 在第二次重启后依然能够正常工作并释放空间。
提示:也可以顺带练习关闭 GC 后再验证,用于对比 GC 关闭状态下删除镜像后
df -h /data的 Used 值基本不变。
预期结果
完成上述流程后,应满足以下预期:
- 第五步中,
/data卷的Used 空间应显著下降,即被删除镜像的空间被回收; - 第六步中,GC 日志文件不应包含任何错误;
- 第七步中,第二次重启触发的 GC 依然有效,空间再次被正确回收。
深入:GC 在源码中是如何工作的
上述验证流程之所以能释放空间,背后是 Harbor 的垃圾回收任务机制。理解这一点有助于判断日志输出、参数行为以及排查回收不彻底等问题。
GC 的执行入口与任务调度
Harbor 将 GC 实现为一个 JobService 任务,任务类型名为GARBAGE_COLLECTION(定义于 src/jobservice/job/known_jobs.go)。GC 控制器(src/controller/gc/controller.go)提供了完整的管理接口:
Start:手动启动一次 GC 任务,会创建 Execution 与 Task,并携带delete_untagged、delete_tag、dry_run、workers、redis_url_reg、time_window等参数(见 controller.go);Stop:停止正在运行的 GC 任务;GetSchedule/CreateSchedule/DeleteSchedule:查看、创建(按 cron 定时)与删除 GC 调度计划。
OVA 版在开机时触发 GC,本质上就是系统启动阶段发起一次 GC 执行;而标准部署中,则可以通过 UI 的"垃圾回收"页面手动触发或按 cron 计划定时触发。
GC 任务的核心执行逻辑:mark 与 sweep 两阶段
GC 的实际执行逻辑在 src/jobservice/job/impl/gc/garbage_collection.go 的GarbageCollector.Run中(见 garbage_collection.go),分为两个阶段:
mark(标记)阶段:找出所有"无引用"的候选数据块。包括:
- 从 Harbor 数据库中删除过的 artifact(记录在 artifact trash 中)对应的 manifest 与 blob;
- 未被任何 manifest 引用的 untagged blob(
delete_untagged开启时,还会先把未打标签的 artifact 移入 trash); - 通过
blobMgr.UselessBlobs查询出的无引用 blob。
mark 阶段只会把候选 blob 的状态标记为
StatusDelete,并不会真正删除数据;同时会统计"可释放空间"的粗略估计值并写入执行结果。sweep(清扫)阶段:真正执行删除。对于 manifest,会先通过 registry v2 API 删除 tag/revision,再调用 registry controller 的
DeleteManifest删除存储中的 manifest,并同步清理数据库中的关联记录;对于普通 blob(config、layer),调用registryCtlClient.DeleteBlob删除存储中的数据并删除数据库记录。删除完成后,GC 会把实际释放的空间(freed_space)、清理的 blob 数(purged_blobs)和 manifest 数(purged_manifests)通过Checkin写回执行结果(见 garbage_collection.go)。
此外,sweep 完成后还会清理 registry 的 Redis 缓存键(blobs::*、repository::*),这是为了解决 registry 的已知缓存问题,保证后续拉取行为正确(见 garbage_collection.go)。
关键参数及其对验证结果的影响
GC 任务的参数解析见parseParams(garbage_collection.go),理解这些参数有助于解释"为什么有的镜像删了空间却回收不掉":
| 参数 | 默认值 | 说明 |
|---|---|---|
delete_untagged | true | 是否删除未打标签(untagged)的 artifact。开启时,GC 会把没有 tag 的 artifact 移入 trash 并最终清理其数据 |
delete_tag | true | 是否在删除 manifest 时同步删除其在 registry 后端存储中的 tag 记录(通过 v2 DELETE manifest API) |
dry_run | false | 是否只做演练。开启时仅标记候选并统计可释放空间,不实际删除任何数据 |
time_window | 2(小时) | 时间窗口。只有在该时间窗口之前创建/更新的候选数据才会被纳入清理,避免误删刚上传的数据;测试调试时可设为 0 |
workers | 1 | 删除 blob 的并发工作线程数,是 sweep 阶段的并行度参数 |
redis_url_reg | 无 | registry 使用的 Redis 地址,用于 sweep 后的缓存清理 |
例如,若镜像删除后空间未立即回收,常见原因可能包括:GC 尚未运行、time_window内保护、数据仍被 tag 引用,或处于 dry run 模式。在 OVA 验证流程中,只有"删除镜像 → 重启触发 GC"两个动作都完成后,/data的 Used 值才会下降。
常见问题排查
- GC 后空间未下降:确认 GC 选项确实已设为 true 并完成了一次重启;确认日志中无报错;确认删除的镜像在数据库中已无 tag 引用(未打标签的镜像需要
delete_untagged生效)。 - GC 日志位置:OVA 版 Harbor 的 GC 日志位于
/data目录下,通过 vSphere 控制台 root 登录即可查看。 - 只删 tag 不删数据:Harbor 中删除镜像的 tag 只是解除引用,blob 仍被保留,等待下一次 GC 的 mark 阶段将其识别为无引用数据并清理,这是正常的延迟释放设计。
小结
本文以 OVA 版 Harbor 的 GC 验证为主线,给出了从环境准备、推送/删除镜像、开机触发 GC、df -h /data对比到日志核查的完整可复现流程,并深入源码说明了 GC 的 mark/sweep 两阶段原理与关键参数。按此流程执行,即可确认 OVA 版 Harbor 的垃圾回收功能正常,确保删除镜像后存储空间能被有效回收。完整的原始测试用例定义见 5-03-OVA-garbage-collection.md,相关实现可继续阅读 src/controller/gc/controller.go 与 src/jobservice/job/impl/gc/garbage_collection.go。
【免费下载链接】harborAn open source trusted cloud native registry project that stores, signs, and scans content.项目地址: https://gitcode.com/GitHub_Trending/ha/harbor
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考