Harbor v2.0 镜像回收那些事

Stella981
• 阅读 626

Harbor 镜像回收流程

Harbor 镜像回收分两部分:

  • 1、删除镜像 TAG

  • 2、执行垃圾清理

早期 Harbor 1.0 版本时,删除镜像TAG可以通过UI界面手动一个个选取删除,也可以调用官方提供的SDK删除(很早以前官方不维护了)。后来官方在 1.9 版本提供TAG保留策略,解决以前镜像Tag回收麻烦的问题。

TAG保留策略有哪些策略,如下图:

Harbor v2.0 镜像回收那些事

Harbor v2.0 镜像回收那些事

Harbor Python SDK

作者写了一个 Python SDK 方法,锦上添花吧!

代码项目地址https://github.com/yangpeng14/harbor\_sdk\_v2.0

注意:Harbor v2.0+ 和 Harbor v1 版本 API调用方式发生很大的改变。安全方面:修复跨域攻击问题,API登陆Harbor方法也发现变化。

#!/usr/bin/env python3# -*- coding=utf8 -*-import loggingimport requestslogging.basicConfig(level=logging.INFO)class HarborClient(object):    def __init__(self, host, user, password, protocol="http"):        self.host = host        self.user = user        self.password = password        self.protocol = protocol        # 第一次get请求,获取 cookie 信息        self.cookies, self.headers = self.get_cookie()        # 获取登陆成功 session        self.session_id = self.login()        # 把登陆成功的 sid值 替换 get_cookie 方法中 cookie sid值,用于 delete 操作        self.cookies_new = self.cookies        self.cookies_new.update({'sid': self.session_id})    # def __del__(self):    #     self.logout()    def get_cookie(self):        response = requests.get("{0}://{1}/c/login".format(self.protocol, self.host))        csrf_cookie = response.cookies.get_dict()        headers = {'X-Harbor-CSRF-Token': csrf_cookie['__csrf']}        return csrf_cookie, headers    def login(self):        login_data = requests.post('%s://%s/c/login' %                                   (self.protocol, self.host),                                   data={'principal': self.user,                                         'password': self.password}, cookies=self.cookies, headers=self.headers)        if login_data.status_code == 200:            session_id = login_data.cookies.get('sid')            logging.debug("Successfully login, session id: {}".format(                session_id))            return session_id        else:            logging.error("Fail to login, please try again")            return None    def logout(self):        requests.get('%s://%s/c/logout' % (self.protocol, self.host),                     cookies={'sid': self.session_id})        logging.debug("Successfully logout")    # GET /projects    def get_projects(self, project_name=None, is_public=None):        # TODO: support parameter        result = []        page = 1        page_size = 15        while True:            path = '%s://%s/api/v2.0/projects?page=%s&page_size=%s' % (self.protocol, self.host, page, page_size)            response = requests.get(path,                                    cookies={'sid': self.session_id})            if response.status_code == 200:                logging.debug("Successfully get projects result: {}".format(                    result))                if isinstance(response.json(), list):                    result.extend(response.json())                    page += 1                else:                    break            else:                logging.error("Fail to get projects result")                result = None                break        return result    # GET /projects/{project_name}/repositories    def get_repositories(self, project_name, query_string=None):        # TODO: support parameter        result = []        page = 1        page_size = 15        while True:            path = '%s://%s/api/v2.0/projects/%s/repositories?page=%s&page_size=%s' % (                self.protocol, self.host, project_name, page, page_size)            response = requests.get(path,                                    cookies={'sid': self.session_id})            if response.status_code == 200:                logging.debug(                    "Successfully get repositories with name: {}, result: {}".format(                        project_name, result))                if len(response.json()):                    result.extend(response.json())                    page += 1                else:                    break            else:                logging.error("Fail to get repositories result with name: {}".format(                    project_name))                result = None                break        return result    # GET /projects/{project_name}/repositories/{repository_name}/artifacts    # GET /projects/{project_name}/repositories/{repository_name}/artifacts?with_tag=true&with_scan_overview=true&with_label=true&page_size=15&page=1    def get_repository_artifacts(self, project_name, repository_name):        result = []        page = 1        page_size = 15        while True:            path = '%s://%s/api/v2.0/projects/%s/repositories/%s/artifacts?with_tag=true&with_scan_overview=true&with_label=true&page_size=%s&page=%s' % (                self.protocol, self.host, project_name, repository_name, page_size, page)            response = requests.get(path,                                    cookies={'sid': self.session_id}, timeout=60)            if response.status_code == 200:                logging.debug(                    "Successfully get repositories artifacts with name: {}, {}, result: {}".format(                        project_name, repository_name, result))                if len(response.json()):                    result.extend(response.json())                    page += 1                else:                    break            else:                logging.error("Fail to get repositories artifacts result with name: {}, {}".format(                    project_name, repository_name))                result = None                break        return result    # DELETE /projects/{project_name}/repositories/{repository_name}    def delete_repository(self, project_name, repository_name, tag=None):        # TODO: support to check tag        # TODO: return 200 but the repo is not deleted, need more test        result = False        path = '%s://%s/api/v2.0/projects/%s/repositories/%s' % (            self.protocol, self.host, project_name, repository_name)        response = requests.delete(path,                                   cookies=self.cookies_new, headers=self.headers)        if response.status_code == 200:            result = True            print("Delete {} successful!".format(repository_name))            logging.debug("Successfully delete repository: {}".format(                repository_name))        else:            logging.error("Fail to delete repository: {}".format(repository_name))        return result    # Get /projects/{project_name}/repositories/{repository_name}/artifacts/{reference}/tags    def get_repository_tags(self, project_name, repository_name, reference_hash):        result = None        path = '%s://%s/api/v2.0/projects/%s/repositories/%s/artifacts/%s/tags' % (            self.protocol, self.host, project_name, repository_name, reference_hash)        response = requests.get(path,                                cookies={'sid': self.session_id}, timeout=60)        if response.status_code == 200:            result = response.json()            logging.debug(                "Successfully get tag with repository name: {}, result: {}".format(                    repository_name, result))        else:            logging.error("Fail to get tags with repository name: {}".format(                repository_name))        return result    # Del /projects/{project_name}/repositories/{repository_name}/artifacts/{reference}/tags/{tag_name}    def del_repository_tag(self, project_name, repository_name, reference_hash, tag):        result = False        path = '%s://%s/api/v2.0/projects/%s/repositories/%s/artifacts/%s/tags/%s' % (            self.protocol, self.host, project_name, repository_name, reference_hash, tag)        response = requests.delete(path, cookies=self.cookies_new, headers=self.headers)        if response.status_code == 200:            result = True            print("Delete {} {} {} {} successful!".format(project_name, repository_name, reference_hash, tag))            logging.debug(                "Successfully delete repository project_name: {}, repository_name: {}, reference_hash: {}, tag: {}".format(                    project_name, repository_name, reference_hash, tag))        else:            logging.error("Fail to delete repository project_name: {}, repository_name: {}, reference_hash: {}, tag: {}".format(                project_name, repository_name, reference_hash, tag))        return result    # Del /projects/{project_name}/repositories/{repository_name}/artifacts/{reference}    def del_artifacts_hash(self, project_name, repository_name, reference_hash):        result = False        path = '%s://%s/api/v2.0/projects/%s/repositories/%s/artifacts/%s' % (            self.protocol, self.host, project_name, repository_name, reference_hash)        response = requests.delete(path, cookies=self.cookies_new, headers=self.headers)        if response.status_code == 200:            result = True            print("Delete artifacts hash {} {} {} successful!".format(project_name, repository_name, reference_hash))            logging.debug(                "Successfully delete repository project_name: {}, repository_name: {}, artifacts hash: {}".format(                    project_name, repository_name, reference_hash))        else:            logging.error("Fail to delete repository project_name: {}, repository_name: {}, artifacts hash: {}".format(                project_name, repository_name, reference_hash))        return result

使用举例

列出 Harbor Projects

import harborclient_modify_v2_0class GetHarborApi(object):    def __init__(self, host, user, password, protocol="http"):        self.host = host        self.user = user        self.password = password        self.protocol = protocol        self.client = harborclient_modify_v2_0.HarborClient(self.host, self.user, self.password, self.protocol)    def main(self):        print(self.client.get_projects())if __name__ == '__main__':    host = "harbor.example.com"    user = "admin"    password = "******"    protocol = "https"    cline_get = GetHarborApi(host, user, password, protocol)    cline_get.main()

热门文章推荐

最后

  • 欢迎您加我微信【 ypxiaozhan01】,拉您进技术群,一起交流学习...

  • 欢迎您关注【 YP小站】,学习互联网最流行的技术,做个专业的技术人...

Harbor v2.0 镜像回收那些事


【文章让您有收获,👇 或者 在看 支持我吧】

本文分享自微信公众号 - YP小站(ypxiaozhan)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
西蒙 西蒙
3年前
docker入门基本命令
docker基础命令dockerimages查看镜像列表dockerpsa查看所有docker容器,a指的是所有包括以关闭的容器dockerrm655e69删除容器,655e69指的是容器Iddockerrminginx:latest删除镜像,:latest为制定版本dockerpullngin
维格云回收舱
在「回收舱」中,你可以:1.查看空间站中被删除的且当前成员拥有「可管理」权限的文件。2.找到已被删除的文件,恢复文件。维格云回收舱操作说明还原文件成员拥有文件的「可管理」权限时,文件被删除后可在回收舱中找回并恢复至工作目录顶部。空间站等级不同,文件保留时长不同。●青铜级:14天●白银级:3个月●企业级:12个月维格云回收舱注意事项文件权限保留
Stella981 Stella981
2年前
Gitlab+Jenkins+K8s集群+Kuboard+Harbor实现自动化CICD
本次通过GitlabJenkinsK8s集群KuboardHarbor实现自动化CICD,当容器镜像推送到Harbor镜像库中之后,自动触发dockerpull更新Kubernetes环境中的容器镜像。实验拓扑图:!1.png(https://s2.51cto.com/images/20201004/16018188
Stella981 Stella981
2年前
Docker常用命令,Docker安装Nginx、Redis、Jenkins、tomcat、MySQL
常用命令拉取镜像:dockerpullxxx启动镜像:dockerrunnamexxx8080:8080dxxx查看容器:dockerpsxxx停止容器:dockerstopxxx启动容器:dockerstartxxx删除容器:dockerrmxxx删除镜像:docke
Stella981 Stella981
2年前
Harbor部署私有镜像仓库
部署私有仓库下载harbor2.1.0安装包下载离线安装包:$wgethttps://github.com/goharbor/harbor/releases/download/v2.1.0rc2/harborofflineinstallerv2.1.0rc2.tgz解压!修改
Stella981 Stella981
2年前
Dockerfile 说明
1.基本说明  Dockfile是一个用于编写docker镜像生成过程的文件,其有特定的语法。在一个文件夹中,如果有一个名字为Dockfile的文件,其内容满足语法要求,在这个文件夹路径下执行命令:dockerbuildtagname:tag.,就可以按照描述构建一个镜像了。name是镜像的名称,tag是镜像的版本或者是标签号,
Stella981 Stella981
2年前
Android SDK更新及安装
这篇文章主要介绍了Android在线更新SDK的方法,分别介绍了修改hosts文件使用谷歌官方镜像更新及使用国内镜像更新SDK的方法,非常简单实用,需要的朋友可以参考下本文讲述了Android使用国内镜像在线更新SDK的方法。分享给大家供大家参考,具体如下:什么是AndroidSDK:SDK:(softwaredevelopment
Stella981 Stella981
2年前
Docker删除全部镜像和容器
杀死所有正在运行的容器dockerkill$(dockerpsaq)删除所有已经停止的容器dockerrm$(dockerpsaq)删除所有未打dangling标签的镜像dockerrmi$(dockerimagesqfda
Stella981 Stella981
2年前
Dockerfile指令:
Dockerfile指令:第一行注释,指令是大写字母开头,FROM指令:FROM<image,后面跟镜像名,FROM<image:<tag,后面跟镜像名和标签名,必须是已经存在的镜像,后续指令都是基于这个镜像来执行的,这个镜像也叫基础镜像,必须是第一条非注释指令,FROMubuntu:14.0
Stella981 Stella981
2年前
JVM调优总结(三)
可以从不同的的角度去划分垃圾回收算法:按照基本回收策略分引用计数(ReferenceCounting):比较古老的回收算法。原理是此对象有一个引用,即增加一个计数,删除一个引用则减少一个计数。垃圾回收时,只用收集计数为0的对象。此算法最致命的是无法处理循环引用的问题。标记清除(MarkSweep):