参考链接:
官方:https://goharbor.io/docs/2.7.0/install-config/harbor-ha-helm/
https://blog.51cto.com/lidabai/5195706
1、先决条件
- Kubernetes 集群 1.10+
- 头盔 2.8.0+
- 高可用入口控制器(Harbor 不管理外部端点)
- 高可用 PostgreSQL 9.6+(Harbor 不处理数据库 HA 的部署)
- 高可用Redis(Harbor不处理Redis的HA部署)
- 可以跨节点或外部对象存储共享的 PVC
2、下载Chart并部署
# 添加仓库(helm repo add repoName repoURL)helm repo add harbor https://helm.goharbor.io# 查看添加的仓库helm repo list# 删除已经添加的仓库(helm repo remove repoName)# 将本地所添加的chart仓库的最新信息缓存到本地(helm repo update)# helm列出所有版本:helm search repo harbor -l# helm 下载指定版本:# helm fetch harbor/harbor --version 1.7.2helm fetch harbor/harbor --untar # 拉取最新并解压
或者使用一下方式下载chart到不本地解压
$ helm search repo harbor # 搜索chart包NAME CHART VERSION APP VERSION DESCRIPTIONharbor/harbor 1.8.2 2.4.2 An open source trusted cloud native registry th...$ helm pull harbor/harbor # 下载Chart包$ tar zxvf harbor-1.8.2.tgz # 解压包
- 这里可以使用使用默认配置直接部署
helm install my-harbor harbor/
- 这种方式不建议
- 建议使用单独的名称空间和外部储存进行部署
3、创建harbor名称空间
kubectl create namespace harbor
4、修改values.yaml配置
- chart目录结构
[root@k8s-node1 harbor]# ll总用量 256drwxr-xr-x 2 root root 36 12月 30 17:28 cert-rw-r--r-- 1 root root 569 12月 30 17:28 Chart.yamldrwxr-xr-x 2 root root 58 12月 30 17:28 conf-rw-r--r-- 1 root root 11357 12月 30 17:28 LICENSE-rw-r--r-- 1 root root 204387 12月 30 17:28 README.mddrwxr-xr-x 16 root root 4096 12月 30 17:28 templates-rw-r--r-- 1 root root 34194 12月 30 17:28 values.yaml
- values.yaml配置
# 修改前建议先备份配置文件cp values.yaml valies.yaml-bakcat values.yamlexpose:type: nodePort # 对外暴露方式(默认使用ingress),这里没有ingress环境使用NodePorttls:enabled: false # 关闭tls安全加密认证(如果开启需要配置证书)certSource: autoauto:commonName: ""secret:secretName: ""notarySecretName: ""ingress:hosts:core: core.harbor.domainnotary: notary.harbor.domaincontroller: defaultkubeVersionOverride: ""className: ""annotations:ingress.kubernetes.io/ssl-redirect: "true"ingress.kubernetes.io/proxy-body-size: "0"nginx.ingress.kubernetes.io/ssl-redirect: "true"nginx.ingress.kubernetes.io/proxy-body-size: "0"notary:annotations: {}labels: {}harbor:annotations: {}labels: {}clusterIP:name: harborannotations: {}ports:httpPort: 80httpsPort: 443notaryPort: 4443nodePort:name: harborports:http:port: 80nodePort: 30002https:port: 443nodePort: 30003notary:port: 4443nodePort: 30004loadBalancer:name: harborIP: ""ports:httpPort: 80httpsPort: 443notaryPort: 4443annotations: {}sourceRanges: []externalURL: https://core.harbor.domain # 使用nodePort且关闭tls认证,则此处需要修改为http协议和expose.nodePort.ports.http.nodePort指定的端口号,IP即为kubernetes的节点IP地址externalURL: http://192.168.6.31:30002internalTLS:enabled: falsecertSource: "auto"trustCa: ""core:secretName: ""crt: ""key: ""jobservice:secretName: ""crt: ""key: ""registry:secretName: ""crt: ""key: ""portal:secretName: ""crt: ""key: ""chartmuseum:secretName: ""crt: ""key: ""trivy:secretName: ""crt: ""key: ""ipFamily:ipv6:enabled: trueipv4:enabled: true# 持久化存储配置部分persistence:enabled: true # 开启持久化存储resourcePolicy: "keep"persistentVolumeClaim: # 定义Harbor各个组件的PVC持久卷部分registry: # registry组件(持久卷)配置部分existingClaim: ""storageClass: "managed-nfs-storage" # StorageClass,其它组件同样配置subPath: ""accessMode: ReadWriteMany # 卷的访问模式,需要修改为ReadWriteMany,允许多个组件读写,否则有的组件无法读取其它组件的数据size: 5Giannotations: {}chartmuseum: # chartmuseum组件(持久卷)配置部分existingClaim: ""storageClass: "managed-nfs-storage" #修改,同上subPath: ""accessMode: ReadWriteOncesize: 5Giannotations: {}jobservice:jobLog:existingClaim: ""storageClass: ""subPath: ""accessMode: ReadWriteOncesize: 1Giannotations: {}scanDataExports:existingClaim: ""storageClass: ""subPath: ""accessMode: ReadWriteOncesize: 1Giannotations: {}database: # PostgreSQl数据库组件(持久卷)配置部分existingClaim: ""storageClass: "managed-nfs-storage" # 同上subPath: ""accessMode: ReadWriteMany # 同上size: 1Giannotations: {}redis: # Redis缓存组件(持久卷)配置部分existingClaim: ""storageClass: "managed-nfs-storage" # 同上subPath: ""accessMode: ReadWriteMany # 同上size: 1Giannotations: {}trivy: # Trity漏洞扫描插件(持久卷)配置部分existingClaim: ""storageClass: "managed-nfs-storage"subPath: ""accessMode: ReadWriteManysize: 5Giannotations: {}imageChartStorage:disableredirect: falsetype: filesystemfilesystem:rootdirectory: /storageazure:accountname: accountnameaccountkey: base64encodedaccountkeycontainer: containernameexistingSecret: ""gcs:bucket: bucketnameencodedkey: base64-encoded-json-key-fileexistingSecret: ""useWorkloadIdentity: falses3:region: us-west-1bucket: bucketnameswift:authurl: https://storage.myprovider.com/v3/authusername: usernamepassword: passwordcontainer: containernameoss:accesskeyid: accesskeyidaccesskeysecret: accesskeysecretregion: regionnamebucket: bucketnameimagePullPolicy: IfNotPresentimagePullSecrets:updateStrategy:type: RollingUpdatelogLevel: infoharborAdminPassword: "Harbor12345" # admin初始密码,不需要修改(生产环境建议修改)caSecretName: ""secretKey: "not-a-secure-key"existingSecretSecretKey: ""proxy:httpProxy:httpsProxy:noProxy: 127.0.0.1,localhost,.local,.internalcomponents:- core- jobservice- trivyenableMigrateHelmHook: falsenginx:image:repository: goharbor/nginx-photontag: v2.7.0serviceAccountName: ""automountServiceAccountToken: falsereplicas: 1revisionHistoryLimit: 10nodeSelector: {}tolerations: []affinity: {}podAnnotations: {}priorityClassName:portal:image:repository: goharbor/harbor-portaltag: v2.7.0serviceAccountName: ""automountServiceAccountToken: falsereplicas: 1revisionHistoryLimit: 10nodeSelector: {}tolerations: []affinity: {}podAnnotations: {}priorityClassName:core:image:repository: goharbor/harbor-coretag: v2.7.0serviceAccountName: ""automountServiceAccountToken: falsereplicas: 1revisionHistoryLimit: 10startupProbe:enabled: trueinitialDelaySeconds: 10nodeSelector: {}tolerations: []affinity: {}podAnnotations: {}serviceAnnotations: {}secret: ""secretName: ""xsrfKey: ""priorityClassName:artifactPullAsyncFlushDuration:gdpr:deleteUser: falsejobservice:image:repository: goharbor/harbor-jobservicetag: v2.7.0replicas: 1revisionHistoryLimit: 10serviceAccountName: ""automountServiceAccountToken: falsemaxJobWorkers: 10jobLoggers:- filenodeSelector: {}tolerations: []affinity: {}podAnnotations: {}secret: ""priorityClassName:registry:serviceAccountName: ""automountServiceAccountToken: falseregistry:image:repository: goharbor/registry-photontag: v2.7.0controller:image:repository: goharbor/harbor-registryctltag: v2.7.0replicas: 1revisionHistoryLimit: 10nodeSelector: {}tolerations: []affinity: {}podAnnotations: {}priorityClassName:secret: ""relativeurls: falsecredentials:username: "harbor_registry_user"password: "harbor_registry_password"existingSecret: ""middleware:enabled: falsetype: cloudFrontcloudFront:baseurl: example.cloudfront.netkeypairid: KEYPAIRIDduration: 3000sipfilteredby: noneprivateKeySecret: "my-secret"upload_purging:enabled: trueage: 168hinterval: 24hdryrun: falsechartmuseum:enabled: trueserviceAccountName: ""automountServiceAccountToken: falseabsoluteUrl: falseimage:repository: goharbor/chartmuseum-photontag: v2.7.0replicas: 1revisionHistoryLimit: 10nodeSelector: {}tolerations: []affinity: {}podAnnotations: {}priorityClassName:indexLimit: 0trivy:enabled: trueimage:repository: goharbor/trivy-adapter-photontag: v2.7.0serviceAccountName: ""automountServiceAccountToken: falsereplicas: 1debugMode: falsevulnType: "os,library"severity: "UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL"ignoreUnfixed: falseinsecure: falsegitHubToken: ""skipUpdate: falseofflineScan: falsesecurityCheck: "vuln"timeout: 5m0sresources:requests:cpu: 200mmemory: 512Milimits:cpu: 1memory: 1GinodeSelector: {}tolerations: []affinity: {}podAnnotations: {}priorityClassName:notary:enabled: trueserver:serviceAccountName: ""automountServiceAccountToken: falseimage:repository: goharbor/notary-server-photontag: v2.7.0replicas: 1nodeSelector: {}tolerations: []affinity: {}podAnnotations: {}priorityClassName:serviceAnnotations: {}signer:serviceAccountName: ""automountServiceAccountToken: falseimage:repository: goharbor/notary-signer-photontag: v2.7.0replicas: 1nodeSelector: {}tolerations: []affinity: {}podAnnotations: {}priorityClassName:secretName: ""database:type: internalinternal:serviceAccountName: ""automountServiceAccountToken: falseimage:repository: goharbor/harbor-dbtag: v2.7.0password: "changeit"shmSizeLimit: 512MilivenessProbe:timeoutSeconds: 1readinessProbe:timeoutSeconds: 1nodeSelector: {}tolerations: []affinity: {}priorityClassName:initContainer:migrator: {}permissions: {}external:host: "192.168.0.1"port: "5432"username: "user"password: "password"coreDatabase: "registry"notaryServerDatabase: "notary_server"notarySignerDatabase: "notary_signer"existingSecret: ""sslmode: "disable"maxIdleConns: 100maxOpenConns: 900podAnnotations: {}redis:type: internalinternal:serviceAccountName: ""automountServiceAccountToken: falseimage:repository: goharbor/redis-photontag: v2.7.0nodeSelector: {}tolerations: []affinity: {}priorityClassName:external:addr: "192.168.0.2:6379"sentinelMasterSet: ""coreDatabaseIndex: "0"jobserviceDatabaseIndex: "1"registryDatabaseIndex: "2"chartmuseumDatabaseIndex: "3"trivyAdapterIndex: "5"password: ""existingSecret: ""podAnnotations: {}exporter:replicas: 1revisionHistoryLimit: 10podAnnotations: {}serviceAccountName: ""automountServiceAccountToken: falseimage:repository: goharbor/harbor-exportertag: v2.7.0nodeSelector: {}tolerations: []affinity: {}cacheDuration: 23cacheCleanInterval: 14400priorityClassName:metrics: # 是否启用监控组件(可以使用Prometheus监控Harbor指标),非必须操作enabled: true # 默认关闭core:path: /metricsport: 8001registry:path: /metricsport: 8001jobservice:path: /metricsport: 8001exporter:path: /metricsport: 8001serviceMonitor:enabled: falseadditionalLabels: {}interval: ""metricRelabelings:[]relabelings:[]trace:enabled: falseprovider: jaegersample_rate: 1jaeger:endpoint: http://hostname:14268/api/tracesotel:endpoint: hostname:4318url_path: /v1/tracescompression: falseinsecure: truetimeout: 10cache:enabled: falseexpireHours: 24
StorageClass部署手册:
https://www.yuque.com/geray-alxoc/bapt5y/ephx5o?singleDoc# 《7、k8s存储》
https://github.com/kubernetes-retired/external-storage/tree/master/nfs
- 修改完成配置之后可以进行安装
helm install harbor ./harbor -n harbor # 将安装资源部署到harbor命名空间

# 查看chart状态helm status harbor -n harbor# 卸载charthelm uninstall harbor -nharbor
- 默认情况下helm3只显示默认名称空间(default)下的发布
5、服务验证
1. 查看所有服务启动状态
kubectl get pod -n harborNAME READY STATUS RESTARTS AGEharbor-chartmuseum-5798db66df-kg7hm 1/1 Running 0 2m20sharbor-core-789d6c44f9-mgdlq 1/1 Running 0 2m20sharbor-database-0 1/1 Running 0 2m18sharbor-exporter-7948fc6669-lw58b 1/1 Running 0 2m20sharbor-jobservice-66bf498cc4-l8cfc 1/1 Running 3 (57s ago) 2m20sharbor-nginx-fc68874d5-hbd59 1/1 Running 0 2m20sharbor-notary-server-f95bc8f6d-kblng 1/1 Running 1 (65s ago) 2m20sharbor-notary-signer-98cc8c75f-gfmr6 1/1 Running 0 2m20sharbor-portal-b7d5d9558-hl9jx 1/1 Running 0 2m20sharbor-redis-0 1/1 Running 0 2m18sharbor-registry-5896d877fc-dbv7b 2/2 Running 0 2m20sharbor-trivy-0 1/1 Running 0 2m18s
2. 查看service
kubectl get svc -nharborNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEharbor NodePort 10.233.25.27 <none> 80:30002/TCP,4443:30004/TCP 15mharbor-chartmuseum ClusterIP 10.233.19.145 <none> 80/TCP 15mharbor-core ClusterIP 10.233.60.97 <none> 80/TCP,8001/TCP 15mharbor-database ClusterIP 10.233.48.217 <none> 5432/TCP 15mharbor-exporter ClusterIP 10.233.28.154 <none> 8001/TCP 15mharbor-jobservice ClusterIP 10.233.17.179 <none> 80/TCP,8001/TCP 15mharbor-notary-server ClusterIP 10.233.43.35 <none> 4443/TCP 15mharbor-notary-signer ClusterIP 10.233.38.126 <none> 7899/TCP 15mharbor-portal ClusterIP 10.233.46.136 <none> 80/TCP 15mharbor-redis ClusterIP 10.233.34.145 <none> 6379/TCP 15mharbor-registry ClusterIP 10.233.22.128 <none> 5000/TCP,8080/TCP,8001/TCP 15mharbor-trivy ClusterIP 10.233.62.176 <none> 8080/TCP 15m
3. 登陆访问测试
# 查看状态,寻找访问方式helm status harbor -n harborNAME: harborLAST DEPLOYED: Wed Feb 8 09:30:07 2023NAMESPACE: harborSTATUS: deployedREVISION: 1TEST SUITE: NoneNOTES:Please wait for several minutes for Harbor deployment to complete.Then you should be able to visit the Harbor portal at http://192.168.6.31:30002For more details, please visit https://github.com/goharbor/harbor
- 拉取镜像打标签推送测试
# 添加私服地址vim /etc/docker/daemon.json"insecure-registries": ["192.168.6.31:30002"]
docker pull nginxdocker tag nginx:latest 192.168.6.31:30002/mid/nginx:latestdocker push 192.168.6.31:30002/mid/nginx:latest

6、错误排查
kubectl describe pod harbor-notary-server-54f99bd444-shxl6 -n harbor...Normal Started 12m (x4 over 15m) kubelet Started container notary-serverNormal Pulled 12m (x3 over 14m) kubelet Container image "goharbor/notary-server-photon:v2.7.0" already present on machineWarning Unhealthy 7m36s (x12 over 9m14s) kubelet Readiness probe failed: HTTP probe failed with statuscode: 503Warning Unhealthy 104s (x6 over 14m) kubelet Readiness probe failed: Get "http://10.233.111.122:4443/_notary_server/health": dial tcp 10.233.111.122:4443: connect: connection refused

kubectl describe pod harbor-notary-signer-5db9f5ff9-5rdtb -n harbor...Normal Pulled 9m27s (x6 over 17m) kubelet Container image "goharbor/notary-signer-photon:v2.7.0" already present on machineWarning Unhealthy 3m31s (x7 over 17m) kubelet Readiness probe failed: Get "https://10.233.111.120:7899/": dial tcp 10.233.111.120:7899: connect: connection refused
- 本以为是禁用了tls导致的,结果等了一会发现好了(自愈了)
