docker鏡像倉庫中鏡像的清理,一直是個比較麻煩的事情。尤其是在測試環境當中,每天都會有大量的構建。由此會產生大量的歷史鏡像,而這些鏡像,大多數都沒有用。
在harbor中,清理鏡像,也得分為兩步,第一步是從ui中刪除歷史鏡像。這個時候鏡像並不會被真正刪除,好在harbor集成了鏡像刪除的功能。
廢話不多說,直接給操作。
清理UI中的鏡像
清理ui中的鏡像,如果直接通過圖形界面一個個的點擊刪除的話,在有大規模鏡像需要清理的時候,簡直就是災難,而且這種方式,實在太low。
我這里簡單寫了個腳本,以實現如下功能:
- 遍歷所有project
- 獲取project中所有tag數超過30的repositories
- 獲取這些tag數超過30的repositories的所有tag
- 基於時間排序,保留最新的30個tag
- 刪除其他tag
腳本示例:
#! /usr/bin/env python # -*- coding:utf-8 -*- import requests import json class RequestClient(object): def __init__(self,login_url, username, password): self.username = username self.password = password self.login_url = login_url self.session = requests.Session() self.login() def login(self): self.session.post(self.login_url, params={"principal": self.username, "password": self.password}) class ClearHarbor(object): def __init__(self, harbor_domain, password, schema="https", username="admin"): self.schema = schema self.harbor_domain = harbor_domain self.harbor_url = self.schema + "://" + self.harbor_domain self.login_url = self.harbor_url + "/login" self.api_url = self.harbor_url + "/api" self.pro_url = self.api_url + "/projects" self.repos_url = self.api_url + "/repositories" self.username = username self.password = password self.client = RequestClient(self.login_url, self.username, self.password) def __fetch_pros_obj(self): # TODO self.pros_obj = self.client.session.get(self.pro_url).json() return self.pros_obj def fetch_pros_id(self): self.pros_id = [] # TODO pro_res = self.__fetch_pros_obj() for i in pro_res: self.pros_id.append(i['project_id']) return self.pros_id def fetch_del_repos_name(self, pro_id): self.del_repos_name = [] repos_res = self.client.session.get(self.repos_url, params={"project_id": pro_id}) # TODO for repo in repos_res.json(): if repo["tags_count"] > 30: self.del_repos_name.append(repo['name']) return self.del_repos_name def fetch_del_repos(self, repo_name): self.del_res = [] tag_url = self.repos_url + "/" + repo_name + "/tags" # TODO tags = self.client.session.get(tag_url).json() tags_sort = sorted(tags, key=lambda a: a["created"]) #print(tags_sort) del_tags = tags_sort[0:len(tags_sort) -30] #print(del_tags) for tag in del_tags: del_repo_tag_url = tag_url + "/" + tag['name'] print(del_repo_tag_url) del_res = self.client.session.delete(del_repo_tag_url) self.del_res.append(del_res) return self.del_res if __name__ == "__main__": harbor_domain = "hub.test.com" password = "xxxxxxx" res = ClearHarbor(harbor_domain,password) # 循環所有的project id for i in res.fetch_pros_id(): # 獲取所有tag超過30的repos repos = res.fetch_del_repos_name(i) if repos: print(repos) for repo in repos: del_repos = res.fetch_del_repos(repo) print(del_repos)
清理鏡像釋放空間
依舊為286m,到是什么原因呢,通過官方github查看使用文檔,終於找到了解決辦法,那就是在webui刪除鏡像是軟刪除,並不會釋放空間,在
webui界面刪除后必須停止harbor后再進行硬刪除,也就是空間釋放,垃圾回收,下面是官方文檔原文
Deleting repositories
Repository deletion runs in two steps.
First, delete a repository in Harbor's UI. This is soft deletion. You can delete the entire repository or just a tag of it. After the soft deletion, the repository is no longer managed in Harbor, however, the files of the repository still remain in Harbor's storage.
CAUTION: If both tag A and tag B refer to the same image, after deleting tag A, B will also get deleted. if you enabled content trust, you need to use notary command line tool to delete the tag's signature before you delete an image.
Next, delete the actual files of the repository using the registry's garbage collection(GC). Make sure that no one is pushing images or Harbor is not running at all before you perform a GC. If someone were pushing an image while GC is running, there is a risk that the image's layers will be mistakenly deleted which results in a corrupted image. So before running GC, a preferred approach is to stop Harbor first.
Run the below commands on the host which Harbor is deployed on to preview what files/images will be affected:
$ docker-compose stop
$ docker run -it --name gc --rm --volumes-from registry vmware/registry:2.6.2-photon garbage-collect --dry-run /etc/registry/config.yml
NOTE: The above option "--dry-run" will print the progress without removing any data.
Verify the result of the above test, then use the below commands to perform garbage collection and restart Harbor.
$ docker run -it --name gc --rm --volumes-from registry vmware/registry:2.6.2-photon garbage-collect /etc/registry/config.yml
$ docker-compose start
For more information about GC, please see GC.
官方已經說的很明白了,第一個run是只打印出來已刪除鏡像,但不進行空間釋放和垃圾回收,執行下面的一個run,成功釋放空間了。
執行垃圾回收命令 docker run -it --name gc --rm --volumes-from registry vmware/registry:2.6.2-photon garbage-collect /etc/registry/config.yml 自行參照鏡像名稱修改
釋放過程截圖
啟動harbor
查看空間是否釋放
我們的空間回來了
再上傳一次試試?
證明沒問題,可以上傳。
也可以下載
至此,倉庫空間釋放,垃圾回收告一段落
附上官方文檔地址
https://github.com/vmware/harbor/blob/master/docs/user_guide.md