痛点
团队规模一大,容器镜像管理就失控:
- Docker Hub 拉取限流(匿名用户 100 pulls/6h),CI/CD 流水线频繁卡死
- 镜像散落在多个 registry,版本溯源困难,无法统一安全扫描
- 合规要求镜像不能存放第三方公有云,必须内部托管
- 缺乏细粒度权限控制,所有人都能 push/delete 生产镜像
如果你的 Kubernetes 集群超过 10 个节点、每天构建镜像超过 50 次,一个靠谱的私有 registry 就是刚需。Harbor 是 CNCF 毕业项目,目前最成熟的开源选择。
方案
Harbor = 私有镜像仓库 + 漏洞扫描 + RBAC + 镜像签名 + 复制策略,一套解决所有镜像管理问题。
核心架构:
┌─────────────────────────────────────────────┐
│ Harbor Core │
├──────────┬──────────┬───────────┬───────────┤
│ Portal │ API v2 │ Registry │ Trivy │
│ (Web UI)│ (REST) │ (分发) │ (扫描) │
├──────────┴──────────┴───────────┴───────────┤
│ PostgreSQL │ Redis │ S3/MinIO (存储后端) │
└─────────────────────────────────────────────┘
关键能力对比:
| 特性 | Docker Registry | Harbor | AWS ECR |
|---|---|---|---|
| 漏洞扫描 | ❌ | ✅ (Trivy 集成) | ✅ |
| RBAC | ❌ | ✅ (项目级) | ✅ (IAM) |
| 镜像签名 | 手动 | ✅ (Cosign/Notation) | ✅ |
| 复制策略 | ❌ | ✅ (跨地域) | ✅ (ECR Replication) |
| 垃圾回收 | 手动 | ✅ (定时) | ✅ (Lifecycle) |
| 成本 | 免费 | 免费 | $0.10/GB/月 |
实操步骤
第一步:用 Docker Compose 快速部署(生产就绪)
# 下载 Harbor 离线安装包(v2.11.x)
wget https://github.com/goharbor/harbor/releases/download/v2.11.2/harbor-offline-installer-v2.11.2.tgz
tar xzf harbor-offline-installer-v2.11.2.tgz
cd harbor
# 复制并编辑配置
cp harbor.yml.tmpl harbor.yml
编辑 harbor.yml 核心配置:
hostname: registry.example.com
# HTTPS 配置(生产必开)
https:
port: 443
certificate: /etc/harbor/certs/server.crt
private_key: /etc/harbor/certs/server.key
# 存储后端改用 S3/MinIO(默认是本地文件系统)
storage_service:
s3:
accesskey: YOUR_ACCESS_KEY
secretkey: YOUR_SECRET_KEY
region: us-east-1
bucket: harbor-registry
rootdirectory: /registry
# 数据库(生产建议外置 PostgreSQL)
database:
password: <strong-password>
max_idle_conns: 50
max_open_conns: 1000
# Trivy 漏洞扫描器
trivy:
ignore_unfixed: true
skip_update: false
security_check: vuln
执行安装:
./install.sh --with-trivy --with-chartmuseum
# 验证所有组件运行
docker compose ps
# 应看到 harbor-core, harbor-portal, registry, trivy-adapter 等全部 healthy
第二步:配置项目与 RBAC 权限
# 创建项目(通过 API)
curl -k -X POST "https://registry.example.com/api/v2.0/projects" \
-H "Authorization: Basic $(echo -n 'admin:Harbor12345' | base64)" \
-H "Content-Type: application/json" \
-d '{
"project_name": "production",
"metadata": {
"public": "false",
"auto_scan": "true",
"severity": "high",
"prevent_vul": "true"
},
"storage_limit": 107374182400
}'
关键安全配置说明:
- auto_scan: true — 每次 push 自动触发 Trivy 扫描
- prevent_vul: true + severity: high — 含高危/严重漏洞的镜像禁止被 pull
- storage_limit — 项目级存储配额(此处 100GB)
配置机器人账户(给 CI/CD 用):
# 创建机器人账户,限制只能 push 到 production 项目
curl -k -X POST "https://registry.example.com/api/v2.0/robots" \
-H "Authorization: Basic $(echo -n 'admin:Harbor12345' | base64)" \
-H "Content-Type: application/json" \
-d '{
"name": "ci-pusher",
"duration": 365,
"level": "project",
"permissions": [{
"namespace": "production",
"kind": "project",
"access": [
{"resource": "repository", "action": "push"},
{"resource": "repository", "action": "pull"}
]
}]
}'
第三步:Kubernetes 集群对接
创建 pull secret 并配置默认 ServiceAccount:
# 创建 registry secret
kubectl create secret docker-registry harbor-creds \
--docker-server=registry.example.com \
--docker-username=robot\$ci-pusher \
--docker-password=<robot-token> \
-n production
# 给 default ServiceAccount 添加 imagePullSecrets(全命名空间生效)
kubectl patch serviceaccount default -n production \
-p '{"imagePullSecrets": [{"name": "harbor-creds"}]}'
在 CI/CD 中使用(GitHub Actions 示例):
- name: Build and Push
run: |
docker login registry.example.com -u robot\$ci-pusher -p ${{ secrets.HARBOR_TOKEN }}
docker build -t registry.example.com/production/myapp:${{ github.sha }} .
docker push registry.example.com/production/myapp:${{ github.sha }}
第四步:配置跨地域复制(灾备)
# 添加远端 registry endpoint
curl -k -X POST "https://registry.example.com/api/v2.0/registries" \
-H "Authorization: Basic $(echo -n 'admin:Harbor12345' | base64)" \
-H "Content-Type: application/json" \
-d '{
"name": "dr-site",
"type": "harbor",
"url": "https://registry-dr.example.com",
"credential": {
"type": "basic",
"access_key": "replication-user",
"access_secret": "replication-password"
}
}'
# 创建复制策略:production 项目所有 tag 为 release-* 的镜像同步到灾备站
curl -k -X POST "https://registry.example.com/api/v2.0/replication/policies" \
-H "Authorization: Basic $(echo -n 'admin:Harbor12345' | base64)" \
-H "Content-Type: application/json" \
-d '{
"name": "prod-to-dr",
"src_registry": null,
"dest_registry": {"id": 1},
"dest_namespace": "production",
"filters": [
{"type": "name", "value": "production/**"},
{"type": "tag", "value": "release-*"}
],
"trigger": {"type": "event_based"},
"enabled": true
}'
避坑
1. 存储爆炸 — 不清理旧镜像导致磁盘告警
Harbor 默认不删除未被 tag 引用的 blob。必须开启垃圾回收:
# 通过 API 触发 GC(建议 cron 每周执行)
curl -k -X POST "https://registry.example.com/api/v2.0/system/gc/schedule" \
-H "Authorization: Basic $(echo -n 'admin:Harbor12345' | base64)" \
-H "Content-Type: application/json" \
-d '{"schedule": {"type": "Weekly", "cron": "0 0 2 * * 0"}}'
同时配置 Tag 保留策略:每个仓库只保留最近 10 个 tag + 最近 30 天的 tag,其余自动删除。
2. Trivy 数据库更新失败 — 扫描结果过时
离线环境下 Trivy 无法自动拉取漏洞数据库。解决方案:
# 在有网络的机器上定期下载 Trivy DB
oras pull ghcr.io/aquasecurity/trivy-db:2
# 将 db.tar.gz 传到 Harbor 服务器,配置 skip_update + 本地 DB 路径
生产环境建议:用内网 HTTP 代理让 Trivy 定时同步,或搭建 trivy-db 的内部 mirror。
3. Harbor 升级踩坑 — 数据库迁移失败
升级前必做:
# 1. 备份数据库
docker compose exec harbor-db pg_dump -U postgres registry > harbor_backup.sql
# 2. 备份配置
cp harbor.yml harbor.yml.bak
# 3. 停止服务后再解压新版本覆盖安装
docker compose down
# 4. 使用 migrate 工具
./install.sh --with-trivy
切勿跨大版本升级(如 2.8 直接到 2.11),必须逐版本滚动升级。
总结
Harbor 解决了企业容器镜像管理的三大核心问题:安全(漏洞扫描+镜像签名)、权限(项目级 RBAC+机器人账户)、可靠(跨地域复制+GC 策略)。
落地建议: - 小团队(<20人):单节点 Docker Compose 部署,S3 后端,够用 - 中大规模:HA 部署(多副本 Harbor Core + 外置 PostgreSQL/Redis + 共享存储) - 存储后端优先选 S3/MinIO,本地文件系统不利于扩展和备份 - Day 2 运维:监控 Harbor 组件健康(Prometheus exporter 已内置)、定期 GC、告警磁盘水位
一句话:镜像数量超过 100 个或者团队超过 5 人,就该上 Harbor 了。