参考链接:
官方: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.2
helm fetch harbor/harbor --untar # 拉取最新并解压
或者使用一下方式下载chart到不本地解压
$ helm search repo harbor # 搜索chart包
NAME CHART VERSION APP VERSION DESCRIPTION
harbor/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
总用量 256
drwxr-xr-x 2 root root 36 12月 30 17:28 cert
-rw-r--r-- 1 root root 569 12月 30 17:28 Chart.yaml
drwxr-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.md
drwxr-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-bak
cat values.yaml
expose:
type: nodePort # 对外暴露方式(默认使用ingress),这里没有ingress环境使用NodePort
tls:
enabled: false # 关闭tls安全加密认证(如果开启需要配置证书)
certSource: auto
auto:
commonName: ""
secret:
secretName: ""
notarySecretName: ""
ingress:
hosts:
core: core.harbor.domain
notary: notary.harbor.domain
controller: default
kubeVersionOverride: ""
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: harbor
annotations: {}
ports:
httpPort: 80
httpsPort: 443
notaryPort: 4443
nodePort:
name: harbor
ports:
http:
port: 80
nodePort: 30002
https:
port: 443
nodePort: 30003
notary:
port: 4443
nodePort: 30004
loadBalancer:
name: harbor
IP: ""
ports:
httpPort: 80
httpsPort: 443
notaryPort: 4443
annotations: {}
sourceRanges: []
externalURL: https://core.harbor.domain # 使用nodePort且关闭tls认证,则此处需要修改为http协议和expose.nodePort.ports.http.nodePort指定的端口号,IP即为kubernetes的节点IP地址
externalURL: http://192.168.6.31:30002
internalTLS:
enabled: false
certSource: "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: true
ipv4:
enabled: true
# 持久化存储配置部分
persistence:
enabled: true # 开启持久化存储
resourcePolicy: "keep"
persistentVolumeClaim: # 定义Harbor各个组件的PVC持久卷部分
registry: # registry组件(持久卷)配置部分
existingClaim: ""
storageClass: "managed-nfs-storage" # StorageClass,其它组件同样配置
subPath: ""
accessMode: ReadWriteMany # 卷的访问模式,需要修改为ReadWriteMany,允许多个组件读写,否则有的组件无法读取其它组件的数据
size: 5Gi
annotations: {}
chartmuseum: # chartmuseum组件(持久卷)配置部分
existingClaim: ""
storageClass: "managed-nfs-storage" #修改,同上
subPath: ""
accessMode: ReadWriteOnce
size: 5Gi
annotations: {}
jobservice:
jobLog:
existingClaim: ""
storageClass: ""
subPath: ""
accessMode: ReadWriteOnce
size: 1Gi
annotations: {}
scanDataExports:
existingClaim: ""
storageClass: ""
subPath: ""
accessMode: ReadWriteOnce
size: 1Gi
annotations: {}
database: # PostgreSQl数据库组件(持久卷)配置部分
existingClaim: ""
storageClass: "managed-nfs-storage" # 同上
subPath: ""
accessMode: ReadWriteMany # 同上
size: 1Gi
annotations: {}
redis: # Redis缓存组件(持久卷)配置部分
existingClaim: ""
storageClass: "managed-nfs-storage" # 同上
subPath: ""
accessMode: ReadWriteMany # 同上
size: 1Gi
annotations: {}
trivy: # Trity漏洞扫描插件(持久卷)配置部分
existingClaim: ""
storageClass: "managed-nfs-storage"
subPath: ""
accessMode: ReadWriteMany
size: 5Gi
annotations: {}
imageChartStorage:
disableredirect: false
type: filesystem
filesystem:
rootdirectory: /storage
azure:
accountname: accountname
accountkey: base64encodedaccountkey
container: containername
existingSecret: ""
gcs:
bucket: bucketname
encodedkey: base64-encoded-json-key-file
existingSecret: ""
useWorkloadIdentity: false
s3:
region: us-west-1
bucket: bucketname
swift:
authurl: https://storage.myprovider.com/v3/auth
username: username
password: password
container: containername
oss:
accesskeyid: accesskeyid
accesskeysecret: accesskeysecret
region: regionname
bucket: bucketname
imagePullPolicy: IfNotPresent
imagePullSecrets:
updateStrategy:
type: RollingUpdate
logLevel: info
harborAdminPassword: "Harbor12345" # admin初始密码,不需要修改(生产环境建议修改)
caSecretName: ""
secretKey: "not-a-secure-key"
existingSecretSecretKey: ""
proxy:
httpProxy:
httpsProxy:
noProxy: 127.0.0.1,localhost,.local,.internal
components:
- core
- jobservice
- trivy
enableMigrateHelmHook: false
nginx:
image:
repository: goharbor/nginx-photon
tag: v2.7.0
serviceAccountName: ""
automountServiceAccountToken: false
replicas: 1
revisionHistoryLimit: 10
nodeSelector: {}
tolerations: []
affinity: {}
podAnnotations: {}
priorityClassName:
portal:
image:
repository: goharbor/harbor-portal
tag: v2.7.0
serviceAccountName: ""
automountServiceAccountToken: false
replicas: 1
revisionHistoryLimit: 10
nodeSelector: {}
tolerations: []
affinity: {}
podAnnotations: {}
priorityClassName:
core:
image:
repository: goharbor/harbor-core
tag: v2.7.0
serviceAccountName: ""
automountServiceAccountToken: false
replicas: 1
revisionHistoryLimit: 10
startupProbe:
enabled: true
initialDelaySeconds: 10
nodeSelector: {}
tolerations: []
affinity: {}
podAnnotations: {}
serviceAnnotations: {}
secret: ""
secretName: ""
xsrfKey: ""
priorityClassName:
artifactPullAsyncFlushDuration:
gdpr:
deleteUser: false
jobservice:
image:
repository: goharbor/harbor-jobservice
tag: v2.7.0
replicas: 1
revisionHistoryLimit: 10
serviceAccountName: ""
automountServiceAccountToken: false
maxJobWorkers: 10
jobLoggers:
- file
nodeSelector: {}
tolerations: []
affinity: {}
podAnnotations: {}
secret: ""
priorityClassName:
registry:
serviceAccountName: ""
automountServiceAccountToken: false
registry:
image:
repository: goharbor/registry-photon
tag: v2.7.0
controller:
image:
repository: goharbor/harbor-registryctl
tag: v2.7.0
replicas: 1
revisionHistoryLimit: 10
nodeSelector: {}
tolerations: []
affinity: {}
podAnnotations: {}
priorityClassName:
secret: ""
relativeurls: false
credentials:
username: "harbor_registry_user"
password: "harbor_registry_password"
existingSecret: ""
middleware:
enabled: false
type: cloudFront
cloudFront:
baseurl: example.cloudfront.net
keypairid: KEYPAIRID
duration: 3000s
ipfilteredby: none
privateKeySecret: "my-secret"
upload_purging:
enabled: true
age: 168h
interval: 24h
dryrun: false
chartmuseum:
enabled: true
serviceAccountName: ""
automountServiceAccountToken: false
absoluteUrl: false
image:
repository: goharbor/chartmuseum-photon
tag: v2.7.0
replicas: 1
revisionHistoryLimit: 10
nodeSelector: {}
tolerations: []
affinity: {}
podAnnotations: {}
priorityClassName:
indexLimit: 0
trivy:
enabled: true
image:
repository: goharbor/trivy-adapter-photon
tag: v2.7.0
serviceAccountName: ""
automountServiceAccountToken: false
replicas: 1
debugMode: false
vulnType: "os,library"
severity: "UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL"
ignoreUnfixed: false
insecure: false
gitHubToken: ""
skipUpdate: false
offlineScan: false
securityCheck: "vuln"
timeout: 5m0s
resources:
requests:
cpu: 200m
memory: 512Mi
limits:
cpu: 1
memory: 1Gi
nodeSelector: {}
tolerations: []
affinity: {}
podAnnotations: {}
priorityClassName:
notary:
enabled: true
server:
serviceAccountName: ""
automountServiceAccountToken: false
image:
repository: goharbor/notary-server-photon
tag: v2.7.0
replicas: 1
nodeSelector: {}
tolerations: []
affinity: {}
podAnnotations: {}
priorityClassName:
serviceAnnotations: {}
signer:
serviceAccountName: ""
automountServiceAccountToken: false
image:
repository: goharbor/notary-signer-photon
tag: v2.7.0
replicas: 1
nodeSelector: {}
tolerations: []
affinity: {}
podAnnotations: {}
priorityClassName:
secretName: ""
database:
type: internal
internal:
serviceAccountName: ""
automountServiceAccountToken: false
image:
repository: goharbor/harbor-db
tag: v2.7.0
password: "changeit"
shmSizeLimit: 512Mi
livenessProbe:
timeoutSeconds: 1
readinessProbe:
timeoutSeconds: 1
nodeSelector: {}
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: 100
maxOpenConns: 900
podAnnotations: {}
redis:
type: internal
internal:
serviceAccountName: ""
automountServiceAccountToken: false
image:
repository: goharbor/redis-photon
tag: v2.7.0
nodeSelector: {}
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: 1
revisionHistoryLimit: 10
podAnnotations: {}
serviceAccountName: ""
automountServiceAccountToken: false
image:
repository: goharbor/harbor-exporter
tag: v2.7.0
nodeSelector: {}
tolerations: []
affinity: {}
cacheDuration: 23
cacheCleanInterval: 14400
priorityClassName:
metrics: # 是否启用监控组件(可以使用Prometheus监控Harbor指标),非必须操作
enabled: true # 默认关闭
core:
path: /metrics
port: 8001
registry:
path: /metrics
port: 8001
jobservice:
path: /metrics
port: 8001
exporter:
path: /metrics
port: 8001
serviceMonitor:
enabled: false
additionalLabels: {}
interval: ""
metricRelabelings:
[]
relabelings:
[]
trace:
enabled: false
provider: jaeger
sample_rate: 1
jaeger:
endpoint: http://hostname:14268/api/traces
otel:
endpoint: hostname:4318
url_path: /v1/traces
compression: false
insecure: true
timeout: 10
cache:
enabled: false
expireHours: 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
# 卸载chart
helm uninstall harbor -nharbor
- 默认情况下helm3只显示默认名称空间(default)下的发布
5、服务验证
1. 查看所有服务启动状态
kubectl get pod -n harbor
NAME READY STATUS RESTARTS AGE
harbor-chartmuseum-5798db66df-kg7hm 1/1 Running 0 2m20s
harbor-core-789d6c44f9-mgdlq 1/1 Running 0 2m20s
harbor-database-0 1/1 Running 0 2m18s
harbor-exporter-7948fc6669-lw58b 1/1 Running 0 2m20s
harbor-jobservice-66bf498cc4-l8cfc 1/1 Running 3 (57s ago) 2m20s
harbor-nginx-fc68874d5-hbd59 1/1 Running 0 2m20s
harbor-notary-server-f95bc8f6d-kblng 1/1 Running 1 (65s ago) 2m20s
harbor-notary-signer-98cc8c75f-gfmr6 1/1 Running 0 2m20s
harbor-portal-b7d5d9558-hl9jx 1/1 Running 0 2m20s
harbor-redis-0 1/1 Running 0 2m18s
harbor-registry-5896d877fc-dbv7b 2/2 Running 0 2m20s
harbor-trivy-0 1/1 Running 0 2m18s
2. 查看service
kubectl get svc -nharbor
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
harbor NodePort 10.233.25.27 <none> 80:30002/TCP,4443:30004/TCP 15m
harbor-chartmuseum ClusterIP 10.233.19.145 <none> 80/TCP 15m
harbor-core ClusterIP 10.233.60.97 <none> 80/TCP,8001/TCP 15m
harbor-database ClusterIP 10.233.48.217 <none> 5432/TCP 15m
harbor-exporter ClusterIP 10.233.28.154 <none> 8001/TCP 15m
harbor-jobservice ClusterIP 10.233.17.179 <none> 80/TCP,8001/TCP 15m
harbor-notary-server ClusterIP 10.233.43.35 <none> 4443/TCP 15m
harbor-notary-signer ClusterIP 10.233.38.126 <none> 7899/TCP 15m
harbor-portal ClusterIP 10.233.46.136 <none> 80/TCP 15m
harbor-redis ClusterIP 10.233.34.145 <none> 6379/TCP 15m
harbor-registry ClusterIP 10.233.22.128 <none> 5000/TCP,8080/TCP,8001/TCP 15m
harbor-trivy ClusterIP 10.233.62.176 <none> 8080/TCP 15m
3. 登陆访问测试
# 查看状态,寻找访问方式
helm status harbor -n harbor
NAME: harbor
LAST DEPLOYED: Wed Feb 8 09:30:07 2023
NAMESPACE: harbor
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
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:30002
For more details, please visit https://github.com/goharbor/harbor
- 拉取镜像打标签推送测试
# 添加私服地址
vim /etc/docker/daemon.json
"insecure-registries": ["192.168.6.31:30002"]
docker pull nginx
docker tag nginx:latest 192.168.6.31:30002/mid/nginx:latest
docker 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-server
Normal Pulled 12m (x3 over 14m) kubelet Container image "goharbor/notary-server-photon:v2.7.0" already present on machine
Warning Unhealthy 7m36s (x12 over 9m14s) kubelet Readiness probe failed: HTTP probe failed with statuscode: 503
Warning 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 machine
Warning 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导致的,结果等了一会发现好了(自愈了)