一、环境清单
1、集群基础信息
|
|
|
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2、节点信息总览
|
|
|
|
|
|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3、 Ceph 分布式存储(Harbor 镜像存储专用)
|
|
|
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4、业务资源
4.1 数据库机器基础信息表
|
|
|
|
|
|
|---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|---|---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4.2 数据库访问方式表
|
|
|
|
|
|
|
|---|---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4.3 Ingress-Nginx 集群入口
4.3.1 基础配置
|
|
|
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
4.3.2 服务与工作负载
|
|
|
|
|
|
|
|---|---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4.3.3 访问入口
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
5、Ceph 集群详细配置
5.1 软件版本与安装
|
|
|
|
|
|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5.2 核心组件配置
|
|
|
|
|
|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5.3 存储池配置
|
|
|
|
|
|
|---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
二、部署前准备工作
1. 环境依赖校验
# 1. 检查 K8s 集群状态(确保节点 Ready、核心组件正常)kubectl get nodeskubectl get pods -n kube-systemkubectl get pods -n ingress-nginx # 确认 Ingress 控制器运行############################################################################################################# 2. 检查 PostgreSQL 可用性以及数据库psql -h 10.132.47.65 -U postgres -d postgres# 执行后输入以下 SQL 验证,能返回结果则正常\lexit#示例[root@localhost ~]# psql -h 10.132.47.65 -U postgres -d postgres用户 postgres 的口令:psql (9.2.24, 服务器 15.14)警告:psql 版本9.2, 服务器版本15.0.一些psql功能可能无法工作.输入 "help" 来获取帮助信息.postgres=# \l资料库列表名称 | 拥有者 | 字元编码 | 校对规则 | Ctype | 存取权限----------------------+----------+----------+-------------+-------------+-----------------------harbor_core | postgres | UTF8 | zh_CN.UTF-8 | zh_CN.UTF-8 |harbor_notary_server | postgres | UTF8 | zh_CN.UTF-8 | zh_CN.UTF-8 |harbor_notary_signer | postgres | UTF8 | zh_CN.UTF-8 | zh_CN.UTF-8 |postgres | postgres | UTF8 | zh_CN.UTF-8 | zh_CN.UTF-8 |template0 | postgres | UTF8 | zh_CN.UTF-8 | zh_CN.UTF-8 | =c/postgres +| | | | | postgres=CTc/postgrestemplate1 | postgres | UTF8 | zh_CN.UTF-8 | zh_CN.UTF-8 | =c/postgres +| | | | | postgres=CTc/postgres(6 行记录)############################################################################################################# 3. 检查 Redis 集群可用性(测试连接)redis-cli -h 10.132.47.65 -p 6379 -a Shyshy521521! -c# 执行后输入以下命令,返回 PONG 则正常pingexit#示例[root@localhost ~]# redis-cli -h 10.132.47.65 -p 6379 -a Shyshy521521! -c10.132.47.65:6379> pingPONG10.132.47.65:6379> exit#############################################################################################################检查[root@k8s-master harbor]# kubectl get nodesNAME STATUS ROLES AGE VERSIONk8s-master Ready control-plane,master 10d v1.23.0k8s-node1 Ready <none> 10d v1.23.0k8s-node2 Ready <none> 10d v1.23.0k8s-node3 Ready <none> 10d v1.23.0[root@k8s-master harbor]# kubectl get pods -n kube-systemNAME READY STATUS RESTARTS AGEcalico-kube-controllers-5bb5d4f7f4-ldx68 1/1 Running 1 (9d ago) 10dcalico-node-4c4wz 1/1 Running 1 (8d ago) 10dcalico-node-mc6xn 1/1 Running 1 (8d ago) 10dcalico-node-mhck8 1/1 Running 1 (9d ago) 10dcalico-node-nk77r 1/1 Running 1 (8d ago) 10dcoredns-6d8c4cb4d-76fkb 1/1 Running 1 (9d ago) 10dcoredns-6d8c4cb4d-b4wwq 1/1 Running 1 (9d ago) 10detcd-k8s-master 1/1 Running 1 (9d ago) 10dkube-apiserver-k8s-master 1/1 Running 1 (9d ago) 10dkube-controller-manager-k8s-master 1/1 Running 1 (9d ago) 10dkube-proxy-474gq 1/1 Running 1 (8d ago) 10dkube-proxy-g8sfp 1/1 Running 1 (8d ago) 10dkube-proxy-rgrn7 1/1 Running 1 (9d ago) 10dkube-proxy-tjmh5 1/1 Running 1 (8d ago) 10dkube-scheduler-k8s-master 1/1 Running 1 (9d ago) 10dmetrics-server-8f68868ff-nwjrx 1/1 Running 1 (8d ago) 10dnfs-client-provisioner-5bfb45b7b8-9gbbn 1/1 Running 0 3d[root@k8s-master harbor]# kubectl get pods -n ingress-nginxNAME READY STATUS RESTARTS AGEnginx-ingress-ingress-nginx-controller-f5664cdf7-9tckg 1/1 Running 0 57m############################################################################################################
2. 检查 Ceph RGW 可用性(测试 S3 连接)
2.1 安装 awscli(用于测试 S3)
yum install -y awscli
2.2 查看 Ceph RGW 已创建的用户
#登录任意 Ceph 节点(如 ceph-1:10.132.47.68),执行以下命令列出所有 RGW 用户:radosgw-admin user list#输出示例(包含你创建的 harbor-user 用户):["harbor-user"]
2.3. 如果没有:
创建 RGW 专用存储池与用户
# 用ceph-deploy部署RGW# 在部署节点执行ceph-deploy rgw create ceph-1 ceph-2 ceph-3# 部署完成后,验证RGW服务# 查看RGW进程ssh ceph-1 "ps -ef | grep radosgw"# 查看RGW端口(默认7480)ssh ceph-1 "netstat -ntlp | grep 7480"# 创建基础用户(仅包含uid、display-name、email)radosgw-admin user create \--uid=Harbor_rgw \--display-name="RGW Super Administrator" \--email=Harbor_rgw@example.com# 1. 添加用户管理全权限(创建/删除其他用户)radosgw-admin caps add --uid=Harbor_rgw --caps="users=*"# 2. 添加桶管理全权限(创建/删除/修改所有桶)radosgw-admin caps add --uid=Harbor_rgw --caps="buckets=*"# 3. 添加对象操作全权限(读写/删除所有桶内对象)radosgw-admin caps add --uid=Harbor_rgw --caps="objects=*"# 4. 添加元数据操作全权限(修改所有对象元数据)radosgw-admin caps add --uid=Harbor_rgw --caps="metadata=*"# 5. (已添加,可选验证)确认usage权限radosgw-admin caps add --uid=Harbor_rgw --caps="usage=*"# 查看用户信息(关键:获取Access Key和Secret Key,用于客户端连接)radosgw-admin user info --uid=Harbor_rgw
执行后会输出用户的access_key和secret_key,务必保存好,后续配置 Harbor 会用到。
2.5 验证用户创建成功
# 再次列出 RGW 用户,确认 harbor-user 已存在radosgw-admin user list# 输出示例:["harbor-user"]# 查看用户详细信息(若之前没记全密钥,可重新查询)radosgw-admin user info --uid=harbor-user
vim /etc/ceph/ceph.conf
在[client.rgw.<你的rgw实例名>]段(如[client.rgw.ceph-1])添加以下配置:
-
若不知道 rgw实例名,可执行ceph -s或systemctl list-units | grep rgw查看(如ceph-radosgw@rgw.ceph-1.service中的ceph-1)。
[client.rgw.ceph-1]# 强制开启S3路径风格访问(关键,解决Registry的路径解析问题)rgw_s3_enable_path_style = true# 强制使用S3 V4签名(与Registry的signature_version: s3v4匹配)rgw_signature_version = s3v4# 关闭虚拟主机风格访问(避免冲突)rgw_dns_name =# 允许跨桶的路径访问rgw_allow_multiple_buckets_in_request = true
配置 S3 客户端
aws configure set aws_access_key_id 你的_harbor_rgw_access_keyaws configure set aws_secret_access_key 你的_harbor_rgw_secret_keyaws configure set default.s3.signature_version s3v4aws configure set aws_access_key_id HARBOR123456789aws configure set aws_secret_access_key HarborSecretKey123456789aws configure set default.s3.signature_version s3v4aws s3 ls --endpoint-url http://10.132.47.68:7480aws s3 mb s3://harbor-image-storage --endpoint-url http://10.132.47.68:7480aws s3 ls --endpoint-url http://10.132.47.68:7480[][]make_bucket: harbor-image-storage[]2025-11-14 11:13:22 harbor-image-storage
测试列出存储桶
aws s3 ls --endpoint-url http://10.132.47.68:7480
3. 创建 Harbor 专用命名空间
kubectl create namespace harbor# 验证命名空间创建成功kubectl get namespaces | grep harbor#示例[root@k8s-master harbor-helm-1.8.3]# kubectl get namespaces | grep harborharbor Active 9s
4. 下载 Harbor Helm Chart 包
# 创建 Chart 存储目录mkdir -p /root/k8s-yaml/harbor && cd /root/k8s-yaml/harbor# 添 Harbor 官方 Helm 仓库(若无法访问可替换为国内镜像)helm repo add harbor https://helm.goharbor.iohelm repo update#若失败,直接下载wget --no-check-certificate https://ghproxy.com/https://github.com/goharbor/harbor-helm/releases/download/v1.7.0/harbor-1.7.0.tgz -O harbor-1.7.0.tgz#官网下载zip文件https://github.com/goharbor/harbor-helm/tree/v1.7.0# 解压 ZIP 包(需安装 unzip,若未安装先执行:yum install -y unzip)unzip harbor-helm-1.7.0.zip# 进入解压后的目录(目录名应为 harbor-helm-1.8.3)cd harbor-helm-1.7.0# 检查是否包含部署必需文件ls -l values.yaml Chart.yaml templates/# 预期输出:# -rw-r--r-- 1 root root xxxx values.yaml # 配置文件# -rw-r--r-- 1 root root xxxx Chart.yaml # Chart 元数据# drwxr-xr-x 2 root root xxxx templates/ # 部署模板目录# 下载指定版本的 Chart 包helm pull harbor/harbor --version 1.7.0tar -zxvf harbor-1.7.0.tgz # 解压 Chart 包cd harbor # 进入 Chart 目录(后续修改 values.yaml 在此目录)
二、核心配置文件修改(values.yaml)
进入 Chart 解压后的 harbor 目录,编辑 values.yaml,按以下关键配置修改(其余默认,注释说明修改原因):
1. 全局基础配置
# 1. 管理员密码(自定义,建议复杂度高)harborAdminPassword: "Shyshy521521!"# 2. 外部访问 URL(对应 /etc/hosts 配置的域名)externalURL: https://harbor.example.com# 3. 镜像拉取策略(复用现有环境配置)imagePullPolicy: IfNotPresent
2. 关闭内部依赖,使用外部PostgreSQL
# 数据库配置:控制 Harbor 元数据存储的数据库来源(内部或外部)database:# 数据库类型:# - "internal":使用 Harbor 内置的 PostgreSQL 数据库(默认)# - "external":使用外部数据库(此处配置为外部,需填写下方 external section)type: external# 内部数据库(PostgreSQL)配置(当 type=internal 时生效,当前禁用)internal:# 服务账户配置:指定运行数据库 Pod 的 ServiceAccount(留空则使用默认)serviceAccountName: ""# 是否自动挂载服务账户令牌(用于访问集群内其他资源,默认关闭)automountServiceAccountToken: false# 内部数据库镜像信息image:repository: goharbor/harbor-db # 镜像仓库tag: v2.4.3 # 镜像版本(需与 Harbor 版本兼容)# 内部数据库初始超级用户密码(首次启动时生效,生产需修改)password: "changeit"# 共享内存大小限制:PostgreSQL 用于 shared_buffer(共享缓冲区)# 详情参考:https://github.com/goharbor/harbor/issues/15034shmSizeLimit: 512Mi# 资源限制配置(默认未设置,生产建议根据需求添加)# resources:# requests:# memory: 256Mi # 最小内存请求# cpu: 100m # 最小 CPU 请求# 节点选择器:指定数据库 Pod 调度到哪些节点(默认无限制)nodeSelector: {}# 污点容忍:允许数据库 Pod 调度到带有指定污点的节点tolerations: []# 亲和性规则:控制 Pod 与节点/其他 Pod 的调度关系affinity: {}# 优先级类:指定 Pod 的调度优先级(默认不设置)priorityClassName:# 初始化容器配置(数据库初始化、权限设置等)initContainer:migrator: {} # 数据库迁移容器(用于版本升级时的数据迁移)# 迁移容器资源配置(默认未设置)# resources:# requests:# memory: 128Mi# cpu: 100mpermissions: {} # 权限设置容器(用于调整存储目录权限)# 权限容器资源配置(默认未设置)# resources:# requests:# memory: 128Mi# cpu: 100m# 外部数据库配置(当 type=external 时生效,当前启用)external:host: "10.132.47.65" # 外部数据库地址port: "5432" # 数据库端口(PostgreSQL 默认 5432)username: "postgres" # 访问数据库的用户名(需具备创建数据库的权限)password: "Shyshy521521!" # 用户名对应的密码(生产环境建议使用 Secret 存储)# Harbor 各组件使用的数据库名(需提前创建或确保用户有权限创建)coreDatabase: "harbor_core" # 核心服务(core)数据库notaryServerDatabase: "harbor_notary_server" # 镜像签名服务(notary-server)数据库notarySignerDatabase: "harbor_notary_signer" # 签名验证服务(notary-signer)数据库# SSL 连接模式(控制数据库通信加密):# - "disable":不使用 SSL(明文传输,适合集群内部信任网络)# - "require":强制使用 SSL,但不验证证书有效性# - "verify-ca":强制使用 SSL,且验证证书由可信 CA 签发# - "verify-full":强制使用 SSL,验证 CA 且证书主机名匹配sslmode: "disable" # 当前禁用 SSL(根据实际安全需求调整)# 补充内部数据库开关(显式禁用内置数据库,与 type=external 配合)internal:enabled: false # 禁用内置 PostgreSQL(必须设为 false,否则与外部数据库冲突)# 数据库连接池配置(控制每个 Pod 对数据库的连接数)# 空闲连接池最大连接数(每个 Pod:core 服务 + exporter 组件)# 若 <=0,则不保留空闲连接maxIdleConns: 100# 最大打开连接数(每个 Pod:core 服务 + exporter 组件)# 若 <=0,则无限制(注意:PostgreSQL 默认最大连接数为 1024,需合理分配)maxOpenConns: 900# 数据库相关 Pod 的额外注解(可添加监控、日志等注解)podAnnotations: {}
3. 关闭内部依赖,复用外部 Redis 集群
# Redis 配置:控制 Harbor 缓存及临时数据存储的 Redis 来源(内部或外部)redis:# Redis 类型:# - "internal":使用 Harbor 内置的 Redis(默认)# - "external":使用外部 Redis(此处配置为外部,需填写下方 external 部分)type: external# 内部 Redis 配置(当 type=internal 时生效,当前禁用)internal:# 服务账户配置:指定运行 Redis Pod 的 ServiceAccount(留空则使用默认)serviceAccountName: ""# 是否自动挂载服务账户令牌(用于访问集群内其他资源,默认关闭)automountServiceAccountToken: false# 内部 Redis 镜像信息image:repository: goharbor/redis-photon # 镜像仓库tag: v2.4.3 # 镜像版本(需与 Harbor 版本兼容)# 资源限制配置(默认未设置,生产建议根据需求添加)# resources:# requests:# memory: 256Mi # 最小内存请求# cpu: 100m # 最小 CPU 请求# 节点选择器:指定 Redis Pod 调度到哪些节点(默认无限制)nodeSelector: {}# 污点容忍:允许 Redis Pod 调度到带有指定污点的节点tolerations: []# 亲和性规则:控制 Pod 与节点/其他 Pod 的调度关系affinity: {}# 优先级类:指定 Pod 的调度优先级(默认不设置)priorityClassName:# 外部 Redis 配置(当 type=external 时生效,当前启用)external:# Redis 地址:# - 单节点 Redis:格式为 <主机>:<端口># - Redis 集群(无哨兵):若需指定多个节点,用逗号分隔(如 "node1:6379,node2:6379")# - Redis+哨兵模式:填写哨兵节点地址(如 "sentinel1:26379,sentinel2:26379")# 此处为 K8s 内 Redis 集群的 Service 地址(格式:服务名.命名空间.svc.cluster.local:端口)addr: "10.132.47.65:6379""# 哨兵主节点集名称:仅 Redis+哨兵模式需要填写(指定监控的主节点名称)# 无哨兵模式下留空(当前为无哨兵集群,故不配置)sentinelMasterSet: ""# 各组件使用的 Redis 数据库索引(Redis 支持多数据库,通过索引隔离数据)coreDatabaseIndex: "0" # 核心服务(core)使用的数据库索引(必须为 0,Harbor 库不支持自定义)jobserviceDatabaseIndex: "1" # 任务服务(jobservice)使用的数据库索引registryDatabaseIndex: "2" # 镜像仓库(registry)使用的数据库索引chartmuseumDatabaseIndex: "3" # 图表仓库(chartmuseum)使用的数据库索引trivyAdapterIndex: "5" # 漏洞扫描(trivy)适配器使用的数据库索引# Redis 相关 Pod 的额外注解(可添加监控、日志等注解)podAnnotations: {}
4. 存储配置:使用 Ceph RGW
# 持久化存储配置:控制 Harbor 各组件的数据持久化方式persistence:enabled: true # 启用持久化存储(生产环境必须开启,否则数据会随 Pod 销毁丢失)# 资源保留策略:删除 Helm 释放时的 PVC 处理规则# - 设为 "keep":保留 PVC,避免误删数据(推荐生产环境使用)# - 留空:删除 Helm 图表后自动删除 PVC(不推荐)# 注意:内置数据库(PostgreSQL)和 Redis 的 PVC 永远不会自动删除,此配置仅作用于其他组件resourcePolicy: "keep"# 各组件的 PersistentVolumeClaim(PVC)配置:为每个核心组件单独分配存储persistentVolumeClaim:# 镜像仓库(registry)组件的 PVC 配置:存储上传的镜像数据registry:existingClaim: "nfs-storage" # 使用已存在的 PVC(需手动提前创建,此处未使用)storageClass: "" # 存储类名称(使用 NFS 存储,需集群已创建该存储类)subPath: "" # PVC 子路径(若 PVC 被多组件共享时指定,此处单独使用留空)accessMode: ReadWriteOnce # 访问模式:单节点读写(NFS 支持该模式)size: 50Gi # 存储容量:根据实际镜像存储需求调整(生产建议至少 100Gi+)# 图表仓库(chartmuseum)组件的 PVC 配置:存储 Helm 图表数据chartmuseum:existingClaim: ""storageClass: "nfs-storage" # 同样使用 NFS 存储类subPath: ""accessMode: ReadWriteOncesize: 5Gi # 图表存储容量:根据 Helm 图表数量调整# 任务服务(jobservice)组件的 PVC 配置:存储任务日志、临时文件(如镜像扫描结果)jobservice:existingClaim: ""storageClass: "nfs-storage"subPath: ""accessMode: ReadWriteOncesize: 1Gi # 任务日志容量:一般 1-5Gi 足够# 数据库(database)组件的 PVC 配置:存储 Harbor 元数据(如项目、用户、权限)# 注意:若已配置外部数据库(如之前的外部 PostgreSQL),此配置会被忽略database:existingClaim: ""storageClass: "" # 数据库专用存储类(单独配置,优化性能)subPath: ""accessMode: ReadWriteMany # 访问模式:多节点读写(适配数据库主从或集群场景)size: 1Gi # 数据库容量:根据元数据量调整(生产建议 10Gi+)# Redis 组件的 PVC 配置:存储 Redis 缓存数据# 注意:若已配置外部 Redis 集群,此配置会被忽略redis:existingClaim: ""storageClass: ""subPath: ""accessMode: ReadWriteOncesize: 1Gi # Redis 缓存容量:一般 1-5Gi 足够# 漏洞扫描(trivy)组件的 PVC 配置:存储漏洞数据库、扫描缓存trivy:existingClaim: ""storageClass: "nfs-storage"subPath: ""accessMode: ReadWriteOncesize: 5Gi # Trivy 漏洞库容量:漏洞库较大,建议 5-20Gi# 镜像和图表的存储后端配置:指定 registry(镜像)和 chartmuseum(图表)的数据存储方式# 参考文档:https://github.com/docker/distribution/blob/master/docs/configuration.md#storageimageChartStorage:# 禁用存储重定向:部分存储后端(如 MinIO S3)不支持重定向,需设为 true# 启用重定向时,客户端直接与存储后端交互(提升传输效率),默认禁用(false)disableredirect: true# CA 证书秘钥名称:若存储服务使用自签名证书,需指定包含 "ca.crt" 的 Secret 名称# 用于注入到 registry 和 chartmuseum 容器的信任证书库# caBundleSecretName: ""# 存储类型:支持 filesystem(文件系统)、azure、gcs、s3、swift、oss# 注意:若使用 PVC 持久化(上面的 persistentVolumeClaim 配置),需设为 filesystem# 此处配置为 s3,说明镜像/图表直接存储到 S3 兼容存储(而非 PVC)type: s3# 文件系统存储配置(当 type=filesystem 时生效)filesystem:rootdirectory: /storage # 存储根目录(与 PVC 挂载路径对应)# maxthreads: 100 # 最大并发线程数(默认不限制)# Azure Blob 存储配置(当 type=azure 时生效,此处未使用)azure:accountname: accountname # Azure 存储账户名accountkey: base64encodedaccountkey # Base64 编码的账户密钥container: containername # 存储容器名称# realm: core.windows.net # Azure 域名(默认无需修改)# Google Cloud Storage 配置(当 type=gcs 时生效,此处未使用)gcs:bucket: bucketname # GCS 存储桶名称encodedkey: base64-encoded-json-key-file # Base64 编码的密钥文件内容# rootdirectory: /gcs/object/name/prefix # 存储前缀(用于隔离数据)# chunksize: "5242880" # 分片上传大小(默认 5MB)# S3 兼容存储配置(当 type=s3 时生效,此处使用 Ceph RGW 作为 S3 存储)s3:region: default # 区域(Ceph RGW 默认为 default)bucket: harbor-image-storage # 自动创建的桶名称accesskey: CM3YBZV8Y55A9QWHNC0E # Ceph RGW 访问密钥(AK)secretkey: cuDoZN1jumZaV0eoUPYSi31kk585IIXsgc5AfmBq # Ceph RGW 密钥(SK)regionendpoint: http://10.132.47.68:7480 # Ceph RGW 访问地址(节点 IP + 7480 端口)secure: false # 是否启用 SSL(Ceph RGW 未配置 HTTPS,设为 false)v4auth: true # 启用 S3 v4 认证(Ceph RGW 支持,必须开启)rootdirectory: /harbor # 存储桶内根目录(用于隔离 Harbor 数据)forcepathstyle: true # 绕开域名解析signature_version: "s3v4" # 明确V4签名encrypt: false # 测试环境禁用加密,生产可按需开启pathstyle: true # 必须为 true,兼容 RGW# accesskey: awsaccesskey # AWS S3 访问密钥(兼容 AWS 时使用)# secretkey: awssecretkey # AWS S3 密钥# regionendpoint: http://myobjects.local # AWS S3 终端地址# encrypt: false # 是否加密存储(默认不加密)# keyid: mykeyid # 加密密钥 ID(启用加密时填写)# skipverify: false # 是否跳过 SSL 证书验证(默认不跳过)chunksize: "5242880" # 分片上传大小(默认 5MB)#storageclass: STANDARD # S3 存储类别(默认标准存储)# Swift 存储配置(当 type=swift 时生效,此处未使用)swift:authurl: https://storage.myprovider.com/v3/auth # Swift 认证地址username: username # 用户名password: password # 密码container: containername # 存储容器名称# region: fr # 区域(根据实际环境填写)# tenant: tenantname # 租户名称(OpenStack 环境需填写)# 阿里云 OSS 存储配置(当 type=oss 时生效,此处未使用)oss:accesskeyid: accesskeyid # OSS 访问密钥 IDaccesskeysecret: accesskeysecret # OSS 访问密钥 Secretregion: regionname # OSS 区域(如 cn-hangzhou)bucket: bucketname # OSS 存储桶名称# endpoint: endpoint # 自定义 OSS 终端地址(默认无需修改)
5. 网络暴露配置:Ingress
查看集群中可用的 IngressClass
kubectl get ingressclasseskubectl get svc -n ingress-nginxkubectl get pod -n ingress-nginxhelm ls -n ingress-nginxkubectl get ingressclasses 输出,集群中有效的 IngressClass 名称是 nginx(控制器为 k8s.io/ingress-nginx)
# 服务暴露配置:控制 Harbor 如何通过 Kubernetes 对外提供服务expose:# 暴露类型:使用 Ingress(需提前部署 Ingress Controller,如 Nginx Ingress)type: ingress# TLS 证书配置(用于 HTTPS 加密)tls:enabled: true # 启用 HTTPS 加密(必须开启,否则 Harbor 核心功能可能受限)certSource: auto # 证书来源:自动生成(由 Ingress Controller 或 cert-manager 自动创建证书)auto:commonName: "harbor.example.com" # 自动生成证书的主域名(需与实际访问域名一致)secret:secretName: "" # 若 certSource 设为 "secret",需填写存储证书的 Secret 名称(此处未使用)notarySecretName: "" # Notary 服务(镜像签名验证)的证书 Secret 名称(此处未使用)# Ingress 具体配置(当 expose.type=ingress 时生效)ingress:hosts:core: harbor.example.com # Harbor 核心服务(UI、API 等)的访问域名notary: notary.harbor.example.com # Notary 服务的访问域名(用于镜像签名验证)controller: nginx # Ingress Controller )kubeVersionOverride: "" # 覆盖 Kubernetes 版本(一般留空,由 Helm 自动识别)annotations: # Ingress 注解(用于配置 Ingress Controller 行为)ingress.kubernetes.io/ssl-redirect: "true" # 强制 HTTP 重定向到 HTTPS(旧版注解)ingress.kubernetes.io/proxy-body-size: "0" # 允许上传任意大小的文件(0 表示不限制)nginx.ingress.kubernetes.io/ssl-redirect: "true" # 强制 HTTP 重定向到 HTTPS(Nginx 新版注解)nginx.ingress.kubernetes.io/proxy-body-size: "0" # 允许上传任意大小的文件(Nginx 新版注解)notary:annotations: {} # Notary 服务的独立 Ingress 注解(此处未额外配置)harbor:annotations: {} # Harbor 核心服务的独立 Ingress 注解(此处未额外配置)# ClusterIP 配置(当 expose.type=clusterIP 时生效,仅集群内部可访问)clusterIP:name: harbor # ClusterIP Service 的名称annotations: {} # 给 ClusterIP Service 添加的注解ports:httpPort: 80 # HTTP 端口(内部访问用)httpsPort: 443 # HTTPS 端口(内部访问用)notaryPort: 4443 # Notary 服务端口(内部访问用)# NodePort 配置(当 expose.type=nodePort 时生效,通过节点 IP+端口访问)nodePort:name: harbor # NodePort Service 的名称ports:http:port: 80 # 服务内部 HTTP 端口nodePort: 30002 # 节点暴露的 HTTP 端口(需在 30000-32767 范围内)https:port: 443 # 服务内部 HTTPS 端口nodePort: 30003 # 节点暴露的 HTTPS 端口notary:port: 4443 # 服务内部 Notary 端口nodePort: 30004 # 节点暴露的 Notary 端口# LoadBalancer 配置(当 expose.type=loadBalancer 时生效,适用于云厂商环境)loadBalancer:name: harbor # LoadBalancer Service 的名称IP: "" # 固定负载均衡器 IP(云厂商支持时填写)ports:httpPort: 80 # 负载均衡器转发的 HTTP 端口httpsPort: 443 # 负载均衡器转发的 HTTPS 端口notaryPort: 4443 # 负载均衡器转发的 Notary 端口annotations: {} # 给 LoadBalancer Service 添加的注解(如云厂商特定配置)sourceRanges: [] # 限制允许访问的 IP 段(如 ["192.168.0.0/16"])# Harbor 外部访问 URL(必须与 Ingress 配置的域名一致,用户实际访问的地址)externalURL: https://harbor.example.com# 内部组件间通信的 TLS 配置(Harbor 各组件之间的加密通信)internalTLS:enabled: false # 禁用内部 TLS 加密(生产环境建议开启,需配置证书)certSource: "auto" # 内部证书来源:自动生成(若 enabled=true 时生效)trustCa: "" # 信任的 CA 证书(若使用自定义 CA 需填写)# 以下为各组件的证书配置(若 enabled=true 时需分别设置)core:secretName: "" # 存储 core 组件证书的 Secret 名称crt: "" # 证书内容(直接填写时用,通常优先用 secretName)key: "" # 私钥内容jobservice:secretName: "" # jobservice 组件证书的 Secret 名称crt: ""key: ""registry:secretName: "" # 镜像仓库组件证书的 Secret 名称crt: ""key: ""portal:secretName: "" # UI 门户组件证书的 Secret 名称crt: ""key: ""chartmuseum:secretName: "" # Helm 图表仓库组件证书的 Secret 名称crt: ""key: ""trivy:secretName: "" # 漏洞扫描组件证书的 Secret 名称crt: ""key: ""# IP 协议族配置(控制 Harbor 服务使用 IPv4 还是 IPv6)ipFamily:ipv6:enabled: false # 禁用 IPv6ipv4:enabled: true # 启用 IPv4(默认使用 IPv4)
6. 组件高可用配置
# 核心组件副本数(参考架构为 3,按需调整,建议 ≥2 保证高可用)core:replicas: 2portal:replicas: 2nginx:replicas: 2registry:replicas: 2jobservice:replicas: 2# 非核心组件副本数notary:enabled: true # 启用镜像签名验证server:replicas: 1signer:replicas: 1trivy:enabled: true # 启用漏洞扫描replicas: 1chartmuseum:enabled: true # 启用 Chart 仓库replicas: 1
三、执行 Helm 部署
1. 部署前配置校验
# 执行配置校验(检查 values.yaml 语法是否正确)helm lint -f values.yaml .
2. 执行部署
# 部署 Harbor 到 harbor 命名空间helm install harbor . -n harbor -f values.yamlhelm install harbor . -f values.yaml --namespace harbor --create-namespace# 查看部署进度(等待所有 Pod 变为 Running 状态)kubectl get pods -n harbor -o wide -w# 若有 Pod 启动失败,查看日志排查:kubectl logs <pod名称> -n harbor#执行 Helm 升级,应用配置变更helm upgrade harbor . -n harbor -f values.yaml#等待完成[root@k8s-master harbor-helm-1.8.3]# kubectl get pod -n harborNAME READY STATUS RESTARTS AGEharbor-chartmuseum-79df59d854-4k6pg 1/1 Running 0 5m57sharbor-core-bcbf795db-b97kc 1/1 Running 0 5m37sharbor-core-bcbf795db-c6w8k 1/1 Running 0 5m57sharbor-jobservice-6466d59f5c-8nvms 1/1 Running 0 5m7sharbor-jobservice-6466d59f5c-zw7cp 1/1 Running 0 5m57sharbor-notary-server-f69564c57-xgq9z 1/1 Running 1 (27s ago) 5m57sharbor-notary-signer-7bb86c8596-hxcrx 1/1 Running 0 5m57sharbor-portal-57cf48cfc8-6lmlc 1/1 Running 0 14mharbor-portal-57cf48cfc8-rjdkj 1/1 Running 0 14mharbor-registry-64fc45b845-x7d77 2/2 Running 0 5m57sharbor-registry-64fc45b845-zl7mr 2/2 Running 0 5m55sharbor-trivy-0 1/1 Running 0 14m
3. 验证部署资源
kubectl get svc -n harborkubectl get ingress -n harborkubectl get pvc -n harbor
如果出现问题:通过外部域名或IP访问时出现404或连接超时错误
kubectl -n harbor get ingressNAME CLASS HOSTS ADDRESS PORTS AGEharbor-ingress nginx dockerhub.kubekey.localkubectl get ingressclasses.networking.k8s.ioNAME CONTROLLER PARAMETERS AGEnginx k8s.io/ingress-nginx <none> 7h45mkubectl -n harbor edit ingress harbor-ingressspec:ingressClassName: nginxkubectl -n harbor edit ingress harbor-ingress-notaryspec:ingressClassName: nginx
卸载流程
helm uninstall harbor -n harborkubectl delete pvc -n harbor --allkubectl get all -n harborkubectl delete all --all -n harbor --forcekubectl delete namespace harbor
四、访问与功能验证
1. 本地访问测试(部署节点)
# 由于未配置 SSL,直接访问 HTTP 地址(Ingress 会重定向到 HTTPS,忽略证书警告)curl -k https://harbor.example.com# 返回 Harbor 登录页面 HTML 内容则正常
2. 浏览器访问验证
#从 Harbor 集群中导出证书(在 k8s 主节点执行):# 1. 查看 Harbor 自动生成的证书 Secret(命名空间为 harbor)kubectl get secrets -n harbor | grep tls# 输出通常是 harbor-tls(核心证书)和 notary-tls(可选)# 2. 导出证书并保存到 Docker 信任目录mkdir -p /etc/docker/certs.d/harbor.example.com# 导出证书到 Docker 信任目录kubectl get secret harbor-ingress -n harbor -o jsonpath='{.data.tls\.crt}' | base64 -d > /etc/docker/certs.d/harbor.example.com/ca.crt# 查看证书文件内容(有内容则正常)cat /etc/docker/certs.d/harbor.example.com/ca.crt
-
打开本地浏览器,输入地址:
https://harbor.example.com
-
忽略 SSL 证书警告(若未配置有效证书)
-
使用管理员账号登录:用户名
admin,密码Shyshy521521!(配置文件中自定义的)证书下载
Harobr主页->配置管理->系统配置->镜像库根证书
然后进入服务器,在服务器上
/etc/docker目录下创建 certs.d 文件夹,然后在 certs.d 文件夹下创建 Harobr 域名文件夹,可以输入下面命令创建对应文件夹:mkdir -p /etc/docker/certs.d/harbor.example.com在此目录放证书文件
-
-
-
-
登录后验证核心功能:
-
创建项目(如
test-project) -
本地 Docker 登录 Harbor(需配置 Docker 信任私有仓库)
# Docker 配置信任 Harbor 域名(避免 https 报错)cat > /etc/docker/daemon.json << EOF{"insecure-registries": ["https://harbor.example.com"],}EOFsystemctl restart docker# Docker 登录 Harborecho 'Shyshy521521!' | docker login harbor.example.com -u admin --password-stdindocker login -u admin -p Shyshy521521! harbor.example.com#示例[root@k8s-master harbor-helm-1.8.3]# echo 'Shyshy521521!' | docker login harbor.example.com -u admin --password-stdinWARNING! Your password will be stored unencrypted in /root/.docker/config.json.Configure a credential helper to remove this warning. Seehttps://docs.docker.com/engine/reference/commandline/login/#credentials-storeLogin Succeeded
-
-
-
-
-
-
-
-
-
-
-
推送镜像到 Harbor(测试存储功能)
# 拉取测试镜像并打标签docker pull nginx:latest# 示例:将 nginx:latest 推送到 Harbor 的 library 项目(默认项目)docker tag nginx:latest harbor.example.com/library/nginx:v1# 推送镜像(验证 Ceph RGW 存储是否正常)docker push harbor.example.com/library/nginx:v1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
拉取镜像(验证镜像可访问)
docker rmi harbor.example.com/library/nginx:v1docker pull harbor.example.com/library/nginx:v1
-
-
-
-
创建 Harbor 镜像仓库的 Secret
创建在默认(default)命名空间
kubectl create secret docker-registry registry-auth \--docker-username=admin \--docker-password=shyshy521521 \--docker-server=harbor.example.com
若你的业务 Pod 部署在特定命名空间,建议将 Secret 创建在同一命名空间(K8s 的 Secret 是命名空间级资源,跨命名空间无法直接引用),命令添加-n <命名空间>即可:
# 示例:创建在dev命名空间kubectl create secret docker-registry registry-auth \--docker-username=admin \--docker-password=shyshy521521 \--docker-server=harbor.example.com \-n dev
查看 Secret
kubectl get secretskubectl get secrets -n dev查看 Secret 详细信息kubectl describe secret registry-authkubectl describe secret registry-auth -n dev
在 Pod/Deployment 中引用该 Secret
创建 Secret 后,需在 Pod 或 Deployment 的配置中通过imagePullSecrets字段引用,K8s 才会在拉取 Harbor 私有镜像时自动使用该凭据认证。
Deployment 中引用(生产环境常用)
编写一个拉取 Harbor 私有镜像的 Deployment 配置文件(如harbor-nginx-deploy.yaml),注意替换镜像地址为你 Harbor 中的实际镜像:
apiVersion: apps/v1kind: Deploymentmetadata:name: harbor-nginx-deploynamespace: default # 需与Secret的命名空间一致spec:replicas: 1selector:matchLabels:app: harbor-nginxtemplate:metadata:labels:app: harbor-nginxspec:containers:- name: nginx# 替换为你Harbor中的镜像地址,格式:harbor.example.com/项目名/镜像名:版本image: harbor.example.com/library/nginx:v1ports:- containerPort: 80# 引用创建的SecretimagePullSecrets:- name: registry-auth

