Harbor Registry Garbage Collect(垃圾回收)
by 伊布
我们内部开发用的Harbor做Docker registry,已经跑了7个多月了,一百多个镜像仓库,1T的硬盘空间逐渐被消耗,今天一看还剩下12GB了,赶紧做Garbage Collect。
GC背景知识
docker镜像是分层的,registry在存储镜像的时候,将docker镜像分成了2部分:
- 镜像元数据(manifests),存储在
docker/registry/v2/repositories
目录中,在这里会看到registry上的项目、项目中的镜像、镜像到Layer的索引信息。 - blobs,存储在
docker/registry/v2/blobs
目录中,在这里按00-ff分目录存储了所有镜像的layer。
如果有2个镜像使用了同一个基础镜像,那么在registry上存储的时候,blobs只有一份数据,而镜像元数据中两个镜像各自的索引都有一部分layer指向相同的layer。
举个例子。
初始状态,A、B两个镜像,都是基于layer a所做的镜像;A引用a,b,B引用a,c。
A -----> a <----- B
\--> b |
c <--/
之后删掉B镜像(通过Harbor的web,或者通过api)
A -----> a B
\--> b
c
此时layer c实际已经没人用了,但是registry在删除B镜像时,只是会删除B的元数据,并不会主动删除layer c。
layer c就是无人照看的孤儿待回收的垃圾,需要GC。
GC过程
registry的GC使用“标记-清理”法。
- 第一步,标记。registry扫描元数据,元数据能够索引到的blob标记为不能删除。
- 第二步,清理。registry扫描所有blobs,如果改blob没有被标记,则删除它。
跟JVM老年代的GC是不是很像?
registry GC也是stop-the-world。将来registry会在起后台任务自动回收,不再需要手工去启动GC。
GC实战
registry GC的命令如下。它提供了一个--dry-run
的参数,可以先test一下,看到report再考虑是不是真的要GC。
registry garbage-collect [--dry-run] /path/to/config.yml
进入Harbor的registry容器,先看一下当前的硬盘情况。
df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/b 10G 197M 9.8G 2% /
tmpfs 48G 0 48G 0% /dev
tmpfs 48G 0 48G 0% /sys/fs/cgroup
/dev/sda5 997G 935G 12G 99% /storage
shm 64M 0 64M 0% /dev/shm
存储目录是/storage
,所以需要改一下config.yml。将/etc/registry/config.yml
新拷贝一份,将rootdirectory
改为/storage
。
version: 0.1
log:
fields:
service: registry
storage:
cache:
blobdescriptor: inmemory
filesystem:
rootdirectory: /storage
先dry-run一下,看看报告。
36770 blobs marked, 21213 blobs eligible for deletion
可以清理的blobs还是挺多的。去掉dry-run,实际跑一下,GC效果还可以,清理出来150GB左右的空间。
/dev/sda5 997G 783G 163G 83% /storage
由于registry上还有不少荒废的tag,如果把这些也清理掉,应该能GC出来更多空间。
Ref:
Subscribe via RSS