Docker鏡像倉庫清理的探索之路

用友雲開發者中心是基於Docker容器進行微服務架構應用的落地與管理。相信各位同學在使用的過程中,會發現隨着Docker鏡像的增多,佔用磁盤空間也約來越多。這時我們需要清理私有鏡像倉庫中不需要的鏡像。但在實際操作時,纔會發現這本以爲很簡單的任務中卻暗藏玄機,遇到了不少的麻煩。在這裏我們分享一下清理鏡像倉庫時遇到的坑點。想要直接尋求解決方案的同學可以直接看第二部分。
一、那些年,我們在清理鏡像倉庫時走過的坑
坑點1:官方提供的接口並不能真正的刪除鏡像
這着實是最大的坑點。很多同學查資料發現,官方已經提供了刪除鏡像倉庫的API,所以可能相當然的以爲直接使用就好,殊不知掉入了官方埋下的最大的坑點,也是本文要着手解決的核心問題:官方提供的刪除鏡像倉庫中鏡像的接口,僅僅是把manifest刪除了,真正的鏡像文件還存在!官方並沒有提供刪除鏡像層的接口!這也就是說,當我們調用刪除鏡像的接口之後,僅僅是查看鏡像的列表時看不到原鏡像了,然而原有鏡像仍然在磁盤中,佔用着寶貴的文件存儲空間。
  坑點2:直接調用官方的刪除鏡像API,會返回405的錯誤碼
直接調用刪除鏡像的接口,可能會遇到以下錯誤提示:
clipboard.png
405,意味着方法不被允許。實際上,官方可能是處於安全性的考慮,在默認的情況下禁止了直接刪除鏡像的功能。若要開啓刪除鏡像功能,需要修改鏡像倉庫的配置文件。具體操作爲修改/etc/docker/registry/config.yml文件,在storage下添加delete的許可之後,重啓鏡像倉庫服務。
  坑點3:使用官方提供的garbage-collect工具,會有無用的文件殘留
官方爲registry提供了garbage-collect(gc)工具清理鏡像的物理存儲,將沒有引用的layer刪除。
gc的清理過程分爲兩部分:
1)mark:掃描所有的manifest,列出引用的layer;
2)sweep:掃描所有的layer,不在mark裏的layer將被清理刪除。
gc可以在dry-run的模式下運行(添加參數-d),只輸出gc信息,不進行實際操作。我們可以通過這種方式來確認哪些鏡像會被清除。
使用gc工具清理鏡像的一個問題就是文件清理得不夠乾淨,無法清理已經沒有tag的鏡像目錄,並且還殘存少部分文件,從十KB到幾十KB不等。久而久之,垃圾文件和目錄的數量會越來越多。
坑點4:garbage-collect不是事務操作,清理鏡像時可能會產生誤操作
gc不是事務操作,當gc過程中剛好有push操作時,則可能會誤刪數據。一個可行的解決辦法是手動更改鏡像倉庫的配置,暫時禁止鏡像的push操作。
在鏡像倉庫的配置文件中可以配置read-only模式。當啓用read-only之後,再push鏡像時會得到405的錯誤。gc完成後取消read-only模式,再push鏡像即可。
坑點5:使用garbage-collect工具後,必須重啓鏡像倉庫才能正常使用
如果不重啓鏡像倉庫,則再次push該鏡像時可能會得到layer already exists錯誤:
clipboard.png
其可能的原因是鏡像被刪除後,倉庫的緩存中還存有已經刪除的鏡像信息,所以再次push會報層存在的錯誤。
二、兩種清理鏡像倉庫的方案
方案一:使用官方API + GC
使用官方提供的方法可以較爲簡便的清理鏡像倉庫。整個清理過程可能需要幾百毫秒到幾秒的時間。此操作有一定的危險性,因此清理鏡像不宜過於頻繁。官方在git上也有類似描述。點擊查看:https://github.com/docker/doc...
具體操作過程如下:
1、準備工作
在配置中許可刪除操作。修改鏡像倉庫的配置文件,一般在如下路徑:
/etc/docker/registry/config.yml
在storage下添加delete的許可之後,重啓鏡像倉庫。
clipboard.png
用docker方式啓動的鏡像倉庫也可以添加環境變量:
REGISTRY_STORAGE_DELETE_ENABLED=true
2、獲取待刪鏡像的digest
獲取鏡像digest的API爲:
GET /v2/<name>/manifests/<reference>
其中,name是倉庫名,reference是標籤,此時需要注意,調用時需要加上header內容:
Accept: application/vnd.docker.distribution.manifest.v2+json
其中Docker-Content-Digest的值就是鏡像的digest
3、調用官方的HTTP API V2刪除鏡像
刪除鏡像的API爲:
DELETE /v2/<name>/manifests/<reference>
其中,name是倉庫名稱,reference是包含“sha256:”的digest。
4、調用GC清理鏡像文件
使用gc工具的方式爲:
bin/registry garbage-collect /etc/docker/registry/config.yml
gc清理需要時間,如果在gc過程中剛好有push操作,可能會產生未知的問題,建議設置read-only模式之後再進行gc,然後再改回來。
5、重啓docker registry
注意,如果不重啓會導致push相同鏡像時產生layer already exists錯誤。
方案二:使用第三方腳本
在清理鏡像倉庫這件事上,業內已經有很多人進行過各種各樣的嘗試。本文挑選一種比較好的方式推薦使用。
1、宿主機安裝delete-docker-registry-image
可參考此命令的安裝和使用方式。參考鏈接:https://github.com/burnettk/d...
2、執行delete-docker-registry-image命令可以刪除某個倉庫(sb)
clipboard.png
或者某個具體的鏡像(如alpine:3.2)
clipboard.png
如果刪除某鏡像後該倉庫爲空,可以用刪除倉庫的方式刪除此空倉。
clipboard.png
該工具也提供了dry-run的方式,只輸出待刪除的信息不執行刪除操作。在命令後加上——dry-run即可。
3、重啓docker registry
跟gc方式一樣,刪除鏡像之後要重啓docker registry,不然還是會出現相同鏡像push不成功的問題。
以上就是本文推薦的兩種清理鏡像倉庫的兩種方案。第一種方案更多的使用了官方提供的工具,使用時相對更加安全,且無需額外安裝其他內容。第二種方案使用了第三方工具或腳本,使用時更加靈活且簡便,且清理的更加徹底。具體操作時可根據自己的需求選擇方案。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章