生产环境 DevOps 实战 | 第 17 天:Harbor 项目隔离与权限管理——项目类型、访问级别、成员角色

第 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-billingteam-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 天的完整落地方案,今天掌握的权限模型正是其基石——先想清楚角色边界,再谈镜像与部署的全链路自动化。
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片快捷回复

    暂无评论内容