当 GC 失败时如何手动清理 blob 目录
解读
国内生产环境普遍使用 Harbor 或 Docker Distribution 作为私有镜像仓库。GC(Garbage Collection)失败通常表现为 磁盘空间持续增长、registry 日志报 “blob not found”、Harbor UI 清理任务卡住 或 S3 后端出现 404。根本原因是 registry 的 mark-and-sweep 阶段中断,导致 orphan blob(已无任何 manifest 指向的层文件)未被删除,堆积在 docker/registry/v2/blobs/sha256/* 目录。手动清理必须在 只读模式 下进行,否则并发推送会产生数据不一致,甚至触发 镜像拉取 500 错误。因此,面试官想确认你能否在 零停机 或 可接受窗口 内,安全地回收空间并恢复服务。
知识点
- registry 存储结构:
blobs/sha256/xx/xxx…存放真实层文件,repositories/*/manifests存放镜像索引,_layers存放软链接。 - GC 两阶段:read-only=true → docker-registry garbage-collect config.yml → 生成 mark 清单 → 删除未标记 blob。
- GC 失败常见根因:
- S3 令牌过期 导致 list 中断;
- NFS 锁竞争 造成 manifest 读取超时;
- Harbor 2.1 之前版本 的 Redis 缓存与数据库不一致,mark 阶段漏扫。
- 手动清理原则:先备份、再只读、再二次标记、再删除、最后校验。
- 工具链:
registry garbage-collect --dry-run、fuser、lsof、rsync --delete、sha256sum比对。
答案
步骤以 Harbor 2.8 + filesystem 存储 为例,S3 后端只需把本地路径换成 s3cmd 即可。
-
禁用写操作
在 harbor.yml 设置read_only: true并 重启 harbor-core 与 registry;若仅用原生 distribution,给 registry 加环境变量REGISTRY_STORAGE_MAINTENANCE_READONLY=true。 -
备份元数据
cp -a /data/registry/docker/registry/v2/repositories /backup/repositories_$(date +%F)
只备份元数据,不备份 blob,节省空间与时间。 -
二次标记(生成白名单)
docker run --rm -v /data/registry:/registry -v /etc/registry/config.yml:/etc/registry/config.yml registry:2.8 garbage-collect --dry-run /etc/registry/config.yml > /tmp/mark.list 2>&1
解析mark.list,提取 “marked” 的 blob digest,写入/tmp/white.list,一行一个sha256:xxx…。 -
扫描现存 blob
find /data/registry/docker/registry/v2/blobs/sha256 -type f -name 'data' | awk -F/ '{print $(NF-1)}' | sort > /tmp/all.blob -
求差集得 orphan
comm -23 /tmp/all.blob /tmp/white.list > /tmp/orphan.blob -
安全删除
while read dgst; do rm -rf /data/registry/docker/registry/v2/blobs/sha256/${dgst:0:2}/$dgst; done < /tmp/orphan.blob
删除后 再次运行sha256sum抽样校验仍在白名单中的 blob 可正常读取,确保无误删。 -
恢复写操作
将read_only改回 false,重启 registry;Harbor 需额外 清空 Redis 缓存redis-cli -n 2 FLUSHDB,防止旧 manifest 缓存命中。 -
验证
docker pull 私有域名/项目/镜像:tag成功,GC 后磁盘空间下降 与du -sh /data/registry对比,Harbor 项目配额实时刷新 即视为完成。
拓展思考
- 在线清理方案:若业务 不允许只读,可搭建 双实例主从(利用 harbor replication),在从库做 GC,完成后 切换 SLB 流量,实现 用户无感知。
- 自动化兜底:在 夜维脚本 里先
garbage-collect --dry-run统计可释放空间,超过阈值 20 % 才触发只读与真实 GC,否则只报警,避免频繁中断。 - 版本缺陷:Harbor 2.3 之前存在 artifact 与 blob 不同步 的 bug,需 升级至 2.5+ 并执行
migrate -t 220修复数据库,否则手动清理后仍会出现 幽灵记录。 - S3 后端清理加速:使用 s3cmd lifecycle 先标记 orphan 对象,再调用 registry GC,减少 LIST 请求费用;同时开启 S3 多版本暂停,防止删除后又被版本化占用空间。