工作日志——Docker Registry GC

2024-06-11 07:08
文章标签 工作 日志 docker gc registry

本文主要是介绍工作日志——Docker Registry GC,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

近期调研了Registry存储空间管理相关的内容,特与大家分享相关收获。调研时Registry最新版本为registry:2.5.0-rc.1

相关资料

这里是index:
https://github.com/docker/distribution

这里是roadmap,包括registry未来会实现的特性:
https://github.com/docker/distribution/blob/master/ROADMAP.md

这篇是API说明:
https://github.com/docker/distribution/blob/master/docs/spec/api.md

这篇是gc功能的说明:
https://github.com/docker/distribution/blob/e66f9c14409f1834fe40278635da55ca4063c4f6/docs/garbage-collection.md

这篇介绍了registry部署相关内容:
https://github.com/docker/distribution/blob/master/docs/deploying.md

这篇介绍了registry的配置:
https://github.com/docker/distribution/blob/master/docs/configuration.md

这篇介绍了registry的token认证方式:
https://github.com/docker/distribution/blob/master/docs/spec/auth/token.md

registry简易安装

首先来介绍如何在本地安装一个简易的registry。我们用以下命令可以创建一个容器化的registry:

docker run -d -v `pwd`/registry/data/:/var/lib/registry --name registry -p 5000:5000 registry:2.5.0-rc.1
  • 1
  • 1

上述指令中,我们使用了官方的registry镜像,并将镜像中的/var/lib/registry挂载到主机中,该目录就是保存manifests和layers数据的目录。

通过下面两条指令可以向本地的registry服务push一个镜像:

  $ docker tag <local-image> localhost:5000/nginx$ docker push localhost:5000/nginx
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

push之后,我们可以在挂载目录中看到数据了:

  $ ls registry/data/docker/registry/v2/blobs  repositories
  • 1
  • 2
  • 1
  • 2

其中blobs子目录保存的layers数据,repositories子目录保存的是manifests数据。

现在我们可以通过API来访问registry服务了,但此时会发现delete相关的API是不能正常工作的(返回405错误),原来registry默认的配置是关闭delete相关操作的,需要修改默认配置来开启删除操作。

delete操作

我们可以在容器中修改配置并重启,也可以通过volume方式来将配置文件挂载到宿主机,从而可以在宿主机中修改配置。

首先创建一个配置文件,在配置文件中开启delete开关:

  vi registry/config/config.ymlversion: 0.1log:fields:service: registrystorage:delete:enabled: true #打开delete开关cache:blobdescriptor: inmemoryfilesystem:rootdirectory: /var/lib/registryhttp:addr: :5000headers:X-Content-Type-Options: [nosniff]health:storagedriver:enabled: trueinterval: 10sthreshold: 3
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

将配置文件挂载到registry容器中。

  docker run -d -v `pwd`/registry/data/:/var/lib/registry -v `pwd`/registry/config/config.yml:/etc/docker/registry/config.yml --name registry -p 5000:5000 registry:2.5.0-rc.1
  • 1
  • 1

这样我们就可以通过API执行delete相关操作了。通过API说明可以发现删除manifest需要获取对应的digest,这些digest需要访问相应的get接口来获取。

通过下面的方式可以获取nginx:latest镜像的digest,响应的Docker-Content-Digest头就是该镜像的digest值。注意,该方法发送的是一个HEAD请求,请求设置的Accept头是必须的,否则获取不到正确的digest。

  $ curl -I -H "Accept: application/vnd.docker.distribution.manifest.v2+json" localhost:5000/v2/nginx/manifests/latestHTTP/1.1 200 OKContent-Length: 2187Content-Type: application/vnd.docker.distribution.manifest.v2+jsonDocker-Content-Digest: sha256:94d217c3f369593b85b402d423734a3b6eb63fe07534e3123ac6f60e83b3ce24Docker-Distribution-Api-Version: registry/2.0Etag: "sha256:94d217c3f369593b85b402d423734a3b6eb63fe07534e3123ac6f60e83b3ce24"X-Content-Type-Options: nosniffDate: Thu, 16 Jun 2016 08:25:25 GMT
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

有了digest就可以调用对应的API来删除manifest

  $ curl -i -X DELETE localhost:5000/v2/nginx/manifests/sha256:94d217c3f369593b85b402d423734a3b6eb63fe07534e3123ac6f60e83b3ce24HTTP/1.1 202 AcceptedDocker-Distribution-Api-Version: registry/2.0X-Content-Type-Options: nosniffDate: Thu, 16 Jun 2016 04:53:56 GMTContent-Length: 0Content-Type: text/plain; charset=utf-8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

虽然删除了manifest,通过API也读取不到对应镜像的信息了,但是blobs子目录下的空间并没有被释放。原来DELETE API只是删除了manifest对layer的引用,并未真正的删除对应的layer,删除layer是通过registry gc完成的。

此外,如果registry配置了token认证方式(.auth.token配置项),在调用API删除之前还需要获取有删除权限的token,否则API会返回401错误。需要根据响应的Www-Authenticate header来确定scope信息。

registry gc

在了解gc之前,我们先简单了解一下manifest和layer的关系。每当向registry push一个镜像,就会生成一个manifest,它描述了镜像的信息。从GET API中获取的内容就是从manifest文件中读取的,manifest会记录镜像引用的layer,两者的关系如下图所示:

manifests vs layers

为了节省空间,相同的layer只会在registry中保存一次,这样不同镜像就可能会引用相同的layer。因此不能随意删除registry中的layer,否则可能使得镜像无法下载。当删除manifest时,就会出现下图所示情况:

remove manifest

此时下方的三个layer将变为未引用的状态,未引用的layer对于registry来说就像垃圾一样,占用空间但却没有用处。registry gc功能就是用来清理这些未引用的layer。

上文提到DELETE API并未真正删除layer,其相当于是dereference操作,从而产生未引用的layer。

registry gc的工作原理参考这里,它分成mark和sweep两个阶段。mark阶段会扫描所有manifest,列出所有引用的layer的集合。sweep阶段会扫描所有layer,不在mark集合中的layer会被删除。

我们可以通过容器中的registry指令来执行gc功能:

  $ registry garbage-collect /etc/docker/registry/config.yml INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/a9/a97a0c1976715d95ee07e1e086011e6321919ba85452d5c709c9201af2262cb7  go.version=go1.6.2 instance.id=a3385b4b-a122-4cca-ae23-39f2dce261e3INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/d0/d0ca440e86378344053c79282fe959c9f288ef2ab031411295d87ef1250cfec3  go.version=go1.6.2 instance.id=a3385b4b-a122-4cca-ae23-39f2dce261e3INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/0e/0eff792599d8378f8ce2059ad0e72c1516ca53cee451d50810cc154683bc0b0e  go.version=go1.6.2 instance.id=a3385b4b-a122-4cca-ae23-39f2dce261e3INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/7c/7c99bfba27294e65ec1db8c05c872e029ddc99442c48f8cc58cdf04d33bfc19d  go.version=go1.6.2 instance.id=a3385b4b-a122-4cca-ae23-39f2dce261e3INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/84/847e761c0c61dc5c0f3daa5f8e447bf473ef713ea49dc72c76818fe3bdbbaced  go.version=go1.6.2 instance.id=a3385b4b-a122-4cca-ae23-39f2dce261e3INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/94/94d217c3f369593b85b402d423734a3b6eb63fe07534e3123ac6f60e83b3ce24  go.version=go1.6.2 instance.id=a3385b4b-a122-4cca-ae23-39f2dce261e3INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/a3/a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4  go.version=go1.6.2 instance.id=a3385b4b-a122-4cca-ae23-39f2dce261e3
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

此时可以发现blobs子目录下的数据已被清理了。
增加–dry-run参数可以不执行删除操作,而查看两阶段的扫描结果:

  $ registry garbage-collect --dry-run /etc/docker/registry/config.yml                                                               nginxnginx: marking manifest sha256:d4dc76fa2b8c3a4de832e0fbd209c54400dfb4fe8b643c316a77ba98957ee271 nginx: marking blob sha256:6d6a6a7dae296854b09c2b3c16941416f1efe6dc89cbec1dade03f84233a783fnginx: marking blob sha256:960e66221a5aebfed7597e841ee2dfa3441b2460075041f26858320d3ba05835nginx: marking blob sha256:112f66ec2c6905325b4e7186792165a5ecb40dd25d8ceb7727ab150f88cc94c5nginx: marking blob sha256:386a96b627f3aec32aba0aa5290f37889394a76f8064202eb51dae892aaf2c1fnginx: marking blob sha256:b57f319efde35e1d14701b63c5c8fd888715ce32a7bbe13b91ac935e3c993347nginx: marking blob sha256:13b5f517f567ffc84a95a3973e51e4febf1b8f90ebcdbe31c5ee15ae55528d63nginx: marking blob sha256:a42387bfa94b3c4bef54584ba20c96b8208b3f10ce547bafa4a95b581daf7a22nginx: marking blob sha256:9b802f72d3249095f6d5dcf88d5083096d0fa00902eef6a196b1627777874a04nginx: marking blob sha256:4520c1976cedd427f135b3c7616a222e9f939a42904e44f8235bf25c326a1ab9nginx: marking blob sha256:89f4c89d72642f2db66a8402c0980aa626fb203c20ebad5570210fba9ffc79b0nginx: marking blob sha256:53629dd5771132023a7fa9c1c38c893ccb30065334e69c80b9b2c0df98f24fd3nginx: marking configuration sha256:0711f18a160cdd57068f9e8626b06fde23d93b065ea5834f9d0a753b3a1cfca513 blobs marked, 7 blobs eligible for deletionblob eligible for deletion: sha256:a97a0c1976715d95ee07e1e086011e6321919ba85452d5c709c9201af2262cb7blob eligible for deletion: sha256:d0ca440e86378344053c79282fe959c9f288ef2ab031411295d87ef1250cfec3blob eligible for deletion: sha256:0eff792599d8378f8ce2059ad0e72c1516ca53cee451d50810cc154683bc0b0eblob eligible for deletion: sha256:7c99bfba27294e65ec1db8c05c872e029ddc99442c48f8cc58cdf04d33bfc19dblob eligible for deletion: sha256:847e761c0c61dc5c0f3daa5f8e447bf473ef713ea49dc72c76818fe3bdbbacedblob eligible for deletion: sha256:94d217c3f369593b85b402d423734a3b6eb63fe07534e3123ac6f60e83b3ce24blob eligible for deletion: sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

清理流程

目前registry还没有提供自动清理的功能,应该会在未来的版本中加入。在目前的版本中,清理流程应该是这样的:

  1. push镜像之前通过API获取指定镜像已有manifest的digest
  2. push镜像
  3. 通过digest和API删除旧镜像的manifest
  4. 指定定时任务定期调用registry garbage-collect。注:调用前需修改registry配置,使其变为read-only,再执行gc,之后恢复registry配置,参考这里。

upload清理

查看repositories目录可以看到每个仓库都有一个_uploads目录,这个目录会保存镜像push时的数据。当我们在push过程中出现了中断而再次push的时候,可以发现push并不是重新开始的,这就是因为上次push的数据已在_uploads目录中,后续push操作可以从上次中断时开始。

registry对_uploads数据实现了自动清理的功能,我们可以在registry的配置中修改清理周期,参考这里。

已知问题

目前registry的清理存在以下问题:

  1. gc是非事务性操作。删除前最好置为read-only,而此时registry将暂时不能提供push服务。
  2. 没有查询manifest digest列表的API。因此push前需要先查询对应镜像的digest,否则push之后无法获取旧镜像的digest。并且如果由于网络原因未能调用DELETE API时,此时需要额外的容错逻辑和持久化策略来保证后续可以删除过期的manifest。
  3. 同样由于上述原因,对于已存在的过期的manifest无法进行清理操作。
  4. gc时间待确认,使用blobs 5.2G + repositries 28M的数据测试需要花2-3秒的扫描和清理时间。

这篇关于工作日志——Docker Registry GC的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1050485

相关文章

如何用Docker运行Django项目

本章教程,介绍如何用Docker创建一个Django,并运行能够访问。 一、拉取镜像 这里我们使用python3.11版本的docker镜像 docker pull python:3.11 二、运行容器 这里我们将容器内部的8080端口,映射到宿主机的80端口上。 docker run -itd --name python311 -p

【编程底层思考】垃圾收集机制,GC算法,垃圾收集器类型概述

Java的垃圾收集(Garbage Collection,GC)机制是Java语言的一大特色,它负责自动管理内存的回收,释放不再使用的对象所占用的内存。以下是对Java垃圾收集机制的详细介绍: 一、垃圾收集机制概述: 对象存活判断:垃圾收集器定期检查堆内存中的对象,判断哪些对象是“垃圾”,即不再被任何引用链直接或间接引用的对象。内存回收:将判断为垃圾的对象占用的内存进行回收,以便重新使用。

flume系列之:查看flume系统日志、查看统计flume日志类型、查看flume日志

遍历指定目录下多个文件查找指定内容 服务器系统日志会记录flume相关日志 cat /var/log/messages |grep -i oom 查找系统日志中关于flume的指定日志 import osdef search_string_in_files(directory, search_string):count = 0

我在移动打工的日志

客户:给我搞一下录音 我:不会。不在服务范围。 客户:是不想吧 我:笑嘻嘻(气笑) 客户:小姑娘明明会,却欺负老人 我:笑嘻嘻 客户:那我交话费 我:手机号 客户:给我搞录音 我:不会。不懂。没搞过。 客户:那我交话费 我:手机号。这是电信的啊!!我这是中国移动!! 客户:我不管,我要充话费,充话费是你们的 我:可是这是移动!!中国移动!! 客户:我这是手机号 我:那又如何,这是移动!你是电信!!

工作常用指令与快捷键

Git提交代码 git fetch  git add .  git commit -m “desc”  git pull  git push Git查看当前分支 git symbolic-ref --short -q HEAD Git创建新的分支并切换 git checkout -b XXXXXXXXXXXXXX git push origin XXXXXXXXXXXXXX

嵌入式方向的毕业生,找工作很迷茫

一个应届硕士生的问题: 虽然我明白想成为技术大牛需要日积月累的磨练,但我总感觉自己学习方法或者哪些方面有问题,时间一天天过去,自己也每天不停学习,但总感觉自己没有想象中那样进步,总感觉找不到一个很清晰的学习规划……眼看 9 月份就要参加秋招了,我想毕业了去大城市磨练几年,涨涨见识,拓开眼界多学点东西。但是感觉自己的实力还是很不够,内心慌得不行,总怕浪费了这人生唯一的校招机会,当然我也明白,毕业

禅道Docker安装包发布

禅道Docker安装包发布 大家好, 禅道Docker安装包发布。 一、下载地址 禅道开源版:   /dl/zentao/docker/docker_zentao.zip  备用下载地址:https://download.csdn.net/download/u013490585/16271485 数据库用户名: root,默认密码: 123456。运行时,可以设置 MYSQL_ROOT_P

husky 工具配置代码检查工作流:提交代码至仓库前做代码检查

提示:这篇博客以我前两篇博客作为先修知识,请大家先去看看我前两篇博客 博客指路:前端 ESlint 代码规范及修复代码规范错误-CSDN博客前端 Vue3 项目开发—— ESLint & prettier 配置代码风格-CSDN博客 husky 工具配置代码检查工作流的作用 在工作中,我们经常需要将写好的代码提交至代码仓库 但是由于程序员疏忽而将不规范的代码提交至仓库,显然是不合理的 所

828华为云征文|华为云Flexus X实例docker部署rancher并构建k8s集群

828华为云征文|华为云Flexus X实例docker部署rancher并构建k8s集群 华为云最近正在举办828 B2B企业节,Flexus X实例的促销力度非常大,特别适合那些对算力性能有高要求的小伙伴。如果你有自建MySQL、Redis、Nginx等服务的需求,一定不要错过这个机会。赶紧去看看吧! 什么是华为云Flexus X实例 华为云Flexus X实例云服务是新一代开箱即用、体

未来工作趋势:零工小程序在共享经济中的作用

经济在不断发展的同时,科技也在飞速发展。零工经济作为一种新兴的工作模式,正在全球范围内迅速崛起。特别是在中国,随着数字经济的蓬勃发展和共享经济模式的深入推广,零工小程序在促进就业、提升资源利用效率方面显示出了巨大的潜力和价值。 一、零工经济的定义及现状 零工经济是指通过临时性、自由职业或项目制的工作形式,利用互联网平台快速匹配供需双方的新型经济模式。这种模式打破了传统全职工作的界限,为劳动