shell中获取Harbor中所有的镜像列表

我们要查询Harbor中某个项目下某个镜像是否存在,需要登录Harbor UI管理界面,然后进入到项目(Project),再到搜索框输入镜像的名称来查找镜像在不在。

那么,如果只知道镜像的名称,不知道镜像在哪个项目(Project)呢?你是每个项目下都去搜索么?

那么!有什么方法可以简化这些操作呢?即:

不需要登录Harbor就可以看到Harbor里面所有的镜像;
仅提供镜像名称就可以看到镜像在哪个项目;
仅知道镜像名称就可以判断Harbor镜像仓库中是否存在这个镜像,从而判断上传的镜像是否上传成功。
我在工作中常遇到开发的同事的问题:

我上传一个镜像,帮忙看上传成功没?
我刚发布一个服务,构建的时候报错一直找不到镜像,这是什么原因?
我之前上传好几个版本的镜像,怎么知道都有哪些?


解决方案
刚才描述了我在维护Harbor中遇到的一些业务问题,那有什么方法来优化这些问题呢?来减轻我的维护难度。

Harbor提供了良好的API支持,我何不利用这一点,通过调用API来获取Harbor中所有项目下(Project)所有的镜像,以及该镜像下所有的版本,生成一个镜像清单,再将该清单放到一个文件中,查看的时候仅需要grep命令过滤下就根据镜像名称来查到我想要的信息呢?

具体实现
因为Harbor有两个版本的API,即1.0版本和2.0版本,不同的API调用方法存在一定的区别。

本处我就以shell脚本的方式来实现,Python和Go版本的可自行参考。

1版本APIshell脚本实现
适用于Harbor v2.0以下的版本。1)编写shell脚本
[root@Harbor_backup]# vim  Harbor-image-list-100.sh 

#!/bin/bash

#镜像清单文件,将获取到的镜像信息存到该文件中
File=harbor-images-`date '+%Y-%m-%d'`.txt

## 定义Harbor连接地址,这里需要改为你们自己的Harbor地址
Address=http://192.168.2.250:443

## 定义连接Harbor的用户名和密码(因为是获取全部的镜像,只有admin用户才有该权限)
Hamin=admin:Harbor12345

## 获取Harbor中有哪些项目(Project)
Project_List=$(curl -u "$Hamin"  -X GET  $Address/api/projects  -H "Content-Type: application/json"   | grep name | awk '/"name": /' | awk -F '"' '{print $4}')

for Project in $Project_List;do
  # 循环获取每个项目下所有的镜像
 Image_Names=$(curl -u "$Hamin"  -X GET $Address/api/search?q=$Project -H "Content-Type: application/json" | grep "repository_name" | awk -F "\"" '{print $4}')
    for Image in $Image_Names;do
    # 循环获取每个镜像所有的标签(版本)
    Image_Tags=$(curl -u "$Hamin"  -X GET  $Address/api/repositories/$Image/tags -H "Content-Type: application/json" | awk '/"name": /' | awk -F '"' '{print $4}')
        for Tag in $Image_Tags;do
        # 将获取到的镜像完整路径存档到镜像清单文件
        echo "$Address/$Image:$Tag" | grep -v Base | grep -v Image | grep -v CentOS >>  $File
        done
    done
done
 


2)执行脚本
[root@harbor-conso  ~]# chmod +x   Harbor-image-listk-100.sh 
[root@harbor-conso  ~]# sh  Harbor-image-list-100.sh
...
先让子弹飞会儿,等一哈哈!
 


3)清单文件查看镜像
[root@harbor-conso  ~]# cat harbor-images-2022-04-18.txt c| tail  -10
http://192.168.2.250:443/lihonggang-25655/eeeee:rrrrr-20211207201732
http://192.168.2.250:443/lihonggang-25655/wwww:aaaa-20211207202110
http://192.168.2.250:443/lihonggang-25655/wwww:aaaa-20211207202855
http://192.168.2.250:443/gx-eop-es-30254/gx-eop-es:meng-v1.0.5-20220414154335
http://192.168.2.250:443/gx-eop-es-30254/gx-eop-es:meng-v1.0.5
http://192.168.2.250:443/gx-eop-es-30254/gx-eop-es:meng-v1.0.3-20220412182511
http://192.168.2.250:443/gx-eop-es-30254/gx-eop-es:meng-v1.0.3
http://192.168.2.250:443/gx-eop-es-30254/gx-eop-es:meng-v1.0.3-20220407184829
http://192.168.2.250:443/gx-eop-es-30254/gx-eop-es:meng-v1.0.5-20220412183221
http://192.168.2.250:443/wxgtest-25688/app-wxgtest:v1.0-wxg-20211207193353
 


API v2版本的Shell脚本实现
在shell脚本中通过调用Harbor API获取Harbor中所有项目下的所有镜像,然后导出到文本中。

    本脚本按API V2版本的调用方式编写(2.0版本以下不适用),可通过以下命令查看你使用的Harbor API版本。[root@harbor-conso  ~]# curl https://192.168.2.250:443/api/version  -k
{"version":"v2.0"}
1.
2.
编写脚本
[root@harbor-conso  ~]#  Harbor-image-listk-v2.sh

#!/bin/bash
Harbor_Address=192.168.2.250:443       #Harbor主机地址
Harbor_User=admin                      #登录Harbor的用户
Harbor_Passwd=Harbor12345              #登录Harbor的用户密码
Images_File=harbor-images-`date '+%Y-%m-%d'`.txt   # 镜像清单文件                     #镜像清单文件
Tar_File=/backup/Harbor-backup/                                         #镜像tar包存放路径
set -x
# 获取Harbor中所有的项目(Projects)
Project_List=$(curl -u admin:Harbor12345  -H "Content-Type: application/json" -X GET  https://192.168.2.250:443/api/v2.0/projects  -k  | python -m json.tool | grep name | awk '/"name": /' | awk -F '"' '{print $4}')

for Project in $Project_List;do
   # 循环获取项目下所有的镜像
    Image_Names=$(curl -u admin:Harbor12345 -H "Content-Type: application/json" -X GET https://192.168.2.250:443/api/v2.0/projects/$Project/repositories -k | python -m json.tool | grep name | awk '/"name": /' | awk -F '"' '{print $4}')
    for Image in $Image_Names;do
        # 循环获取镜像的版本(tag)
        Image_Tags=$(curl -u admin:Harbor12345  -H "Content-Type: application/json"   -X GET  https://192.168.2.250:443/v2/$Image/tags/list  -k |  awk -F '"'  '{print $8,$10,$12}')
        for Tag in $Image_Tags;do
            # 格式化输出镜像信息
            echo "$Harbor_Address/$Image:$Tag"   >> harbor-images-`date '+%Y-%m-%d'`.txt
        done
    done
done
 


执行脚本
[root@harbor-conso  ~]# chmod  +x  Harbor-image-listk-v2.sh
[root@harbor-conso  ~]# sh  Harbor-image-listk-v2.sh
1.
2.


从镜像清单查找镜像
然后打开脚本所在目录的harbor-images-`date '+%Y-%m-%d'`.txt文件即可看到镜像清单了。

复制 
[root@harbor-conso  ~]# cat harbor-images-2022-04-18.txt c| tail  -10
http://192.168.2.250:443/lihonggang-25655/eeeee:rrrrr-20211207201732
http://192.168.2.250:443/lihonggang-25655/wwww:aaaa-20211207202110
http://192.168.2.250:443/lihonggang-25655/wwww:aaaa-20211207202855
http://192.168.2.250:443/gx-eop-es-30254/gx-eop-es:meng-v1.0.5-20220414154335
http://192.168.2.250:443/gx-eop-es-30254/gx-eop-es:meng-v1.0.5
http://192.168.2.250:443/gx-eop-es-30254/gx-eop-es:meng-v1.0.3-20220412182511
http://192.168.2.250:443/gx-eop-es-30254/gx-eop-es:meng-v1.0.3
http://192.168.2.250:443/gx-eop-es-30254/gx-eop-es:meng-v1.0.3-20220407184829
http://192.168.2.250:443/gx-eop-es-30254/gx-eop-es:meng-v1.0.5-20220412183221
http://192.168.2.250:443/wxgtest-25688/app-wxgtest:v1.0-wxg-20211207193353
-----------------------------------
©著作权归作者所有:来自51CTO博客作者键客李大白的原创作品,请联系作者获取转载授权,否则将追究法律责任
shell中获取Harbor中所有的镜像列表(超实用,建议收藏)
https://blog.51cto.com/lidabai/5217350

Harbor2.0 API 镜像仓库清理脚本--python

harbor_clearimage.py
# -*- coding:utf-8 -*-
import requests
from requests.auth import HTTPBasicAuth
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry
import os
import time
import logging
from logging.handlers import RotatingFileHandler
 
class Harbor(object):
def __init__(self, api_url, api_user, api_passwd, tag_num, proj_exclude):
self.api_url = api_url
self.api_user = api_user
self.api_passwd = api_passwd
self.api_auth = HTTPBasicAuth(self.api_user, self.api_passwd)
self.tag_num = int(tag_num)
self.proj_exclude = proj_exclude
self.proj_url = self.api_url + "/projects"
self.repos_url = self.api_url + "/repositories"
self.header_dict = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36',
'Content-Type': 'application/x-www-form-urlencoded'
}
self.deldata = []
self.session = requests.Session()
self.session.auth = self.api_auth
retry = Retry(connect=3, backoff_factor=1)
adapter = HTTPAdapter(max_retries=retry)
self.session.mount('http://', adapter)
self.session.keep_alive = False
 
def soft_del_repos(self):
try:
projresp = self.session.get(self.proj_url, headers=self.header_dict)
if projresp.status_code == 200:
projdata = projresp.json()
for proj in projdata:
if proj['name'] not in self.proj_exclude # and proj['name'] == "gxjxhwebtest-28003" :
try:
reporesp = self.session.get(self.repos_url, params={"project_id": proj['project_id']} , headers=self.header_dict)
if reporesp.status_code == 200:
repodata = reporesp.json()
for repo in repodata:
if repo["tags_count"] > self.tag_num:
tag_url = self.repos_url + "/" + repo['name'] + "/tags"
tags = self.session.get(tag_url).json()
tagdata = sorted(tags, key=lambda a: a["created"])
del_tags = tagdata[0:len(tagdata) - self.tag_num]
for tag in del_tags:
del_repo_tag_url = tag_url + "/" + tag['name']
cmd = 'curl -v -X DELETE -u "' + self.api_user + ":" + self.api_passwd + '" -H "accept: application/json" ' + del_repo_tag_url
try:
#del_resp = self.session.delete(del_repo_tag_url,headers=self.header_dict)
ok = os.system(cmd)
if ok == 0 :
logging.info("httpdel:" + del_repo_tag_url )
_deldata = {"project_id":proj['project_id'],"project_name":proj['name'],"repo_name":repo['name'],"tag_name":tag['name']}
self.deldata.append(_deldata)
logging.info("httpdel project_id=" + str(proj['project_id']) + ",project_name=" + proj['name'] + ",repo_name=" + repo['name'] + ",tag_name=" + tag['name'])
else:
logging.error("exec_cmd fail:" + cmd )
except:
logging.error("exec_cmd fail:" + cmd )
except:
logging.error("httpget fail:" + self.repos_url)
else:
logging.error("httpget fail:" + self.proj_url )
except:
logging.error("apilogin fail:" + self.api_url )
return self.deldata
 
def hard_del_repo(self):
pwd_cmd = "cd /dcos/app/harbor/ " #进入到Harbor安装目录
stop_cmd = "docker-compose stop" #停止Harbor服务
del_cmd = "docker run -it --name gc --rm --volumes-from registry goharbor/registry-photon:v2.7.1-patch-2819-v1.8.6 garbage-collect /etc/registryctl/config.yml"
start_cmd = "docker-compose start" #启动Harbor服务
os.system(pwd_cmd)
ok1 = os.system(stop_cmd)
if ok1 == 0 :
time.sleep(10)
ok2 = os.system(del_cmd)
ok3 = os.system(start_cmd)
if ok3 == 0 :
logging.info("hard_del_repo ok:")
else:
logging.error("hard_del_repo fail:")
 
if __name__ == "__main__":
Rthandler = RotatingFileHandler('harbor_repo_clear.log', maxBytes=10*1024*1024,backupCount=5)
logging.basicConfig(level=logging.INFO)
formatter = logging.Formatter('%(levelname)s %(asctime)s %(process)d %(thread)d %(pathname)s %(filename)s %(funcName)s[line:%(lineno)d] %(message)s')
Rthandler.setFormatter(formatter)
logging.getLogger('').addHandler(Rthandler)
 
api_url = "http://192.168,2,66:443/api" #Harbor服务的API URL
api_user = "admin" #超级管理员
api_passwd = "Harbor12345" #超级管理员的用户密码
tag_num = 20 #保留的tag数量
proj_exclude = ["library"]
harborClient = Harbor(api_url,api_user,api_passwd,tag_num,proj_exclude)
data = harborClient.soft_del_repos()
if len(data) > 0 :
#harborClient.hard_del_repos()
logging.info("hard_del_repo:")

执行Python脚本

python harbor_clearimage.py

Harbor2.0 API 镜像仓库清理脚本--shell

执行前须安装jq(json解析工具)

wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
yum install jq -y

shell脚本如下,需要放置harbor机器执行:

#!/bin/bash
set -e
HARBOR_URL=xxxx.xxxx.xxxx
HARBOR_USER=user
HARBOR_PASSWD=password
#最大保留镜像个数。超过后的删除。
OLD_VERSION_NUM=20

#获取仓库项目列表
function get_projects_list(){
  projects_list=$(curl -s -k -u ${HARBOR_USER}:${HARBOR_PASSWD} "https://${HARBOR_URL}/api/v2.0/projects?page=1&page_size=100")
  mkdir -p $PWD/projectsList
  echo "${projects_list}" | jq '.[]' | jq -r '.name' > $PWD/projectsList/projectsList.txt
}

#获取每个项目下仓库列表
function get_repos_list(){
  mkdir -p $PWD/reposList
  for project in $(cat $PWD/projectsList/projectsList.txt);do
    repos_list=$(curl -s -k -u ${HARBOR_USER}:${HARBOR_PASSWD} "https://${HARBOR_URL}/api/v2.0/projects/${project}/repositories?page=1&page_size=100")
    echo "${repos_list}" | jq '.[]' | jq -r '.name'| awk -F "/" '{print $2}' > $PWD/reposList/${project}.txt
  done
}

#获取每个仓库下镜像digest列表
function get_tag_list(){

  for project in $(cat $PWD/projectsList/projectsList.txt)
  do
    for repo in `cat $PWD/reposList/${project}.txt`
      do
        mkdir -p $PWD/tagsList/$project/$repo
        curl -s -k -u ${HARBOR_USER}:${HARBOR_PASSWD} "https://${HARBOR_URL}/api/v2.0/projects/${project}/repositories/${repo}/artifacts?page=1&page_size=100&with_tag=true&wi
th_label=false&with_scan_overview=false&with_signature=false&with_immutable_status=false" | jq '.[]' | jq -r '.digest' > $PWD/tagsList/$project/$repo/tags.txt
     done
  done
}

#遍历每个项目下每个仓库执行镜像删除
function delete_images(){
  for project in $(cat $PWD/projectsList/projectsList.txt)
  do
    for repo in `cat $PWD/reposList/${project}.txt`
      do
        TOTAL_NUN=`cat $PWD/tagsList/$project/$repo/tags.txt |wc -l `
        if [ $TOTAL_NUN -gt $OLD_VERSION_NUM ];then
            DELETE_NUN=`echo $TOTAL_NUN - $OLD_VERSION_NUM | bc `
            tail -n  $DELETE_NUN $PWD/tagsList/$project/$repo/tags.txt > $PWD/tagsList/$project/$repo/tags-deleted.txt
            echo "################## ${project}/${repo} have $DELETE_NUN images need to delete ###############################################"
            echo "#######################begine delete ${project}/${repo} images###################################"
            for i in `cat $PWD/tagsList/$project/$repo/tags-deleted.txt`
              do
                IMAGE_NAME=`curl -s -k -u ${HARBOR_USER}:${HARBOR_PASSWD} "https://${HARBOR_URL}/api/v2.0/projects/${project}/repositories/${repo}/artifacts/${i}?page=1&page_
size=10&with_tag=true&with_label=false&with_scan_overview=false&with_signature=false&with_immutable_status=false" | jq -r '.tags' | jq -r '.[]' | jq -r '.name'`
                echo "######################### delete image $HARBOR_URL/$project/$repo:$IMAGE_NAME #################"
                curl -X 'DELETE' -u ${HARBOR_USER}:${HARBOR_PASSWD} "https://${HARBOR_URL}/api/v2.0/projects/${project}/repositories/${repo}/artifacts/${i}"
                echo "######################## delete image $HARBOR_URL/$project/$repo:$IMAGE_NAME success #########"
             done
             echo "####################### ${project}/${repo} images have deleted success###################################"
             echo "*********************************************************************************************************"
          fi
     done
  done

}

#启动容器,执行harbor gc 回收
function clean_registry(){
#  image_name=$(docker ps | grep registry | grep photon | awk -F " " '{print $2}')
#  docker run -it --name gc --rm --volumes-from registry ${image_name} garbage-collect  /etc/registry/config.yml
   docker run -it --name gc --rm --volumes-from registry vmware/registry:2.6.2-photon garbage-collect  /etc/registry/config.yml

}

function entrance(){
 get_projects_list
 get_repos_list
 get_tag_list
 delete_images
 clean_registry
}

entrance

定时清理添加定时任务:

crontab -e
00 3 * * * /opt/docker-clean/harbor-clean.sh > /opt/docker-clean/harbor-clean.log 2>&1
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值