Harbor 实例部署

本文档介绍 Harbor Operator 的订阅及基于 Harbor 实例部署的功能。

目录

前提条件

  • 本文档适用于平台提供的 Harbor 2.12 及以上版本,基于 Operator 等技术实现与平台解耦。

  • 请确保目标集群已部署(订阅)Harbor Operator,即 Harbor Operator 已准备好创建实例。

部署规划

Harbor 支持多种资源配置以满足不同客户场景。不同场景下所需资源和配置差异较大,因此本节介绍部署 Harbor 实例前需要考虑的方面及决策点的影响,帮助用户基于此信息进行后续具体实例部署。

基本信息

  1. 平台提供的 Harbor Operator 基于社区官方 Harbor Operator,具备企业级能力增强,如 ARM 支持和安全漏洞修复,功能上与社区版本完全兼容,体验上通过可选和可定制模板提升 Harbor 部署便利性。

  2. 一个 Harbor 实例包含多个组件,如负责管理镜像文件的 Registry 组件,提供应用元数据和用户信息存储的 PostgreSQL 组件,以及用于缓存的 Redis 组件 等。平台提供专业的 PostgreSQL Operator 和 Redis Operator,部署 Harbor 实例时不再直接部署 Redis 和 PostgreSQL 资源,而是通过配置已有实例的访问凭证进行访问。

部署前资源规划

部署前资源规划指部署前需做出的决策,并在部署时生效,主要内容包括:

高可用

  • Harbor 支持高可用部署,主要影响和限制如下:

    • 各组件将使用多副本

    • 网络访问不再支持 NodePort,需通过 Ingress 配置的域名访问

    • 存储方式不再支持 节点存储,需通过 StorageClassPVC 访问

资源

根据社区建议和实践,非高可用 Harbor 实例最低可用资源为 2 核 CPU 和 4Gi 内存,高可用模式下稳定运行需至少 8 核 CPU 和 16Gi 内存。

存储

  • Harbor 可使用平台提供的常见存储方式,如存储类、持久卷声明(PVC)、节点存储等。

  • 节点存储不适用于 高可用 模式,因为其文件存储在宿主节点指定路径。

  • 此外,Harbor 还支持对象存储,该模式需单独适配存储访问方式,详情请咨询厂商。

网络

  • 平台提供两种主流网络访问方式:NodePortIngress

    • NodePort 需指定 HTTP 端口和 SSH 端口,且确保端口可用,不适用于 高可用 模式

    • Ingress 需指定域名,且确保域名解析正常

  • 平台支持 HTTPS 协议,需在实例部署后配置,详见 配置 HTTPS

Redis

PostgreSQL

  • 当前 Harbor 依赖的 PostgreSQL 组件版本为 v14,建议使用平台提供的 PostgreSQL Operator 部署 PostgreSQL 实例,再通过配置访问凭证完成 PostgreSQL 集成。

账号凭证

初始化 Harbor 实例时需配置管理员账号及密码,通过配置 secret 资源实现,详见 配置 Redis、PostgreSQL 及账号访问凭证

部署后配置规划

部署后配置规划指无需部署前决策,可通过规范化操作按需变更的规划,主要包括单点登录(SSO)、HTTPS 配置、外部负载均衡配置等,详情请参见 后续操作

实例部署

平台提供的 Harbor Operator 主要支持两种部署方式:模板部署和 YAML 部署。

平台内置两种模板供使用:Harbor 快速启动 模板和 Harbor 高可用 模板,同时支持自定义模板以满足特定客户场景。

内置模板及 YAML 部署信息如下:

使用 Harbor 快速启动 模板部署

该模板用于快速创建适合开发测试场景的轻量级 Harbor 实例,不建议用于生产环境。

  • 计算资源:CPU 2 核,内存 4Gi

  • 存储方式:使用本地节点存储,需配置存储节点 IP 和路径

  • 网络访问:使用 NodePort 方式,存储与节点 IP 共享,需指定端口

  • 依赖服务:需配置已有 Redis 和 PostgreSQL 访问凭证

  • 其他设置:需配置账号凭证,默认禁用 SSO 功能

根据模板提示填写相关信息完成部署。

使用 Harbor 高可用 模板部署

部署高可用 Harbor 实例需更高资源配置,提供更高可用标准。

  • 计算资源:CPU 16 核,内存 16Gi

  • 存储方式:使用存储类资源存储镜像文件、后台任务日志及镜像扫描漏洞数据库

  • 网络访问:使用 Ingress 方式,需指定域名

  • 依赖服务:需配置已有 Redis 和 PostgreSQL 访问凭证

  • 其他设置:需配置账号凭证,默认禁用 SSO 功能

实现 Harbor 高可用需满足以下外部依赖条件:

  1. RedisPostgreSQL 实例均为高可用

  2. 网络负载均衡器为高可用;使用 ALB 时需配置 VIP

  3. 集群节点数大于 2 个

根据模板提示填写相关信息完成部署。

使用 YAML 部署

YAML 部署是最基础且强大的部署能力。这里针对 部署规划 各维度提供对应的 YAML 片段,并提供两个完整场景的 YAML 示例,帮助用户理解 YAML 配置方式并按需修改配置。

基于部署规划的 YAML 片段

高可用

高可用模式下,Harbor 组件副本数应不少于 2,YAML 配置片段如下:

spec:
  helmValues:
    core:
      replicas: 2
    portal:
      replicas: 2
    jobservice:
      replicas: 2
    registry:
      replicas: 2
存储

Harbor 数据存储主要包括两部分:

  • Registry:管理和存储容器镜像及制品,负责镜像上传、下载和存储操作。

  • Jobservice:执行镜像间复制、垃圾回收及其他定时或按需后台任务。

  • Trivy:对容器镜像进行漏洞扫描,识别安全问题,确保安全策略合规。

目前支持三种存储配置方式:存储类、PVC 和本地节点存储。使用存储类或 PVC 时,存储必须支持多节点读写(ReadWriteMany)。

存储类配置片段:

spec:
  helmValues:
    persistence:
      enabled: true
      persistentVolumeClaim:
        registry:
          storageClass: ceph
          accessMode: ReadWriteMany
          size: 10Gi
        jobservice:
          jobLog:
            storageClass: ceph
            accessMode: ReadWriteMany
            size: 1Gi
        trivy:
          storageClass: ceph
          accessMode: ReadWriteMany
          size: 5Gi

PVC 配置片段(PVC 需提前创建):

spec:
  helmValues:
    harbor:
      persistence:
        enabled: true
        persistentVolumeClaim:
          registry:
            existingClaim: <registry 组件 pvc>
          jobservice:
            jobLog:
              existingClaim: <jobservice 组件 pvc>
          trivy:
            existingClaim: <trivy 组件 pvc>

本地节点存储配置片段:

spec:
  helmValues:
    persistence:
      enabled: true
      hostPath:
        registry:
          path: <registry 组件节点存储路径>
        jobservice:
          path: <jobservice 组件节点存储路径>
        trivy:
          path: <trivy 组件节点存储路径>
    registry:
      nodeSelector:
        kubernetes.io/hostname: <节点名称>
    jobservice:
      nodeSelector:
        kubernetes.io/hostname: <节点名称>
    trivy:
      nodeSelector:
        kubernetes.io/hostname: <节点名称>
    
网络访问

网络访问主要包括两种方式:域名访问和 NodePort 访问。

域名访问配置片段:

spec:
  helmValues:
    expose:
      type: ingress
      tls:
        enabled: false
      ingress:
        hosts:
          core: <域名>
    
    externalURL: http://<域名>

NodePort 访问配置片段:

spec:
  helmValues:
    expose:
      type: nodePort
      nodePort:
        name: harbor
        ports:
          http:
            port: 80
            nodePort: <端口号>
    
    externalURL: http://<节点 IP>:<端口号>
Redis 访问凭证配置

指在配置 Redis 凭证 secret 资源后,在 Harbor 实例中配置这些凭证的片段:

独立实例示例:

spec:
  helmValues:
    database:    
    redis:
      external:
        addr: "<redis 访问地址>:<redis 端口>"
        existingSecret: <存储 redis 密码的 secret>
        existingSecretKey: password
      type: external

Sentinel 示例:

spec:
  helmValues:
    database:    
    redis:
      external:
        addr: "<sentinel1 访问地址>:<sentinel1 端口>,<sentinel2 访问地址>:<sentinel2 端口>,<sentinel3 访问地址>:<sentinel3 端口>"
        sentinelMasterSet: mymaster
        existingSecret: <存储 redis 密码的 secret>
        existingSecretKey: password
      type: external
PostgreSQL 访问凭证配置

指在配置 PostgreSQL 凭证 secret 资源后,在 Harbor 实例中配置这些凭证的片段:

spec:
  helmValues:
    database:
      external:
        host: <postgresql 访问地址>
        port: <postgresql 端口>
        sslmode: <是否启用 ssl>
        username: <postgresql 用户名>
        coreDatabase: <数据库名>
        existingSecret: <存储 postgresql 密码的 secret>
      type: external
管理员账号配置

指在配置账号凭证 secret 资源后,在 Harbor 实例中配置这些凭证的片段:

spec:
  helmValues:
    existingSecretAdminPassword: <存储 harbor 管理员密码的 secret>
    existingSecretAdminPasswordKey: password

完整 YAML 示例:单实例,节点存储,NodePort 网络访问


spec:
  helmValues:
    existingSecretAdminPassword: harbor-password # 存储 harbor 管理员账号密码的 Secret
    existingSecretAdminPasswordKey: password # 存储 harbor 管理员账号密码的 Secret key
    externalURL: http://192.168.142.11:32001 # Harbor 访问地址
    expose:
      nodePort:
        name: harbor
        ports:
          http:
            nodePort: 32001 # Harbor 节点端口号
            port: 80
      type: nodePort
    persistence:
      enabled: true
      hostPath:
        jobservice:
          path: /data/harbor/jobservice # Jobservice 组件节点存储路径
        registry:
          path: /data/harbor/registry # Registry 组件节点存储路径
        trivy:
          path: /data/harbor/trivy # Trivy 组件节点存储路径
    portal:
      resources:
        request:
          cpu: 100m
          memory: 128Mi
        limit:
          cpu: 200m
          memory: 256Mi
    nginx:
      resources:
        request:
          cpu: 100m
          memory: 128Mi
        limit:
          cpu: 200m
          memory: 256Mi
    core:
      resources:
        request:
          cpu: 200m
          memory: 256Mi
        limit:
          cpu: 400m
          memory: 512Mi
    registry:
      nodeSelector:
        kubernetes.io/hostname: 192.168.142.11 # Registry 组件节点选择器
      resources:
        request:
          cpu: 200m
          memory: 512Mi
        limit:
          cpu: 400m
          memory: 1Gi
    jobservice:
      nodeSelector:
        kubernetes.io/hostname: 192.168.142.11 # Jobservice 组件节点选择器
      resources:
        request:
          cpu: 200m
          memory: 256Mi
        limit:
          cpu: 400m
          memory: 512Mi
    trivy:
      skipUpdate: true
      offlineScan: true
      nodeSelector:
        kubernetes.io/hostname: 192.168.142.11 # Trivy 组件节点选择器
      resources:
        request:
          cpu: 200m
          memory: 512Mi
        limit:
          cpu: 400m
          memory: 1Gi
    database:
      external:
        host: harbor-database # 数据库访问地址
        port: 5432 # 数据库端口号
        sslmode: require # 是否启用 SSL
        username: harbor # 数据库用户名
        coreDatabase: registry # 数据库名
        existingSecret: harbor-database # 存储数据库密码的 Secret
        existingSecretKey: password # 存储数据库密码的 Secret key
      type: external
    redis:
      external:
        addr: harbor-redis:6379 # Redis 访问地址及端口号
        existingSecret: harbor-redis # 存储 Redis 密码的 Secret
        existingSecretKey: password # 存储 Redis 密码的 Secret key
      type: external

完整 YAML 示例:高可用,存储类,Ingress 网络访问

spec:
  helmValues:
    existingSecretAdminPassword: harbor-password # 存储 harbor 管理员账号密码的 Secret
    existingSecretAdminPasswordKey: password # 存储 harbor 管理员账号密码的 Secret key
    externalURL: http://harbor.example.com # Harbor 访问地址
    expose:
      type: ingress
      tls:
        enabled: false
      ingress:
        hosts:
          core: harbor.example.com # Harbor 域名
    persistence:
      enabled: true
      persistentVolumeClaim:
        registry:
          storageClass: ceph # Registry 组件存储类
          accessMode: ReadWriteMany 
          size: 10Gi # Registry 组件存储大小
        jobservice:
          jobLog:
            storageClass: ceph # Jobservice 组件存储类
            accessMode: ReadWriteMany
            size: 1Gi # Jobservice 组件存储大小
        trivy:
          storageClass: ceph # Trivy 组件存储类
          accessMode: ReadWriteMany
          size: 5Gi # Trivy 组件存储大小
    portal:
      replicas: 2 # Portal 组件副本数
      resources:
        request:
          cpu: 200m
          memory: 256Mi
        limit:
          cpu: 400m
          memory: 512Mi
    core:
      replicas: 2 # Core 组件副本数
      resources:
        request:
          cpu: 200m
          memory: 256Mi
        limit:
          cpu: 400m
          memory: 512Mi
    registry:
      replicas: 2 # Registry 组件副本数
      resources:
        request:
          cpu: 400m
          memory: 1Gi
        limit:
          cpu: 800m
          memory: 2Gi
    jobservice:
      replicas: 2 # Jobservice 组件副本数
      resources:
        request:
          cpu: 200m
          memory: 256Mi
        limit:
          cpu: 400m
          memory: 512Mi
    trivy:
      skipUpdate: true
      offlineScan: true
      resources:
        request:
          cpu: 400m
          memory: 1Gi
        limit:
          cpu: 800m
          memory: 2Gi
    database:
      external:
        host: harbor-database # 数据库访问地址
        port: 5432 # 数据库端口号
        sslmode: require # 是否启用 SSL
        username: harbor # 数据库用户名
        coreDatabase: registry # 数据库名
        existingSecret: harbor-database # 存储数据库密码的 Secret
        existingSecretKey: password # 存储数据库密码的 Secret key
      type: external
    redis:
      external:
        addr: harbor-redis:6379 # Redis 访问地址及端口号
        existingSecret: harbor-redis # 存储 Redis 密码的 Secret
        existingSecretKey: password # 存储 Redis 密码的 Secret key
      type: external

后续操作

配置单点登录(SSO)

配置 SSO 包括以下步骤:

  1. 在 global 集群注册 SSO 认证客户端

  2. 准备 SSO 认证配置

  3. 配置 Harbor 实例使用 SSO 认证

在 global 集群创建如下 OAuth2Client 资源以注册 SSO 认证客户端:

apiVersion: dex.coreos.com/v1
kind: OAuth2Client
name: OIDC
metadata:
  name: m5uxi3dbmiwwizlyzpzjzzeeeirsk # 此值基于 id 字段的哈希计算,在线计算器:https://go.dev/play/p/QsoqUohsKok
  namespace: cpaas-system
alignPasswordDB: true
id: harbor-dex # 客户端 id
public: false
redirectURIs:
  - <harbor 访问地址>/c/oidc/callback
secret: Z2l0bGFiLW9mZmljaWFsLTAK # 客户端密钥
spec: {}

编辑 Harbor 实例,添加如下配置:

spec:
  helmValues:
    oidc:
      enable: true
      clientID: "harbor-dex"
      clientSecret: "Z2l0bGFiLW9mZmljaWFsLTAK"
      issuer: "<平台访问地址>/dex"

配置 HTTPS

部署 Harbor 实例后,可根据需要配置 HTTPS。

首先在实例所在命名空间创建 TLS 证书 Secret:

apiVersion: v1
kind: Secret
metadata:
  name: harbor-tls-cert
  namespace: harbor
type: kubernetes.io/tls
data:
  tls.crt: <base64 编码的证书>
  tls.key: <base64 编码的密钥>

然后编辑 Harbor 实例 YAML 配置,启用 HTTPS 访问:

expose:
  type: ingress
  tls:
    enabled: true
    certSource: secret
    secret:
      secretName: harbor-tls-cert
  ingress:
    hosts:
      core: <域名>

externalURL: https://<域名>

配置镜像扫描漏洞数据库策略

Harbor 的镜像扫描功能由 Trivy 组件实现。考虑用户网络环境,该组件默认使用内置离线漏洞数据库,因漏洞库不更新,无法及时发现新漏洞。

若需保持漏洞库更新,可编辑 Harbor 实例 YAML 配置,启用在线更新策略(该策略需访问 GitHub):

trivy:
  skipUpdate: false
  offlineScan: false

启用在线更新策略后,Trivy 会根据上次更新时间决定扫描前是否更新漏洞库。因下载漏洞库耗时,若不需要 Java 漏洞扫描,也可编辑 Harbor 实例 YAML 配置,禁用 Java 漏洞库更新:

trivy:
  skipJavaDBUpdate: true

其他信息

IPv6 环境下部署 Harbor

Harbor 支持 IPv6 环境部署,但需确保客户端工具版本支持 IPv6。如遇 invalid reference format 错误,请检查客户端工具版本是否支持 IPv6。

相关社区问题:

Pod 安全策略

在配置了 Pod 安全策略(PSP)的命名空间部署 Harbor,支持情况如下:

  • StorageClass 和 PVC:支持 enforce 级别为 privilegedbaseline 的部署。

  • 本地节点存储:仅支持 enforce 级别为 privileged 的部署。