Harbor磁盘空间清理指南:如何安全清理半年前的镜像

1 背景:为何需要定期清理Harbor镜像

在多项目开发环境中,随着持续集成/持续部署(CI/CD)流程的不断运行,Jenkins等工具会频繁地向Harbor镜像仓库推送新构建的镜像。久而久之,仓库中会积累大量历史镜像版本,导致虚拟机磁盘空间迅速耗尽。这些"僵尸镜像"不仅占用宝贵的存储资源,还可能增加安全风险和管理复杂度。

根据实践经验,一个中等规模的开发团队每周可能产生数十甚至上百个新镜像。如果没有有效的清理策略,Harbor存储占用呈指数级增长只是时间问题。更糟糕的是,单纯删除镜像并不立即释放物理空间------这是许多管理员常遇到的误区。

本文将详细介绍两种有效清理半年前镜像的方法:Harbor原生保留策略API脚本清理方案,并解释最终释放磁盘空间的关键步骤。

2 清理原理:Harbor的两级删除机制

Harbor采用两级删除机制,理解这一点对有效管理存储空间至关重要:

  1. 软删除(标记删除) :当我们通过界面或API删除镜像标签时,Harbor只是移除了镜像的元数据引用,并未真正删除底层的物理文件(blobs)。这就是为什么删除镜像后磁盘空间似乎没有变化。
  2. 硬删除(物理删除) :需要通过垃圾回收(Garbage Collection, GC) 过程来实现。GC会清理那些不再被任何镜像引用的底层数据块,从而真正释放磁盘空间。

官方推荐

UI配置

高度定制化

API操作

关键步骤:垃圾回收 GC

安排维护窗口

GC期间仓库只读

执行垃圾回收命令

真正释放物理磁盘空间

方案二:通过 Harbor API 编写脚本

认证获取 Token

筛选创建时间早于半年的标签

调用 API 删除旧标签

方案一:通过 Harbor UI 配置保留策略

创建保留规则

设置保留最近180天镜像

设置定时执行或手动运行

Harbor 磁盘空间不足

选择清理方式

磁盘空间得到释放

3 方法一:使用Harbor原生保留策略(推荐UI操作)

Harbor自v2.4版本起提供了强大的**保留策略(Retention Policy)**功能,这是清理旧镜像的最简便方法。

3.1 配置步骤

  1. 登录Harbor控制台 ,进入需要清理的项目
  2. 点击"策略"选项卡 -> "添加规则"
  3. 配置保留规则:
    • 规则名称:例如"清理半年前镜像"
    • 匹配仓库 :可使用**匹配所有仓库,或指定特定仓库
    • 保留策略 :选择"保留最近多少天被推送过的",设置天数为180天(约半年)
    • 标签过滤 :可根据需要设置标签匹配模式(如release-*
    • 删除未打标签的镜像:建议启用,以清理无标签的中间层镜像
  4. 设置执行频率(如每周一次)
  5. 点击"模拟运行"预览将被清理的镜像
  6. 确认无误后"立即执行"

3.2 优势与注意事项

  • 优势:官方支持、配置简单、可定时自动运行、提供模拟运行功能降低风险
  • 注意事项
    • 保留策略基于"保留最近推送的镜像"逻辑,而非直接按时间点删除
    • 需要Harbor v2.4+版本支持
    • 执行后仍需运行垃圾回收才能释放物理空间

4 方法二:使用API脚本精确删除

对于需要更复杂清理逻辑或使用旧版Harbor的情况,可通过API脚本实现精确控制。

4.1 Python脚本示例

以下Python脚本示例演示了如何删除指定项目中所有早于半年的镜像标签:

复制代码
import requests
from datetime import datetime, timedelta

# Harbor配置
HARBOR_URL = 'https://your-harbor.com'
USERNAME = 'admin'
PASSWORD = 'your-password'
PROJECT_NAME = 'your-project'

# 计算半年前时间点
six_months_ago = datetime.now() - timedelta(days=180)

# 获取认证token
def get_token():
    login_url = f'{HARBOR_URL}/c/login'
    resp = requests.post(login_url, json={
        'principal': USERNAME, 
        'password': PASSWORD
    }, verify=False)
    return resp.headers.get('Authorization')

# 获取项目中的所有仓库
def get_repositories(project):
    headers = {'Authorization': get_token()}
    repos_url = f'{HARBOR_URL}/api/v2.0/projects/{project}/repositories'
    resp = requests.get(repos_url, headers=headers, verify=False)
    return [repo['name'] for repo in resp.json()]

# 获取仓库的所有标签及其创建时间
def get_tags(repository):
    headers = {'Authorization': get_token()}
    tags_url = f'{HARBOR_URL}/api/v2.0/{repository}/tags'
    resp = requests.get(tags_url, headers=headers, verify=False)
    return [(tag['name'], datetime.strptime(tag['push_time'], '%Y-%m-%dT%H:%M:%S.%fZ')) 
            for tag in resp.json()]

# 删除早于指定时间的标签
def delete_old_tags():
    for repo in get_repositories(PROJECT_NAME):
        tags = get_tags(repo)
        for tag_name, push_time in tags:
            if push_time < six_months_ago:
                delete_url = f'{HARBOR_URL}/api/v2.0/{repo}/tags/{tag_name}'
                requests.delete(delete_url, headers={'Authorization': get_token()}, verify=False)
                print(f'Deleted: {repo}:{tag_name}')

if __name__ == '__main__':
    delete_old_tags()

4.2 Shell脚本方案

Alternatively,也可以使用Shell脚本实现类似功能:

复制代码
#!/bin/bash
HARBOR_URL="https://your-harbor.com"
USERNAME="admin"
PASSWORD="password"
PROJECT="your-project"

# 获取token
TOKEN=$(curl -s -k -X POST -H "Content-Type: application/json" \
  -d "{\"principal\": \"$USERNAME\", \"password\": \"$PASSWORD\"}" \
  "$HARBOR_URL/c/login" | grep -o '"token":"[^"]*' | cut -d'"' -f4)

# 获取项目中的仓库列表
REPOS=$(curl -s -k -X GET -H "Authorization: Bearer $TOKEN" \
  "$HARBOR_URL/api/v2.0/projects/$PROJECT/repositories" | jq -r '.[].name')

for REPO in $REPOS; do
  # 获取仓库的标签列表
  TAGS=$(curl -s -k -X GET -H "Authorization: Bearer $TOKEN" \
    "$HARBOR_URL/api/v2.0/$REPO/tags" | jq -r '.[] | [.name, .push_time] | @tsv')
  
  while IFS=$'\t' read -r TAG PUSH_TIME; do
    # 转换时间格式并比较
    PTIME=$(date -d "$PUSH_TIME" +%s)
    SIX_MONTHS_AGO=$(date -d "6 months ago" +%s)
    
    if [ $PTIME -lt $SIX_MONTHS_AGO ]; then
      # 删除旧标签
      curl -s -k -X DELETE -H "Authorization: Bearer $TOKEN" \
        "$HARBOR_URL/api/v2.0/$REPO/tags/$TAG"
      echo "Deleted: $REPO:$TAG"
    fi
  done <<< "$TAGS"
done

4.3 API方法的优缺点

  • 优点:灵活性强,可精确控制删除条件,适合批量操作
  • 缺点:需要编程知识,存在一定风险,需谨慎测试

5 关键步骤:运行垃圾回收释放物理空间

无论采用哪种方法删除镜像,都必须执行此步骤才能真正释放磁盘空间

5.1 执行垃圾回收

  1. 安排维护窗口:GC期间Harbor将进入只读模式,需提前通知团队

  2. 执行GC命令

    复制代码
    # 进入Harbor安装目录
    cd /path/to/harbor
    
    # 首先进行试运行(不实际删除)
    docker-compose exec -T registry garbage-collect --dry-run /etc/registry/config.yml
    
    # 确认无误后正式执行
    docker-compose exec -T registry garbage-collect /etc/registry/config.yml
  3. 监控执行结果:GC完成后,查看释放的存储空间大小

5.2 新版Harbor的在线GC

Harbor v2.0+支持在线垃圾回收,可通过UI操作:

  1. 以管理员身份登录
  2. 进入"系统管理" -> "垃圾清理"
  3. 点击"立即清理"或设置定时任务
  4. 在"历史记录"中查看执行结果

6 预防措施:建立有效的镜像管理策略

清理只是治标,预防才是根本。以下措施可有效控制镜像增长:

6.1 制定镜像标签规范

  • 使用语义化版本控制(如v1.2.3
  • 包含构建日期或Git Commit ID(如20230901-abc1234
  • 区分环境(如devstagingprod
  • 避免滥用latest标签

6.2 设置合理的保留策略

根据不同环境设置不同的保留策略:

环境 保留策略 执行频率
开发环境 保留最近10-30个版本或7天 每天
测试环境 保留最近20-50个版本或30天 每周
生产环境 保留所有稳定版本或按需保留 手动

6.3 自动化清理流程

将清理流程纳入CI/CD流水线,定期自动执行:

  1. 使用Harbor API查询存储使用情况
  2. 在磁盘空间达到阈值时自动触发清理
  3. 定期运行垃圾回收任务
  4. 设置通知机制,报告清理结果
相关推荐
alex1002 小时前
Context Compliance Attack:大模型安全的新兴威胁与防御策略
网络·安全·web安全
xiejava10186 小时前
开源安全管理平台wazuh-安装与配置
安全·开源
粟悟饭&龟波功7 小时前
【网络安全】三、入门篇:Web安全常见漏洞概述
安全·web安全
FIN66687 小时前
新天力科技IPO进行时:技术引领未来,创新驱动发展
科技·安全·搜索引擎·产品运营·创业创新·制造
pingao1413788 小时前
道路交通气象站:筑牢交通出行安全防线的智能监测卫士
安全
通信瓦工9 小时前
IEC 62368-1-2023音视频、信息技术和通信技术设备安全标准标准介绍
安全·信息技术·标准下载·标准翻译
大翻哥哥10 小时前
Python 2025:网络安全与智能防御新范式
安全·web安全
知攻善防实验室14 小时前
大洞,速修,Redis远程命令执行漏洞。
安全·网络安全·渗透测试
安卓开发者15 小时前
鸿蒙NEXT安全单元访问开发指南:构建可信应用的安全基石
安全·华为·harmonyos