第 17/60 天
引言
在云原生 DevOps 体系中,Harbor 作为制品仓库承载着全公司的容器镜像与 OCI 制品。当团队规模从一个小项目扩展到多个业务线、多个环境(dev/staging/prod)时,一个赤裸裸的「大杂烩仓库」会迅速演变成安全与协作的噩梦:镜像标签冲突、权限边界模糊、误删生产镜像、审计无从追溯……
Harbor 通过 项目(Project) 这一核心隔离单元,配合精细的成员角色与访问级别,提供了从”一个仓库装所有东西”到”多项目多团队严隔离”的完整能力。
本文是「三件套集成」系列中关键的一环——因为后续第 29 天「Tekton 推送镜像到 Harbor」、第 33 天「多项目多团队隔离方案」都建立在今天讲的项目隔离与权限模型之上。读完本文,你将掌握:
- Harbor 项目的三种类型(公有/私有/代理缓存)及其适用场景
- 项目级成员角色的权限矩阵与最佳实践
- 机器人账号(Robot Account)与成员角色的区别
- 如何用
curl+ Harbor REST API 脚本化完成项目与权限的批量配置 - 结合 Tekton / Argo CD 的权限设计实操
核心概念
1. 项目(Project)是什么
在 Harbor 中,项目是镜像与制品的逻辑分组单元,也是权限控制的基本边界。所有镜像都必须归属于某个项目,镜像名格式为:
<registry-host>/<project>/<repository>:<tag>
例如:harbor.stellardata.top/devops/order-service:v1.0.0
每个项目内部可以包含多个 repository(镜像仓库),仓库名由项目名 + 镜像路径构成。
2. 项目类型(Project Type)
Harbor 2.x 支持三种项目类型:
| 项目类型 | 访问方式 | 适用场景 |
|---|---|---|
| 私有项目(Private) | 仅授权成员可拉取/推送 | 生产镜像、业务核心、含敏感信息的制品(默认推荐) |
| 公有项目(Public) | 任何能访问 Harbor 的人均可匿名拉取 | 公开基础镜像、内部共享的公共组件 |
| 代理缓存项目(Proxy Cache) | 代理远端仓库(如 Docker Hub、GCR)并本地缓存 | 内网环境加速拉取公共镜像、规避网络限制 |
3. 成员角色(Roles)权限矩阵
Harbor 预置了 4 种项目级角色,权限从低到高:
| 角色 | 查看 | 拉取 Pull | 推送 Push | 管理制品(删/扫描/复制) | 管理成员 |
|---|---|---|---|---|---|
| 访客(Guest) | ✅ | ✅ | ❌ | ❌ | ❌ |
| 开发者(Developer) | ✅ | ✅ | ✅ | ✅(部分) | ❌ |
| 维护者(Maintainer) | ✅ | ✅ | ✅ | ✅ | ✅(除 owner) |
| 项目管理员(Project Admin) | ✅ | ✅ | ✅ | ✅ | ✅ |
关键差异:Guest 只能拉不能推,非常适合 Argo CD 这类只读消费者;Developer 能推能管理自己的制品,适合 CI 系统(如 Tekton);Project Admin 负责成员与权限管理,适合平台/DevOps 团队。
4. 系统级 vs 项目级
Harbor 还有系统级角色(通过「用户管理」和「机器人账号」配置):
- 系统管理员(System Admin):全局最高权限,可管理所有项目、系统配置
- 机器人账号(Robot Account):面向自动化流程(CI/CD)的”程序身份”,绑定到单个或多个项目,可赋予精确角色与过期时间
5. 与 Tekton / Argo CD 的角色设计
在实际三件套中,权限模型的经典划分:
- Tekton(CI):使用 Developer 角色(或专用 Robot Account)推送镜像到 dev/staging 项目
- Argo CD(CD):使用 Guest 角色(只读拉取)从 Harbor 拉取镜像用于部署
- 人工操作:维护者/项目管理员角色分配给对应团队负责人
实战步骤
步骤一:创建项目(Web 界面 + CLI 两种方式)
Web 方式:登录 Harbor → 「新建项目」→ 填写名称、选择可见性(私有/公有)、是否启用代理缓存。
API 方式(脚本化创建,便于批量):
#!/bin/bash
# create_project.sh —— 批量创建 Harbor 项目
HARBOR_URL="https://harbor.stellardata.top"
ADMIN_USER="admin"
ADMIN_PASS="your-admin-password"
# 用 basic auth 直接调 API(Harbor 2.x 支持)
for proj in devops-frontend devops-backend prod-core; do
curl -sk -u "$ADMIN_USER:$ADMIN_PASS" -X POST
"$HARBOR_URL/api/v2.0/projects"
-H "Content-Type: application/json"
-d "{"project_name":"$proj","public":false,"metadata":{"public":"false"}}"
echo " -> 创建项目 $proj"
done
步骤二:配置成员角色(用户 + 角色绑定)
通过 API 为项目添加成员并指定角色(1=ProjectAdmin, 2=Developer, 3=Guest, 4=Maintainer):
// 为项目 devops-backend 添加成员并指定角色
POST /api/v2.0/projects/devops-backend/members
{
"role_id": 2, // 2 = Developer
"member_user": {
"username": "tekton-ci"
}
}
对应 curl 命令:
# add_member.sh —— 为项目添加成员并设置角色
HARBOR_URL="https://harbor.stellardata.top"
AUTH="admin:your-admin-password"
add_member() {
local project="$1" username="$2" role="$3"
curl -sk -u "$AUTH" -X POST
"$HARBOR_URL/api/v2.0/projects/$project/members"
-H "Content-Type: application/json"
-d "{"role_id":$role,"member_user":{"username":"$username"}}"
echo " -> $username 已加入 $project (role_id=$role)"
}
# Tekton CI 用户对开发项目拥有 Developer(2) 权限
add_member devops-backend tekton-ci 2
# Argo CD 用户对生产项目只读 Guest(3)
add_member prod-core argocd 3
步骤三:Robot Account(为 Tekton CI 配置自动化凭证)
机器人账号是 Harbor 面向 CI/CD 的推荐方式——它拥有独立凭据(用户名+Token),可设置过期时间,且不属于任何人类用户。这正是第 29 天 Tekton 推送镜像所需的标准凭证。
# 创建 Robot Account 的 API 请求(一次性,返回 token 需保存)
POST /api/v2.0/robots
{
"name": "tekton-push",
"duration": 7776000, // 90 天有效期(秒)
"description": "Tekton CI 推送 devops-* 项目镜像",
"level": "project", // project 级
"disable": false,
"permissions": [
{
"kind": "project",
"namespace": "devops-backend",
"access": [
{ "resource": "repository", "action": "push" },
{ "resource": "repository", "action": "pull" },
{ "resource": "artifact", "action": "read" }
]
}
]
}
关键实践:Robot Account 的 Token 只在创建时返回一次,务必保存到 Secret(如 Kubernetes Secret),供 Tekton PipelineRun 挂载使用。
步骤四:设置私有项目并验证访问控制
将项目设为私有,然后验证未授权用户无法拉取:
# 1. 项目设为私有(metadata.public=false)
curl -sk -u "admin:pass" -X PUT
"$HARBOR_URL/api/v2.0/projects/devops-backend"
-H "Content-Type: application/json"
-d '{"metadata":{"public":"false"}}'
# 2. 验证:无凭据拉取应返回 401
curl -sk -o /dev/null -w "%{http_code}n"
"https://harbor.stellardata.top/v2/devops-backend/order-service/manifests/v1.0.0"
# 预期输出:401
# 3. 验证:guest 用户(只读)可以拉取但推送失败
docker pull harbor.stellardata.top/devops-backend/order-service:v1.0.0 # 成功
docker push harbor.stellardata.top/devops-backend/order-service:v2.0.0 # 失败(403)
步骤五:代理缓存项目加速内网拉取
在内网/离线环境,用代理缓存项目让 Docker/containerd 自动从远端缓存公共镜像:
# 创建代理缓存项目(代理 Docker Hub)
curl -sk -u "admin:pass" -X POST
"$HARBOR_URL/api/v2.0/projects"
-H "Content-Type: application/json"
-d '{
"project_name": "dockerhub-cache",
"registry_id": 1, # 指向已配置的 Docker Hub 端点
"metadata": {"public": "true"}
}'
# 之后 worker 节点拉取时走缓存项目即可
docker pull harbor.stellardata.top/dockerhub-cache/library/nginx:1.27
# Harbor 会自动回源 Docker Hub 并缓存到本地
步骤六:Python 脚本化审计项目成员与权限
生产环境需要定期审计权限,用 Python 脚本批量导出所有项目的成员与角色:
#!/usr/bin/env python3
# audit_harbor.py —— 审计所有项目的成员与角色
import json
import urllib.request
from base64 import b64encode
HARBOR = "https://harbor.stellardata.top"
AUTH = b64encode(b"admin:your-password").decode()
def api(path):
req = urllib.request.Request(
f"{HARBOR}{path}",
headers={"Authorization": f"Basic {AUTH}", "Accept": "application/json"})
with urllib.request.urlopen(req) as r:
return json.loads(r.read())
ROLES = {1: "ProjectAdmin", 2: "Developer", 3: "Guest", 4: "Maintainer"}
projects = api("/api/v2.0/projects?page_size=100")
for p in projects:
name = p["name"]
members = api(f"/api/v2.0/projects/{name}/members")
print(f"n== 项目: {name} (public={p.get('public', False)}) ==")
for m in members:
role = ROLES.get(m.get("role_id"), "unknown")
entity = m.get("entity_name", m.get("entity_type", "?"))
print(f" - {entity:20s} -> {role}")
常见问题
Q1:私有项目和公有项目能互相转换吗?
可以。通过「项目设置」或 API(metadata.public 字段)随时切换。但从公有改为私有时,之前已经拉取的缓存不受影响,只是后续未授权用户无法再拉取。
Q2:Robot Account 和普通用户成员有什么区别?
Robot Account 是”程序身份”,没有密码、不能登录 Web UI、权限按 API/镜像操作精确授权,且可设置过期时间,适合 CI/CD 自动化;普通用户成员是”人类身份”,可登录 UI 管理,适合日常操作与人工审核。
Q3:为什么 Argo CD 建议用 Guest 而不是 Developer?
遵循最小权限原则。Argo CD 只需要从 Harbor 拉取镜像用于部署,Guest 角色已完全满足且无法推送/删除,能有效防止 CD 系统被攻破后对制品库造成写破坏。
Q4:多个团队共用 Harbor 时,项目怎么划分?
推荐”每个团队/每个业务线一个私有项目“,命名带团队前缀(如 team-billing、team-orders),团队成员各自授权 Developer,团队负责人为 Maintainer/Project Admin,平台团队为系统管理员。避免在同一个项目里塞多个团队,否则权限无法精确隔离。
Q5:Tekton 推送镜像的 Robot Account Token 如何安全管理?
Token 创建后仅显示一次。应立刻存入 Kubernetes Secret,通过 Tekton Workspaces/Secret 挂载到流水线 step,禁止硬编码在 YAML 或明文配置里。同时设置合理过期时间并纳入轮换周期。
Q6:代理缓存项目会占用大量存储吗?
会缓存回源镜像,需结合第 19 天的清理策略(保留策略 + 定时回收)控制缓存体积。通常只对常用公共镜像开启代理缓存。
总结
- 项目是 Harbor 权限隔离的基本单元,镜像归属到项目后,项目类型(私有/公有/代理缓存)决定了可见性与访问方式。
- 四种成员角色(Guest/Developer/Maintainer/Project Admin)构成清晰的权限阶梯,生产环境务必遵循最小权限原则:Argo CD 用只读 Guest,Tekton CI 用 Developer 或专用 Robot Account。
- Robot Account 是 CI/CD 自动化凭证的最佳实践,具备精确权限、独立凭据与过期机制,是后续 Tekton→Harbor 集成(第 29 天)的安全基础。
- 全部操作均可通过 Harbor REST API 脚本化,配合批量创建、成员绑定与 Python 审计脚本,可高效管理大规模多团队环境。
- 多项目多团队隔离是第 33 天的完整落地方案,今天掌握的权限模型正是其基石——先想清楚角色边界,再谈镜像与部署的全链路自动化。















暂无评论内容