Harbor API实战:高效批量删除镜像的完整指南

Harbor API实战:高效批量删除镜像的完整指南

一、引言:镜像管理的痛点与Harbor API的价值

在容器化部署的场景中,Harbor作为企业级镜像仓库,承担着镜像存储、版本控制、安全扫描等核心功能。然而,随着项目迭代和镜像数量的激增,镜像管理面临两大挑战:

  1. 存储成本压力:未及时清理的旧镜像会占用大量存储空间,增加硬件成本。
  2. 管理效率低下:手动逐个删除镜像效率低下,尤其在需要清理大量镜像时(如测试环境镜像、过期版本)。

Harbor API的批量删除功能通过自动化脚本,可实现分钟级的镜像清理,显著提升管理效率。本文将结合实战案例,详细解析如何使用Harbor API实现批量删除镜像。

二、Harbor API基础:认证与核心接口

1. API认证机制

Harbor API采用基于Token的认证方式,需通过以下步骤获取访问权限:

  1. # 示例:使用curl获取Token(需替换用户名、密码和Harbor地址)
  2. curl -u "admin:Harbor12345" -X POST "https://harbor.example.com/api/v2.0/users/current/sessions" -k

关键参数

  • -u:用户名和密码(格式为username:password)。
  • -k:忽略SSL证书验证(生产环境需配置有效证书)。
  • 返回的Token需通过Authorization: Bearer <token>头部在后续请求中使用。

2. 核心API接口

批量删除镜像主要依赖以下接口:

  • 获取项目列表GET /api/v2.0/projects
  • 获取镜像仓库列表GET /api/v2.0/projects/{project_id}/repositories
  • 获取镜像标签列表GET /api/v2.0/projects/{project_id}/repositories/{repository_name}/artifacts
  • 删除镜像标签DELETE /api/v2.0/projects/{project_id}/repositories/{repository_name}/artifacts/{digest}

三、实战:批量删除镜像的完整流程

1. 环境准备

  • 工具依赖
    • curl:用于测试API调用。
    • jq:解析JSON响应(可选,但推荐)。
    • 脚本语言(如Python、Bash)编写自动化脚本。
  • Harbor配置
    • 确保用户具有Project AdminSystem Admin权限。
    • 开启API访问(默认启用,需检查core.auth配置)。

2. 步骤一:获取项目ID列表

  1. # 获取所有项目ID(示例)
  2. curl -X GET "https://harbor.example.com/api/v2.0/projects" -H "Authorization: Bearer <token>" -k | jq '.[].project_id'

输出示例

  1. [
  2. "1",
  3. "2",
  4. "3"
  5. ]

3. 步骤二:遍历项目并获取镜像仓库

  1. # 遍历项目ID,获取每个项目的镜像仓库列表
  2. for project_id in 1 2 3; do
  3. curl -X GET "https://harbor.example.com/api/v2.0/projects/${project_id}/repositories" \
  4. -H "Authorization: Bearer <token>" -k | jq '.[] | .name'
  5. done

输出示例

  1. "library/nginx"
  2. "library/ubuntu"
  3. "dev/test-app"

4. 步骤三:获取镜像标签并筛选删除目标

  1. # 获取镜像标签列表(示例:筛选30天前创建的标签)
  2. for repo in "library/nginx" "library/ubuntu"; do
  3. curl -X GET "https://harbor.example.com/api/v2.0/projects/1/repositories/${repo}/artifacts" \
  4. -H "Authorization: Bearer <token>" -k | jq '.[] | select(.tags[0].push_time < "2023-01-01T00:00:00Z") | .digest'
  5. done

筛选逻辑

  • 通过push_time字段筛选过期镜像。
  • 可结合tag名称(如v1.0test)进一步过滤。

5. 步骤四:批量删除镜像

  1. # 批量删除筛选出的镜像(示例)
  2. for digest in "sha256:abc123" "sha256:def456"; do
  3. curl -X DELETE "https://harbor.example.com/api/v2.0/projects/1/repositories/library%2Fnginx/artifacts/${digest}" \
  4. -H "Authorization: Bearer <token>" -k
  5. done

注意事项

  • 仓库名称中的/需转义为%2F
  • 删除操作不可逆,建议先备份重要镜像。

四、自动化脚本优化:Python实现

1. 完整脚本示例

  1. import requests
  2. import json
  3. from datetime import datetime, timedelta
  4. # 配置参数
  5. HARBOR_URL = "https://harbor.example.com"
  6. USERNAME = "admin"
  7. PASSWORD = "Harbor12345"
  8. PROJECT_ID = "1" # 目标项目ID
  9. DAYS_THRESHOLD = 30 # 删除N天前的镜像
  10. # 获取Token
  11. def get_token():
  12. url = f"{HARBOR_URL}/api/v2.0/users/current/sessions"
  13. response = requests.post(url, auth=(USERNAME, PASSWORD), verify=False)
  14. return response.json()["token"]
  15. # 获取过期镜像Digest
  16. def get_expired_artifacts(token):
  17. url = f"{HARBOR_URL}/api/v2.0/projects/{PROJECT_ID}/repositories"
  18. headers = {"Authorization": f"Bearer {token}"}
  19. expired_digests = []
  20. # 获取所有仓库
  21. repositories = requests.get(url, headers=headers, verify=False).json()
  22. for repo in repositories:
  23. repo_name = repo["name"]
  24. artifacts_url = f"{HARBOR_URL}/api/v2.0/projects/{PROJECT_ID}/repositories/{repo_name.replace('/', '%2F')}/artifacts"
  25. artifacts = requests.get(artifacts_url, headers=headers, verify=False).json()
  26. # 筛选过期镜像
  27. for artifact in artifacts:
  28. if artifact["tags"]:
  29. push_time = datetime.fromisoformat(artifact["tags"][0]["push_time"].replace("Z", "+00:00"))
  30. if push_time < datetime.now() - timedelta(days=DAYS_THRESHOLD):
  31. expired_digests.append((repo_name, artifact["digest"]))
  32. return expired_digests
  33. # 批量删除镜像
  34. def delete_artifacts(token, digests):
  35. headers = {"Authorization": f"Bearer {token}"}
  36. for repo_name, digest in digests:
  37. url = f"{HARBOR_URL}/api/v2.0/projects/{PROJECT_ID}/repositories/{repo_name.replace('/', '%2F')}/artifacts/{digest}"
  38. response = requests.delete(url, headers=headers, verify=False)
  39. if response.status_code == 200:
  40. print(f"Deleted: {repo_name}@{digest}")
  41. else:
  42. print(f"Failed to delete {repo_name}@{digest}: {response.text}")
  43. # 主流程
  44. if __name__ == "__main__":
  45. token = get_token()
  46. expired_digests = get_expired_artifacts(token)
  47. delete_artifacts(token, expired_digests)

2. 脚本优化点

  • 错误处理:添加try-except捕获网络异常。
  • 日志记录:将删除结果写入日志文件。
  • 并行删除:使用多线程加速大规模删除操作。
  • 配置化:通过配置文件管理Harbor地址、用户名等参数。

五、安全与最佳实践

1. 安全建议

  • 最小权限原则:为脚本执行账户分配Project Admin而非System Admin权限。
  • API访问控制:通过Harbor的Robot Account功能生成专用Token,限制脚本的访问范围。
  • 审计日志:定期检查Harbor的审计日志,监控删除操作。

2. 最佳实践

  • 测试环境验证:先在测试环境运行脚本,确认无误后再应用到生产环境。
  • 备份策略:删除前通过harbor-backup工具备份镜像数据。
  • 定期清理:将脚本纳入CI/CD流水线,实现自动化清理。

六、总结与扩展

通过Harbor API实现批量删除镜像,可显著提升镜像管理效率,降低存储成本。本文从API认证、核心接口、实战流程到自动化脚本,提供了完整的解决方案。未来可进一步探索:

  • 与Prometheus集成:根据镜像使用率(如拉取次数)动态调整删除策略。
  • 多Harbor实例管理:通过统一脚本管理多个Harbor仓库的镜像。

掌握Harbor API的批量操作能力,是容器化时代开发者必备的技能之一。希望本文的实战指南能为您的镜像管理带来实质性帮助。