11# harbor 插件
22
3- 这个插件使用 helm 在已有的 k8s 集群上安装 [ harbor ] ( https://goharbor.io/ ) 。
3+ ` harbor ` 插件用于部署、管理 [ Harbor ] ( https://goharbor.io/ ) 应用 。
44
5- ## 使用方法
5+ Harbor 的主流部署方式有2种:** docker compose** 和 ** helm** 。
6+ 现在 DevStream 有2个插件 ` harbor-docker ` 和 ` harbor ` 分别支持这2种部署方式,但是目前以 helm 方式为主。
7+ 在不久的将来,这两个插件将会被合并成一个。
68
7- ### 测试环境
9+ ## 1、前置要求
810
9- 如果你想在** 本地测试插件** , 可以使用如下 ` values_yaml ` 配置。
11+ - 有一个可用的 Kubernetes 集群,版本 1.10+
12+
13+ ## 2、部署架构
14+
15+ Harbor 本身并不关注如何实现存储高可用和 PostgreSQL、Redis 的高可用。
16+ 所以 Harbor 支持通过 PVCs 的方式持久化数据,支持对接外部 PostgreSQL 和 Redis。
17+
18+ Harbor 部署架构整体如下图所示(图片来自 Harbor 官网):
19+
20+ ![ Harbor Architecture] ( ./harbor/ha.png )
21+
22+ ## 3、开始部署
23+
24+ 下文将介绍如何配置 ` harbor ` 插件,完成 Harbor 应用的部署。演示环境为一台装有以 minikube 方式部署的单节点 k8s 集群的 Linux 云主机。
25+
26+ ### 3.1、快速开始
27+
28+ 如果仅是用于开发、测试等目的,希望快速完成 Harbor 的部署,可以使用如下配置快速开始:
29+
30+ ``` yaml
31+ --8<-- "harbor.yaml"
32+ ```
33+
34+ 在成功执行 ` dtm apply ` 命令后,我们可以在 harbor 命名空间下看到下述主要资源:
35+
36+ - ** Deployment** (` kubectl get deployment -n harbor ` )
37+
38+ ``` shell
39+ NAME READY UP-TO-DATE AVAILABLE AGE
40+ harbor-core 1/1 1 1 2m56s
41+ harbor-jobservice 1/1 1 1 2m56s
42+ harbor-nginx 1/1 1 1 2m56s
43+ harbor-portal 1/1 1 1 2m56s
44+ harbor-registry 1/1 1 1 2m56s
45+ ```
46+
47+ 可以看到几乎所有 Harbor 相关服务都是以 Deployment 方式在运行。
48+
49+ - ** StatefulSet** (` kubectl get statefulset -n harbor ` )
50+
51+ ``` shell
52+ NAME READY AGE
53+ harbor-database 1/1 3m40s
54+ harbor-redis 1/1 3m40s
55+ ```
56+
57+ 这两个 StatefulSet 资源对应的是 Harbor 所依赖的 PostgreSQL 和 Redis。
58+ 换言之,当前部署方式会自动完成 PostgreSQL 和 Redis 的部署,但是同时需要注意 PostgreSQL 和 Redis 并不是高可用的。
59+
60+ - ** Service** (` kubectl get service -n harbor ` )
61+
62+ ``` shell
63+ NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
64+ harbor NodePort 10.99.177.6 < none> 80:30002/TCP 4m17s
65+ harbor-core ClusterIP 10.106.220.239 < none> 80/TCP 4m17s
66+ harbor-database ClusterIP 10.102.102.95 < none> 5432/TCP 4m17s
67+ harbor-jobservice ClusterIP 10.98.5.49 < none> 80/TCP 4m17s
68+ harbor-portal ClusterIP 10.105.115.5 < none> 80/TCP 4m17s
69+ harbor-redis ClusterIP 10.104.100.167 < none> 6379/TCP 4m17s
70+ harbor-registry ClusterIP 10.106.124.148 < none> 5000/TCP,8080/TCP 4m17s
71+ ```
72+
73+ 可以看到默认情况下 Harbor 通过 NodePort 方式暴露服务时,端口是 30002。
74+
75+ - ** PersistentVolumeClaim** (` kubectl get pvc -n harbor ` )
76+
77+ ``` shell
78+ NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
79+ data-harbor-redis-0 Bound pvc-5b6b5eb4-c40d-4f46-8f19-ff3a8869e56f 1Gi RWO standard 5m12s
80+ database-data-harbor-database-0 Bound pvc-d7ccaf1f-c450-4a16-937a-f55ad0c7c18d 1Gi RWO standard 5m12s
81+ harbor-jobservice Bound pvc-9407ef73-eb65-4a56-8720-a9ddbcb76fef 1Gi RWO standard 5m13s
82+ harbor-registry Bound pvc-34a2b88d-9ff2-4af4-9faf-2b33e97b971f 5Gi RWO standard 5m13s
83+ ```
84+
85+ 从这里可以看到 Harbor 所需要的存储卷有4个,其中也包括了 PostgreSQL 和 Redis 的存储。
86+
87+ - ** PersistentVolume** (` kubectl get pv ` )
88+
89+ ``` shell
90+ pvc-34a2b88d-9ff2-4af4-9faf-2b33e97b971f 5Gi RWO Delete Bound harbor/harbor-registry standard 5m22s
91+ pvc-5b6b5eb4-c40d-4f46-8f19-ff3a8869e56f 1Gi RWO Delete Bound harbor/data-harbor-redis-0 standard 5m22s
92+ pvc-9407ef73-eb65-4a56-8720-a9ddbcb76fef 1Gi RWO Delete Bound harbor/harbor-jobservice standard 5m22s
93+ pvc-d7ccaf1f-c450-4a16-937a-f55ad0c7c18d 1Gi RWO Delete Bound harbor/database-data-harbor-database-0 standard 5m22s
94+ ```
95+
96+ 我们并没有配置 StorageClass,所以这里用的是集群内的 default StorageClass 完成的 pv 创建。
97+
98+ 在我的环境里,default StorageClass 如下(` kubectl get storageclass ` ):
99+
100+ ``` shell
101+ NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
102+ standard (default) k8s.io/minikube-hostpath Delete Immediate false 20h
103+ ```
104+
105+ 这个 StorageClass 对应的 Provisioner 会以 hostPath 的方式提供 pv。
106+
107+ 到这里,我们就可以通过 http://127.0.0.1:3002 访问到 Harbor 登录页面了,如下:
108+
109+ ![ Harbor Login] ( ./harbor/login.png )
110+
111+ 默认登录账号/密码是 ` admin/Harbor12345 ` 。登录后,可以看到默认首页如下:
112+
113+ ![ Harbor Dashboard] ( ./harbor/dashboard.png )
114+
115+ 如果是在云主机上部署的 Harbor,可以通过 ` kubectl port-forward ` 命令来暴露服务:
116+
117+ ``` shell
118+ ip=YOUR_HOST_IP
119+ kubectl port-forward -n harbor service/harbor --address=${ip} 80
120+ ```
121+
122+ 需要注意的是这里得使用主机真实网卡 ip,而我们在浏览器上输入的 ip 是云主机的公网 ip,两者并不一样。
123+
124+ ### 3.2、最小化配置
125+
126+ ` harbor ` 插件的配置项默认值如下表:
127+
128+ | key | default value | description |
129+ | ---- | ---- | ---- |
130+ | chart.chart_name | harbor/harbor | helm chart 包名称 |
131+ | chart.timeout | 10m | helm install 的超时时间 |
132+ | chart.upgradeCRDs | true | 是否更新 CRDs(如果有) |
133+ | chart.release_name | harbor | helm 发布名称 |
134+ | chart.wait | true | 是否等待部署完成 |
135+ | chart.namespace | harbor | 部署的命名空间 |
136+ | repo.url | https://helm.goharbor.io | helm 仓库地址 |
137+ | repo.name | harbor | helm 仓库名 |
138+ | create_namespace | false | 是否需要 dtm 来新建命名空间 |
139+
140+ 目前除了 ` values_yaml ` 字段和默认配置,其它所有示例参数均为必填项。 因此,我们也可以使用如下最小化配置达到和上面配置文件一样的效果:
141+
142+ ``` yaml
143+ tools :
144+ - name : harbor
145+ instanceID : default
146+ dependsOn : [ ]
147+ options :
148+ create_namespace : true
149+ chart :
150+ values_yaml : |
151+ externalURL: http://127.0.0.1
152+ expose:
153+ type: nodePort
154+ tls:
155+ enabled: false
156+ chartmuseum:
157+ enabled: false
158+ notary:
159+ enabled: false
160+ trivy:
161+ enabled: false
162+ ` ` `
163+
164+ ### 3.3、持久化存储数据
165+
166+ 前面我们已经看到了如果不配置 StorageClass,Harbor 会使用集群内的 default StorageClass。比如在当前演示环境下,harbor-registry 所使用的 pv 配置大致如下:
167+
168+ ` ` ` yaml
169+ apiVersion : v1
170+ kind : PersistentVolume
171+ metadata :
172+ name : pvc-34a2b88d-9ff2-4af4-9faf-2b33e97b971f
173+ spec :
174+ accessModes :
175+ - ReadWriteOnce
176+ capacity :
177+ storage : 5Gi
178+ claimRef :
179+ apiVersion : v1
180+ kind : PersistentVolumeClaim
181+ name : harbor-registry
182+ namespace : harbor
183+ hostPath :
184+ path : /tmp/hostpath-provisioner/harbor/harbor-registry
185+ persistentVolumeReclaimPolicy : Delete
186+ storageClassName : standard
187+ volumeMode : Filesystem
188+ status :
189+ phase : Bound
190+ ` ` `
191+
192+ 可见数据其实挂在到了主机的 ` /tmp/hostpath-provisioner/harbor/harbor-registry` 目录下了。
193+
194+ Harbor 支持3种持久化存储数据配置方式:
195+
196+ 1. 配置 StorageClass(默认使用 default StorageClass);
197+ 2. 使用已经存在的 pvc(手动创建);
198+ 3. 对接 azure、gcs、s3、swift、oss 等实现镜像和 Charts 云端存储。
199+
200+ 我们暂时只介绍第一种方式,也就是指定 StorageClass 实现存储数据持久化。
201+ registry、jobservice、chartmuseum、database、redis、trivy 等组件都可以单独指定 StorageClass。
202+ 假设我们现在有一个新的 StorageClass 叫做 nfs,这时候要实现前面部署的 Harbor 所有数据持久化到外部 pv,我们可以这样配置:
10203
11204` ` ` yaml
12- values_yaml : |
13- externalURL: http://127.0.0.1
14- expose:
15- type: nodePort
16- tls:
17- enabled: false
18- chartmuseum:
19- enabled: false
20- clair:
21- enabled: false
22- notary:
23- enabled: false
24- trivy:
25- enabled: false
205+ tools:
206+ - name: harbor
207+ instanceID: default
208+ dependsOn: [ ]
209+ options:
210+ create_namespace: true
211+ chart:
212+ values_yaml: |
213+ persistence:
214+ persistentVolumeClaim:
215+ registry:
216+ storageClass: "nfs"
217+ accessMode: ReadWriteOnce
218+ size: 5Gi
219+ jobservice:
220+ storageClass: "nfs"
221+ accessMode: ReadWriteOnce
222+ size: 1Gi
223+ database:
224+ storageClass: "nfs"
225+ accessMode: ReadWriteOnce
226+ size: 1Gi
227+ redis:
228+ storageClass: "nfs"
229+ accessMode: ReadWriteOnce
230+ size: 1Gi
26231` ` `
27232
28- 在该配置下
233+ # ## 3.4、服务暴露
234+
235+ Harbor 可以以 ClusterIP、LoadBalancer、NodePort 和 Ingress 等方式对外暴露服务。我们前面使用的就是 NodePort 方式:
29236
30- - helm 会自动创建依赖的 Postgresql 和 Redis;
31- - 数据挂载的磁盘默认会使用集群上机器的本地磁盘;
32- - 只安装 ` harbor` 主程序而不会安装其余的插件;
33- - 通过 `NodePort` 对外暴露服务,可使用 `http://{{k8s 节点ip}}:30002` 域名来访问,默认账号名密码为 admin/Harbor12345 (生产环境请替换默认账号密码)。
237+ ` ` ` yaml
238+ tools:
239+ - name: harbor
240+ instanceID: default
241+ dependsOn: [ ]
242+ options:
243+ create_namespace: true
244+ chart:
245+ values_yaml: |
246+ externalURL: http://127.0.0.1
247+ expose:
248+ type: nodePort
249+ ` ` `
34250
35- # ## 生产环境
251+ 本文我们再介绍一下如何使用 Ingress 方式暴露服务:
36252
37- Harbor的大部分组件都是无状态的。因此我们可以通过增加 `Pod` 的副本来确保组件被部署到多个工作节点,并使用 `Kubernetes` 的 `Service` 机制来确保跨 `Pod` 的网络连接。
253+ ` ` ` yaml
254+ tools:
255+ - name: harbor
256+ instanceID: default
257+ dependsOn: [ ]
258+ options:
259+ create_namespace: true
260+ chart:
261+ values_yaml: |
262+ externalURL: http://127.0.0.1
263+ expose:
264+ type: ingress
265+ tls:
266+ enabled: false
267+ hosts:
268+ core: "core.harbor.domain"
269+ ` ` `
38270
39- # ### 外部存储
271+ 注意:如果没有开启 TLS,这种方式暴露 Harbor 服务后 docker push/pull 命令必须带上端口。
40272
41- > Harbor 正常运行依赖 Postgresql 和 Redis。
273+ # ## 3.5、PostgreSQL 和 Redis 高可用
42274
43- - Postgresql:生产环境建议使用外部高可用的 Postgresql 集群,具体配置可参考 [config](https://github.com/goharbor/harbor-helm#configuration) 中的 Database 选项 。
44- - Redis : 生产环境建议使用外部高可用的 Redis 集群,具体配置可参考 [config](https://github.com/goharbor/harbor-helm#configuration) 中的 Redis 选项 。
275+ Harbor 依赖 PostgreSQL 和 Redis 服务,默认情况下自动部署的 PostgreSQL 和 Redis 服务都是非高可用模式 。
276+ 换言之如果我们单独部署高可用的 PostgreSQL 和 Redis 服务,Harbor 是支持去对接外部 PostgreSQL 和 Redis 服务的 。
45277
46- # ### 磁盘存储
47- 请将配置中的 `storageClass` 修改为已存在的 StorageClass,集体配置可参考 [config](https://github.com/goharbor/harbor-helm#configuration) 中的 Persistence 选项。
278+ TODO(daniel-hutao) : 本节待细化
48279
49- # ### 网络层配置
50- 该插件支持 `Ingress`, `ClusterIP`, `NodePort`, `LoadBalancer` 对外暴露的模式,可以基于需求进行选择。
280+ # ## 3.6、https 配置
51281
52- # ### 证书配置
282+ TODO(daniel-hutao) : 本节待细化
53283
54284- 使用自签名证书
55285 1. 将 `tls.enabled` 设置为 `true`,并编辑对应的域名 `externalURL`;
@@ -60,24 +290,22 @@ Harbor的大部分组件都是无状态的。因此我们可以通过增加 `Pod
60290 2. 将 `tls.enabled` 设置为 `true`,并编辑对应的域名 `externalURL`;
61291 3. 配置 `tls.secretName` 使用该公共证书。
62292
63- # ## 配置
293+ # # 4、典型场景
64294
65- ` ` ` yaml
66- --8<-- "harbor.yaml"
67- ` ` `
295+ // TODO(daniel-hutao) : 本节待补充
296+
297+ # ## 4.1、HTTP
298+
299+ # ### 4.1.1 HTTP + Registry + Internal Database + Internal Redis
300+
301+ # ### 4.1.2 HTTP + Registry + Chartmuseum + Internal Database + Internal Redis
302+
303+ # ### 4.1.3 HTTP + Registry + Chartmuseum + External Database + External Redis
304+
305+ # ## 4.2、HTTPS
306+
307+ # ### 4.1.1 HTTPS + Registry + Internal Database + Internal Redis
308+
309+ # ### 4.1.2 HTTPS + Registry + Chartmuseum + Internal Database + Internal Redis
68310
69- # ### 默认配置
70-
71- | key | default value | description |
72- | ---- | ---- | ---- |
73- | chart.chart_name | harbor/harbor | helm 包名称 |
74- | chart.timeout | 10m | 等待部署成功的时间 |
75- | chart.upgradeCRDs | true | 默认更新 CRD 配置(如果存在的话) |
76- | chart.release_name | harbor | helm 发布名称 |
77- | chart.wait | true | 是否等待部署完成 |
78- | chart.namespace | harbor | helm 部署的命名空间名称 |
79- | repo.url | https://helm.goharbor.io | helm 官方仓库地址 |
80- | repo.name | harbor | helm 仓库名 |
81- | create_namespace | false | 是否需要新建命名空间 |
82-
83- 目前除了 `values_yaml` 字段和默认配置,其它所有示例参数均为必填项。
311+ # ### 4.1.3 HTTPS + Registry + Chartmuseum + External Database + External Redis
0 commit comments