Harbor生产级部署实战:PostgreSQL+Redis+MinIO全解耦架构详解

Harbor生产级部署实战:PostgreSQL+Redis+MinIO全解耦架构详解

环境介绍

采用解耦架构 :Harbor 不使用自身内置 PostgreSQL、Redis、本地存储,全部依赖外部独立组件,做到元数据、缓存、镜像存储彻底分离,符合生产高可用架构标准。

各组件部署位置:

1.K8s 集群内部

  • 部署 PostgreSQL:存放 Harbor 所有元数据(用户、项目、镜像信息、配置等)
  • 部署 Redis:负责 Harbor 会话缓存、接口缓存、任务队列缓存
  • 访问方式:通过 K8s NodePort 端口对外暴露,供外网 Harbor 连接

2.独立对象存储服务器

  • 单独部署 MinIO:专门存放 Harbor 镜像二进制层、Blob 文件
  • 端口:9000 为 API 端口、9001 为 Web 管理控制台
  • 自建独立桶 harbor 专供镜像仓库使用

3.独立 Harbor 服务器(Docker 部署)

  • 单独一台机器用 Docker安装 Harbor
  • 配置 HTTPS 域名
  • 完全剥离内置 PG、Redis,全量对接 K8s 集群中间件
  • 镜像存储后端对接外置 MinIO,不落地本地磁盘

一、K8s 部署 PostgreSQL

1.创建命名空间
bash 复制代码
kubectl create ns harbor
2.postgres.yaml
yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: pg-harbor           # Service 的名称
  namespace: harbor         # 指定 Service 所在的命名空间
  labels:
    app: pg-harbor          # 为 Service 添加标签
spec:
  ports:
  - port: 5432              # Service 暴露的端口
    name: pg                # 端口的名称
  clusterIP: None           # 设置为 None 使其成为无头 Service
  selector:
    app: pg-harbor          # 选择器,将流量导向带有 app=pg-harbor 标签的 Pod
---
apiVersion: v1
kind: Service
metadata:
  name: pg-harbor-nodeport  # Service 的名称
  namespace: harbor         # 指定 Service 所在的命名空间
spec:
  type: NodePort            # 指定 Service 类型为 NodePort
  ports:
  - port: 5432              # Service 在集群内部的端口
    nodePort: 30532         # 在节点上开放的固定端口,外部通过 节点IP:30532 访问
  selector:
    app: pg-harbor          # 选择器,同样指向 app=pg-harbor 的 Pod
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: pg-harbor           # StatefulSet 的名称
  namespace: harbor         # 指定 StatefulSet 所在的命名空间
spec:
  serviceName: pg-harbor    # 关联的无头 Service 名称,用于 Pod 的网络身份
  replicas: 1               # 期望运行的 Pod 副本数量
  selector:
    matchLabels:
      app: pg-harbor        # 用于查找和管理 Pod 的选择器
  template:                
    metadata:
      labels:
        app: pg-harbor      # Pod 的标签,必须与上面的 selector 匹配
    spec:
      containers:
      - name: postgres      # 容器的名称
        image: postgres:14-alpine # 使用的容器镜像及版本
        ports:
        - containerPort: 5432 # 容器内部监听的端口
        env:                # 定义容器的环境变量
        - name: POSTGRES_USER
          value: "harbor"   # 设置数据库用户名
        - name: POSTGRES_PASSWORD
          value: "Pg@Harbor123" # 设置数据库密码
        - name: POSTGRES_DB
          value: "registry" # 设置默认创建的数据库名
        - name: TZ
          value: Asia/Shanghai # 设置容器的时区
        volumeMounts:       # 将存储卷挂载到容器内的指定路径
        - name: pg-data     # 引用的存储卷名称(在 volumeClaimTemplates 中定义)
          mountPath: /var/lib/postgresql/data # 挂载路径,即 PostgreSQL 的数据目录
  volumeClaimTemplates:     # 为每个 Pod 自动创建持久化卷声明 (PVC) 的模板
  - metadata:
      name: pg-data         # PVC 的名称模板
    spec:
      accessModes: ["ReadWriteOnce"] # 访问模式,表示卷可以被单个节点以读写方式挂载
      resources:
        requests:
          storage: 10Gi     # 申请 10Gi 的存储空间
3.应用配置
bash 复制代码
kubectl apply -f postgres.yaml
4.手动创建PG库
bash 复制代码
kubectl exec -it -n harbor pg-harbor-0 bash

psql -U harbor -d registry

创建notary_signer和notary_server

bash 复制代码
CREATE DATABASE notary_signer;
CREATE DATABASE notary_server;

退出

bash 复制代码
\q
exit

二、K8s 部署 Redis

1.redis.yaml
yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: redis-harbor
  namespace: harbor
spec:
  ports:
  - port: 6379
    name: redis
  clusterIP: None
  selector:
    app: redis-harbor
---
# 外部访问 Service
apiVersion: v1
kind: Service
metadata:
  name: redis-harbor-nodeport
  namespace: harbor
spec:
  type: NodePort
  ports:
  - port: 6379
    nodePort: 30379
  selector:
    app: redis-harbor
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis-harbor
  namespace: harbor
spec:
  serviceName: redis-harbor
  replicas: 1
  selector:
    matchLabels:
      app: redis-harbor
  template:
    metadata:
      labels:
        app: redis-harbor
    spec:
      containers:
      - name: redis
        image: redis:7-alpine
        command: ["/bin/sh","-c"]
        args:
        - redis-server --requirepass Redis@Harbor123 --appendonly yes --protected-mode no
        volumeMounts:
        - name: redis-data
          mountPath: /data
  volumeClaimTemplates:
  - metadata:
      name: redis-data
    spec:
      accessModes: ["ReadWriteOnce"]
      resources:
        requests:
          storage: 5Gi
2.应用配置
bash 复制代码
kubectl apply -f redis.yaml

三、验证PostgreSQL和Redis外部连接

1.安装 psql 客户端(Harbor 服务器执行)
bash 复制代码
apt install postgresql-client -y
2.连接命令
bash 复制代码
psql -h 172.16.0.200 -p 30532 -U harbor -d registry
3.输入密码,出现下面内容表示PostgreSQL连接成功
4.安装 redis-cli(Harbor 服务器执行)
bash 复制代码
apt install redis-tools -y
5.连接命令
bash 复制代码
redis-cli -h 172.16.0.200 -p 30379

连接后执行:

bash 复制代码
AUTH Redis@Harbor123   #Redis密码
6.出现 OK = Redis认证成功

再测试ping ,返回 pong → Redis完全正常

四、独立部署 MinIO(对象存储)

单机部署硬件条件

  • 操作系统: Linux x86_64 / ARM64。主流发行版如 Ubuntu、CentOS、Debian 均可。
  • CPU: 最低 2 核。
  • 内存: 最低2G,建议至少 4GB。
  • 磁盘: 至少 20GB 可用空间。为获得更好性能,推荐使用 SSD。
  • 网络 : 需要开放 9000 (API) 和 9001 (Web 控制台) 端口。
1.Docker部署指令
bash 复制代码
docker run -d --restart=always --name minio -p 9000:9000 -p 9001:9001 -v /data/minio:/data -e "MINIO_ROOT_USER=minioadmin" -e "MINIO_ROOT_PASSWORD=minioadmin123" --memory 1.5G quay.io/minio/minio server /data --console-address ":9001"

关键说明

  • 宿主机数据目录:/data/minio(自动创建)
  • 内存限制:1.5G(适配本演示2H2G 服务器,不爆内存)
  • 端口:9000(API)、9001(控制台)
  • 账号:minioadmin / 密码:minioadmin123
2.验证MinIo功能正常
①浏览器访问测试

浏览器打开 http://服务器IP:9001,能打开登录页面、输入账号密码能登录 → 控制台正常

②在任意机器测试网络联通
bash 复制代码
curl -v http://云服务器IP:9000

正常会返回一段 XML 内容,不是超时、不是拒绝连接。

3.手动创建Bucket
  • 登录 9001 控制台

  • 左侧 Buckets → Create Bucket

  • 名字填:harbor

  • 其他默认,直接创建

4.测试上传/下载文件(核心功能)
  • harbor 这个 Bucket

  • Upload 随便传一个小文件(txt / 图片都行)

  • 上传成功后,点击文件下载

上传、能下载、不报错存储读写正常

5.用命令行mc测试(模拟调用S3接口)
安装 mc 客户端(随便一台 Linux 机器)
bash 复制代码
wget https://dl.min.io/client/mc/release/linux-amd64/mc
chmod +x mc
mv mc /usr/local/bin/
配置连接你的云服务器 MinIO
bash 复制代码
mc alias set myminio http://云服务器IP:9000 minioadmin minioadmin123
  • 查看 bucket 列表
bash 复制代码
mc ls myminio

能看到刚才建的 harbor 桶 → S3 接口完全正常

  • 测试写入文件
bash 复制代码
echo "test" > test.txt
mc cp test.txt myminio/harbor/

无报错就是写入成功。

同时,在web控制台也能看到上传的test.txt

五、部署harbor

1.下载harbor安装包

前往 github地址:GitHub - goharbor/harbor: An open source trusted cloud native registry project that stores, signs, and scans content. · GitHub下载offline安装压缩包

2.上传到服务器并解压

上传压缩包到服务器解压后获得 harbor 文件夹

3.修改核心配置
bash 复制代码
cp harbor.yml.tmpl harbor.yml

按照配置需求,修改harbor.yml内容如下:

yml 复制代码
hostname: harbor.xxxxx.com   #解析到harbor服务器的域名

http:
  port: 80

https:
  port: 443
  certificate: /data/harbor/cert/harbor.pem    #https证书
  private_key: /data/harbor/cert/harbor.key    #https证书

harbor_admin_password: Harbor12345    #harbor管理员密码

data_volume: /data/harbor   #默认数据存储路径

# 外部 PostgreSQL(对接 K8s-PG)
external_database:
  harbor:
    host: 172.16.0.200
    port: 30532
    db_name: registry
    username: harbor
    password: Pg@Harbor123
    ssl_mode: disable
  notary_signer:
    host: 172.16.0.200
    port: 30532
    db_name: notary_signer
    username: harbor
    password: Pg@Harbor123
    ssl_mode: disable
  notary_server:
    host: 172.16.0.200
    port: 30532
    db_name: notary_server
    username: harbor
    password: Pg@Harbor123
    ssl_mode: disable

# 外部 Redis(对接 K8s-Redis)
external_redis:
  host: 172.16.0.200:30379
  password: Redis@Harbor123
  registry_db_index: 1
  jobservice_db_index: 2
  trivy_db_index: 5
  idle_timeout_seconds: 30

# 外部MinIO(对接云服务器对象存储)
storage_service:
  s3:
    accesskey: minioadmin
    secretkey: minioadmin123
    region: us-east-1
    bucket: harbor  #必须在minio中先创建harbor桶
    secure: false
    regionendpoint: http://你的MinIO服务器IP:9000   #minio服务器IP+9000端口
    v4auth: true
    skipverify: true

trivy:
  ignore_unfixed: false
  skip_update: false
  insecure: false

jobservice:
  max_job_workers: 10
  max_job_duration_hours: 24
  job_loggers:
    - STD_OUTPUT
    - FILE
  logger_sweeper_duration: 1

notification:
  webhook_job_max_retry: 3
  webhook_job_http_client_timeout: 3

log:
  level: info
  local:
    rotate_count: 50
    rotate_size: 200M
    location: /var/log/harbor

_version: 2.15.0
4.执行初始化部署
bash 复制代码
./prepare
docker compose up -d

六、Docker客户端配置&镜像推拉测试

1.从其他仓库拉取一个镜像
bash 复制代码
docker pull nginx:alpine
2.Docker登录私有仓库
bash 复制代码
docker login harbor.xxxxx.com    # 替换成你的仓库地址
3.镜像打标签、推送
bash 复制代码
docker tag nginx:alpine harbor.xxxxx.com/library/nginx:alpine #替换成你的harbor仓库地址
docker push harbor.xxxxx.com/library/nginx:alpine #替换成你的harbor仓库地址
4.测试拉取 + 运行
bash 复制代码
docker pull harbor.xxxxx.com/library/nginx:alpine  # 替换成你的harbor仓库地址
docker run -d harbor.xxxxx.com/library/nginx:alpine  # 替换成你的harbor仓库地址
5.成功在harbor和minio控制台查看上传的镜像文件


七、Harbor + MinIO 进阶用法

1.MinIO 为 Harbor 配置最小权限子账号
①创建 MinIO 专用业务用户
bash 复制代码
mc admin user add myminio harbor-svc HarborPass123!
②编写生产级最小权限策略 policy.json

允许:列出桶内内容、上传 / 下载 / 删除镜像对象,仅限定 harbor

json 复制代码
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:ListBucket",
        "s3:GetObject",
        "s3:PutObject",
        "s3:DeleteObject"
      ],
      "Resource": [
        "arn:aws:s3:::harbor",
        "arn:aws:s3:::harbor/*"
      ]
    }
  ]
}
③创建策略并绑定到专用用户
bash 复制代码
# 创建策略,取名harbor-rw
mc admin policy create myminio harbor-rw policy.json
# 绑定harbor-rw策略给用户harbor-svc
mc admin policy attach myminio harbor-rw --user harbor-svc
④给 Harbor 生成专用 AccessKey
bash 复制代码
mc admin accesskey create myminio --user harbor-svc

保存生成的 AccessKey / SecretKey,用于修改 Harbor 存储配置。

⑤修改 harbor.yml 接入 MinIO 子账号
yaml 复制代码
# MinIO
storage_service:
  s3:
    accesskey: RNJVCGM6PA2UM2KH8WWS   #替换成你的accesskey
    secretkey: uQsH8+i7VcbOPrNUWrgjgghzJ8HL2BptDWshTIVt   #替换成你的secretkey
    region: us-east-1
    bucket: harbor
    secure: false
    regionendpoint: http://你的minio服务器IP:9000
    v4auth: true
    skipverify: true

重启生效 Harbor:

bash 复制代码
docker compose down
./prepare
docker compose up -d
⑥权限验证步骤

用子账号新建 mc 别名做测试

bash 复制代码
mc alias set test-harbor-svc http://你的MinIO服务器IP:9000 harbor-svc HarborPass123!

验证结果:

  • mc ls test-harbor-svc只能看到 harbor 一个桶,看不到其他桶,无全局浏览权限

  • mc ls test-harbor-svc/harbor正常列出桶内 docker 目录,读写列表权限正常

  • Docker 推拉镜像:harbor 推拉、运行完全正常

2.MinIO 生命周期规则(自动清理 Harbor 旧镜像,释放存储)

这里我们给 harbor 桶配置生命周期规则,让 30 天未被访问的镜像分层 / 旧版本自动删除,释放磁盘空间,同时不影响正在使用的镜像。

bash 复制代码
# 创建规则
cat > lifecycle.json << EOF
{
  "Rules": [
    {
      "ID": "harbor-30days-expire",
      "Status": "Enabled",
      "Prefix": "",
      "Expiration": { "Days": 30 }
    }
  ]
}
EOF

# 应用规则
mc ilm rule import myminio/harbor < lifecycle.json

# 查看规则
mc ilm rule list myminio/harbor
3.Harbor 内置垃圾回收 GC

MinIO 生命周期是删过期文件 ;Harbor 垃圾回收是清理镜像废弃分层、冗余垃圾,两个配合,磁盘空间彻底释放。

Harbor 删掉镜像后,镜像层文件还留在 MinIO 里 ,占空间不自动删;执行垃圾回收,清理没被任何镜像引用的冗余层,释放存储空间。

点击【模拟运行】会列出即将清理的文件

点击【立即清理垃圾

从日志可以看到真实删掉了:9 个镜像层 blob、1 个镜像清单 manifest,实际真正从 MinIO 后端 释放了 24MB

配置定时清理

cron格式参考:

执行时间 Cron 表达式
每天凌晨 3 点 0 3 * * *
每周六凌晨 3 点 0 3 * * 6
每月 1 号 凌晨 3 点执行 0 3 1 * *
4.K8s 配置 Harbor 私有镜像拉取

K8s 默认不能直接拉取 Harbor 私有镜像 ,会报ErrImagePull / ImagePullBackOff,接下来我们进行拉取配置

①操作所有 K8s 节点登录 Harbor
bash 复制代码
docker login harbor.xxxxx.com  #替换成你的harbor地址
②创建私有镜像拉取secret
bash 复制代码
kubectl create secret docker-registry harbor-secret \
  --docker-server=harbor.xxxxx.com \   #改成你的harbor仓库地址
  --docker-username=hyz \
  --docker-password='Hyz123!@#' \
  --docker-email=test@example.com
③配置拉取方式(2种)
  • 方式A:单个 YAML 手动指定(繁琐)

在 Pod/Deployment 模板里加:

yaml 复制代码
spec:
  imagePullSecrets:
  - name: harbor-secret
  • 方式B:设为命名空间默认密钥**(推荐)**

default 命名空间默认服务账号绑定拉取密钥:

bash 复制代码
kubectl patch serviceaccount default -p '{"imagePullSecrets": [{"name": "harbor-secret"}]}'

创建测试test.yaml 不配置 imagePullSecrets

yaml 复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  name: test-harbor2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: test-harbor2
  template:
    metadata:
      labels:
        app: test-harbor2
    spec:
      containers:
      - name: nginx
        image: harbor.xxxx.com/library/nginx:alpine  #填仓库镜像名称
        ports:
        - containerPort: 80

应用

bash 复制代码
kubectl appply -f test.yaml

应用后 Pod 状态直接变为 1/1 Running,代表配置全部生效

八、Harbor+LDAP统一认证

Harbor 接入 LDAP,实现统一身份认证,一套账号管理仓库、服务器等多系统,集中管控权限,符合企业运维规范。

LDAP服务器:OpenLDAP + phpLDAPadmin 可视化管理,部署在独立服务器 172.16.3.207

1.LDAP 服务部署(docker)
yml 复制代码
#核心配置(docker-compose.yml)
services:
  openldap:
    image: osixia/openldap:latest
    container_name: openldap
    restart: always
    ports:
      - "389:389"
    environment:
      LDAP_ORGANISATION: "HarborCorp"
      LDAP_DOMAIN: "harbor.local"
      LDAP_ADMIN_PASSWORD: "Admin@123"
    volumes:
      - /data/openldap:/var/lib/ldap
      - /data/openldap-config:/etc/ldap/slapd.d

  phpldapadmin:
    image: osixia/phpldapadmin:latest
    container_name: phpldapadmin
    restart: always
    ports:
      - "8088:80"
    environment:
      PHPLDAPADMIN_LDAP_HOSTS: openldap
      PHPLDAPADMIN_HTTPS: "false"
2.启动服务
bash 复制代码
docker compose up -d
3.访问管理页面
  • 地址:http://172.16.3.207:8088
  • 登录 DN:cn=admin,dc=harbor,dc=local
  • 密码:Admin@123
4.Harbor切换LDAP认证
①修改harbor.yml

新增以下内容,开启LDAP

bash 复制代码
auth_mode: ldap_auth

ldap:
  url: ldap://172.16.3.207:389
  search_dn: cn=admin,dc=harbor,dc=local
  search_password: Admin@123
  base_dn: dc=harbor,dc=local
  uid: cn
  scope: subtree
  verify_cert: false
②修改修改 PostgreSQL 认证模式(外部库必须执行)
bash 复制代码
# 进入PG Pod
kubectl exec -it -n harbor pg-harbor-0 -- bash

# 登录数据库
psql -U harbor -d registry

# 插入认证模式(无则插入,有则更新)
INSERT INTO properties (k, v) VALUES ('auth_mode', 'ldap_auth');

# 验证
SELECT * FROM properties WHERE k = 'auth_mode';
#预计返回以下内容
 id |     k     |     v
----+-----------+-----------
  3 | auth_mode | ldap_auth
(1 row)

#退出
\q
exit
③重启Harbor生效
bash 复制代码
./prepare
docker compose down
docker compose up -d
5.Harbor web界面配置LDAP参数
①进入 【配置管理】→ 【配置】→【认证模式】
②填写参数
配置项 注释
LDAP URL ldap://172.16.3.207:389 LDAP 服务器地址及端口(非加密连接)
LDAP 搜索 DN cn=admin,dc=harbor,dc=local 用于绑定并搜索 LDAP 目录的管理员账户 DN
搜索密码 Admin@123 上述管理员账户的密码
基础 DN dc=harbor,dc=local LDAP 搜索的起始点,所有用户在此路径下查找
过滤器 (objectClass=inetOrgPerson) 只筛选出对象类为 inetOrgPerson 的条目(通常代表人员账号)
用户 UID cn 使用 cn(通用名称)作为用户登录 ID 的属性映射
搜索范围 子树 从基础 DN 开始,递归搜索所有子目录
LDAP 检查证书 否(已取消勾选) 跳过 LDAP 服务端证书校验(仅用于测试或内网信任环境)
③测试连接

点击 【测试连接】 → 连通正常 → 保存

6.创建LDAP管理员用户(用于登录 Harbor)

登录LDAP管理后台 http://172.16.3.207:8088

①登录

DN: cn=admin,dc=harbor,dc=local

密码:Admin@123

②创建用于登录Harbor用户
  • 创建 Generic: Posix Group

左侧点击 dc=harbor,dc=local,点击 Create new entry here ,模板选择:Generic: Posix Group

填写信息:

配置项 注释
Group name users LDAP 中的用户组名称
GID Number 500 用户组的 GID 编号

点击 Create Object,组创建完成

  • 创建Generic: User Account

左侧点击 dc=harbor,dc=local,点击 Create new entry here ,模板选择:Generic: User Account

填写信息:

配置项 注释
First name harbor-admin
Last name harbor-admin
Common Name (cn) harbor-admin 登录用户名,不能包含空格
User ID harbor-admin 用户 ID,通常与 Common Name 保持一致
UID Number 1000 用户 UID 编号
GID Number users(500) 下拉选择,对应 users 组,GID 为 500
Home directory /home/users/harbor-admin 用户主目录路径
密码 admin123!@# 用户登录密码

点击 Create Object,用户创建完成

7.给 LDAP 用户授予 Harbor 系统管理员权限

LDAP 仅负责身份认证,权限由 Harbor 数据库控制

前往harbor web界面授权------【系统管理】------【用户管理】------找到【harbor-admin】------设置为管理员

相关推荐
W23035765731 小时前
Linux C++ 基于 timerfd + epoll 实现高性能定时器队列(完整源码 + 超详细解析)
linux·开发语言·c++·线程池
Lochor Lee1 小时前
C++学习笔记——输入输出的格式
c++·笔记·学习
wanhengidc1 小时前
云手机中虚拟技术的功能
运维·服务器·网络·安全·web安全·智能手机
小杍随笔1 小时前
【LiteAdmin(sql-admin)项目前后端架构深度分析】
数据库·sql·架构·rust
皓月盈江1 小时前
Linux Ubuntu系统使用Docker搭建vulhub靶场环境
linux·ubuntu·docker·tomcat·vulhub·漏洞靶场
小短腿的代码世界1 小时前
QGC固件升级与引导加载架构深度解析:从Bootloader握手到固件校验的完整流程
qt·性能优化·架构
念恒123061 小时前
Docker基础--namespace空间隔离实战(包含部分指令)
linux·运维·服务器
j7~1 小时前
【Linux】基础IO超万字解析(文件描述符)(2)
linux·运维·服务器·c++·file·重定向·文件描述
WangLanguager1 小时前
Linux命令adduser详细介绍
linux·运维·服务器