kubernetes-guide/tencent/install-apps/install-harbor-on-tke.md

288 lines
9.4 KiB
Markdown
Raw Normal View History

2023-09-27 17:04:00 +08:00
# 自建 Harbor 镜像仓库
## 概述
腾讯云有 [容器镜像服务 TCR](https://cloud.tencent.com/product/tcr),企业级容器镜像仓库,满足绝大多数镜像仓库的需求,如果需要使用镜像仓库,可以首选 TCR如果是考虑到成本或想使用 Harbor 的高级功能(如 [Proxy Cache](https://goharbor.io/docs/2.1.0/administration/configure-proxy-cache/)) 等因素,可以考虑自建 Harbor 镜像仓库,本文介绍如何在腾讯云容器服务中部署 Harbor 作为自建的容器镜像仓库。
## 前提条件
* 已安装 [Helm](https://helm.sh)。
* 已开启集群访问并配置好 kubeconfig可以通过 kubectl 操作集群(参考[官方文档:连接集群](https://cloud.tencent.com/document/product/457/32191))。
## 操作步骤
### 准备 COS 对象存储
镜像的存储建议是放对象存储,因为容量大,可扩展,成本低,速度还快。腾讯云上的对象存储是 [COS](https://cloud.tencent.com/product/cos),而 harbor 的存储驱动暂不支持 COS不过 COS 自身兼容 S3所以可以配置 harbor 使用 S3 存储驱动。
下面我们登录腾讯云账号,在 [COS 控制台](https://console.cloud.tencent.com/cos/bucket) 创建一个存储桶:
![](https://image-host-1251893006.cos.ap-chengdu.myqcloud.com/20220718202301.png)
记录一下如下信息后面用:
* `region`: 存储桶所在地域,如 `ap-chengdu`,参考 [地域和可用区](https://cloud.tencent.com/document/product/213/6091)。
* `bucket`: 存储桶名称,如 `registry-12*******6` (有 appid 后缀)。
* `regionendpoint`: 类似 `https://cos.<REGION>.myqcloud.com` 这种格式的 url`https://cos.ap-chengdu.myqcloud.com`
### 创建云 API 密钥
在 [访问密钥](https://console.cloud.tencent.com/cam/capi) 这里新建密钥:
![](https://image-host-1251893006.cos.ap-chengdu.myqcloud.com/20220718203635.png)
> 如果之前已经新建过,可跳过此步骤。
记录一下生成的 `SecretId``SecretKey`,后面需要用。
### 准备 chart
```bash
helm repo add harbor https://helm.goharbor.io
helm fetch harbor/harbor --untar
```
* 参考 [Harbor 官方文档: Deploying Harbor with High Availability via Helm](https://goharbor.io/docs/edge/install-config/harbor-ha-helm/)
* 查看 `./harbor/values.yaml` 可以看到配置项。
### 准备配置
`harbor-values.yaml`:
```yaml
expose:
type: clusterIP
tls:
enabled: false # 建议关闭 tls如果对外需要 https 访问,可以将 TLS 放到前面的 7 层代理进行配置。
externalURL: https://registry.imroc.cc # 镜像仓库的对外访问地址
persistence:
imageChartStorage:
type: s3
s3: # 务必修改! COS 相关配置
region: ap-chegndu
bucket: harbor-12*******6
accesskey: AKI*******************************zv # SecretId
secretkey: g5****************************FR # SecretKey
regionendpoint: https://cos.ap-chengdu.myqcloud.com
rootdirectory: / # 存储桶中存储镜像数据的路径
persistentVolumeClaim:
registry:
existingClaim: 'registry-registry'
jobservice:
existingClaim: "registry-jobservice"
harborAdminPassword: '123456' # 务必修改! harbor 管理员登录密码
chartmuseum:
enabled: false
trivy:
enabled: false
notary:
enabled: false
database:
type: external
external:
host: 'pgsql-postgresql.db'
username: 'postgres'
password: '123456'
coreDatabase: 'registry'
redis:
type: external
external:
addr: 'redis.db:6379'
coreDatabaseIndex: "10"
jobserviceDatabaseIndex: "11"
registryDatabaseIndex: "12"
chartmuseumDatabaseIndex: "13"
trivyAdapterIndex: "14"
```
注意事项:
* `expose` 配置暴露服务,我这里打算用其它方式暴露(istio-ingress-gateway),不使用 Ingress, LoadBalancer 之类的方式,所以 type 置为 clusterIP (表示仅集群内访问)另外tls 也不需要,都是在 gateway 上配置就行。
* `s3` 配置实为 COS 相关配置,将前面步骤记录的信息填上去。
* chartmuseum, trivy, notary 我都不需要,所以 `enabled` 都设为 `false`
* `harborAdminPassword` 是 harbor 管理员登录密码,设置一下。
* `database` 是配置 postgresql 数据库,我使用现成的数据库,配置 type 为 external 并写上相关连接配置。
* `redis` 是配置 redis 缓存,我使用现成的 redis配置 type 为 external 并写上相关连接配置。
* `persistentVolumeClaim` 配置持久化存储,我这里只有 `registry``jobservice` 模块需要挂载存储,存储我挂载的 CFS (腾讯云 NFS 服务),指定 `existingClaim` 为提前创建好的 pvc参考附录【挂载 CFS】。
### 安装
```bash
helm upgrade --install -n registry -f harbor-values.yaml registry ./harbor
```
> 后续如需卸载可以执行: helm uninstall registry
检查 pod 是否正常启动:
```bash
$ kubectl -n registry get pod
NAME READY STATUS RESTARTS AGE
registry-harbor-core-55d577c7-l9k5j 1/1 Running 0 1m
registry-harbor-jobservice-66846c575-dbvdz 1/1 Running 0 1m
registry-harbor-nginx-7d94c9446c-z6rkn 1/1 Running 0 1m
registry-harbor-portal-d87bc7554-psp2r 1/1 Running 0 1m
registry-harbor-registry-66d899c9c9-v2w7r 2/2 Running 0 1m
```
检查自动创建的 service:
```bash
$ kubectl -n registry get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
harbor ClusterIP 172.16.195.61 <none> 80/TCP 1m
registry-harbor-core ClusterIP 172.16.244.174 <none> 80/TCP 1m
registry-harbor-jobservice ClusterIP 172.16.219.62 <none> 80/TCP 1m
registry-harbor-portal ClusterIP 172.16.216.247 <none> 80/TCP 1m
registry-harbor-registry ClusterIP 172.16.146.201 <none> 5000/TCP,8080/TCP 1m
```
### 暴露服务
我这里使用 istio-ingressgateway 进行暴露,创建 VirtualService 与 Gateway 绑定:
```yaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: registry-imroc-cc
namespace: registry
spec:
gateways:
- external/imroc
hosts:
- 'registry.imroc.cc'
http:
- route:
- destination:
host: harbor
port:
number: 80
```
而 Gateway 则是提前创建好的,监听 443并配置了证书:
```yaml
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: imroc
namespace: external
spec:
selector:
app: istio-ingressgateway
istio: ingressgateway
servers:
- hosts:
- imroc.cc
- '*.imroc.cc'
port:
name: HTTPS-443
number: 443
protocol: HTTPS
tls:
credentialName: imroc-cc-crt-secret
mode: SIMPLE
```
### 验证服务与 COS 最终一致性问题
最后,可以登录一下 registry 并 push 下镜像试试:
![](https://image-host-1251893006.cos.ap-chengdu.myqcloud.com/20220718212040.png)
以上直接 push 成功是比较幸运的情况,通常往往会报 500 错误:
![](https://image-host-1251893006.cos.ap-chengdu.myqcloud.com/20220718212302.png)
什么原因? 是因为 COS 是保证最终一致性,当镜像数据 put 成功后,并不能保证马上能 list 到,导致 harbor 以为没 put 成功,从而报错,参考 [这篇文章](https://cloud.tencent.com/developer/article/1855894)。
如何解决?可以提工单将指定存储桶改为强一致性。但是由于 COS 底层架构升级的原因,暂时无法后台改配置,预计今年年底后才可以申请,相关工单截图:
![](https://image-host-1251893006.cos.ap-chengdu.myqcloud.com/20220718212820.png)
![](https://image-host-1251893006.cos.ap-chengdu.myqcloud.com/20220718212838.png)
临时规避的方法可以是:上传失败时重试下,直至上传成功。
## 附录
### 挂载 CFS
使用如下 yaml 将 CFS 作为 jobservice 和 registry 模块的持久化存储进行挂载:
`registry-nfs-pv.yaml`:
```yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: registry-registry
spec:
accessModes:
- ReadWriteMany
capacity:
storage: 10Gi
nfs:
path: /registry/registry
server: 10.10.0.15
persistentVolumeReclaimPolicy: Retain
storageClassName: ""
volumeMode: Filesystem
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: registry-registry
namespace: registry
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 10Gi
storageClassName: ""
volumeMode: Filesystem
volumeName: registry-registry
```
`jobservice-nfs-pv.yaml`:
```yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: registry-jobservice
spec:
accessModes:
- ReadWriteMany
capacity:
storage: 10Gi
nfs:
path: /registry/jobservice
server: 10.10.0.15
persistentVolumeReclaimPolicy: Retain
storageClassName: ""
volumeMode: Filesystem
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: registry-jobservice
namespace: registry
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 10Gi
storageClassName: ""
volumeMode: Filesystem
volumeName: registry-jobservice
```
注意:
* 确保创建的 CFS 与 TKE/EKS 集群在同一个 VPC。
* nfs 的 server ip 在 [CFS 控制台](https://console.cloud.tencent.com/cfs/fs) 可以查看,替换 yaml 中的 ip 地址。
* yaml 中如果指定 path ,确保提前创建好,且 `chmod 0777 <DIR>` 一下,避免因权限问题导致无法启动。