1 背景
随着harbor越来越多的部署在生产环境,harbor的高可用越来越收到人们的关注。对于大中型企业用,如果只有单示例的Harbor,则一旦发生故障,其从开发到交付的流水线就可能被迫停止,无法满足生产高可用的需求。
harbor的高可用目标是消除单点故障。提高系统的高可用性。根据安装方式的不同,高可用分为下面三种:
- 基于Harbor Helm Chart的高可用方案,此方案为官方验证过的方案,推荐方案
- 基于多kubernetes的集群的高可用方案
- 基于离线安装包的高可用方案
从模式上讲,有下面方案实现harbor的HA
- Shared storage
- Replication(no shared storage)
- Using other HA platform
2 方案
2.1 基于Harbor Helm Chart的高可用方案
Kubernetes 平台具有自愈(self-healing)能力,当容器崩溃或无响应时,可自动重启容器,必要时可把容器从失效的节点调度到正常的节点。本方案通过 Helm 部署 Harbor Helm Chart 到 Kubernetes 集群来实现高可用,确保每个Harbor组件都有多于一个副本运行在Kubernetes集群中,当某个Harbor容器不可用时,Harbor服务依然可正常使用。
2.1.1 前置要求
- Kubernetes cluster 1.10+
- Helm 2.8.0+
- High available ingress controller (Harbor does not manage the external endpoint)
- High available PostgreSQL 9.6+ (Harbor does not handle the deployment of HA of database)
- High available Redis (Harbor does not handle the deployment of HA of Redis)
- PVC that can be shared across nodes or external object storage
具体说明如下表:
软件 | 版本 | 描述 |
---|---|---|
kubernetes | 1.10及以上版本 | kubernetes集群组件版本 |
Helm | 2.8.0及以上版本 | Helm版本 |
高可用的Ingress Controller | 用户自行选择 | harbor不会管理external endpoint,需要用户自行准备。如果开启Interanl TLS,则需要使用kubernetes官方维护的Nginx Ingress Controller,因为Internal TLS需要annotation,而只有Nginx Ingress Controller可以识别加载Internal TLS的annotation |
高可用的PostgreSQL集群 | 9.6及以上版本 | harbor不负责数据库的高可用部署 |
高可用的redis | 用户自行选择 | harbor不负责redis的高可用部署 |
可跨节点共享的PVC或外部对象存储 | 用户自行选择 | 需用户自行准备 |
2.1.2 高可用架构
Harbor的大多数组件为无状态应用,因此我们可以通过简单的增加pod的副本数量,来保证组件分布在多个worker节点,同时借助kubernetes的service机制,来确保跨pod的连通性。
有状态组件的状态信息被保存在共享存储而非内存中。
对于存储层,用户需要提供PostgreSQL,Redis集群的高可用,用于存储应用数据。PVC或对象存储用于存储镜像与charts数据。
- Kubernetes平台通过协调调度(Reconciliation Loop)机制使Harbor各组件达到期望的副本数,从而实现服务的高可用。
- PostgreSQL、Redis 集群实现数据的高可用性、一致性和前端会话(session)的共享。
- 共享数据存储实现Artifact数据的一致性。
架构图如下图所示
2.1.3 下载Chart
helm repo add harbor https://helm.goharbor.io
helm fetch harbor/harbor --untar
2.1.4 配置
在values.yaml
文件中配置下面的配置项,也可以通过运行helm install
命令的时候通过--set
参数指定配置:
-
Ingress rule :需要配置
expose.ingress.hosts.core
和expose.ingress.hosts.notary
. -
External URL :配置
externalURL
为Harbor外部访问的URL地址 -
External PostgreSQL :设置
database.type
为external
并将数据库信息写到database.external
配置部分中。本部分还需要要手动为Harbor core
,Notary server
andNotary signer
创建三个空的数据库,并将创建的数据库信息配置到相应组件外置的数据库信息部分。Harbor在启动时,会自动创建对应数据库的数据库表。 -
External Redis :设置
redis.type
为external
并在redis.external
配置redis的连接信息.harbor在2.1.0版本支持sentinel
模式,你可以通过设置sentinel_master_set
和host
为<host_sentinel1>:<port_sentinel1>,<host_sentinel2>:<port_sentinel2>,<host_sentinel3>:<port_sentinel3>
来开启sentinel模式。参考这个指南 guide 在redis前配置HAProxy,来暴露单一的入口。
-
Storage :默认情况下,K8s集群中需要有一个默认的
StorageClass
,用来存储镜像,chart和job日志.如果你想使用指定的
StorageClass
, 需要配置persistence.persistentVolumeClaim.registry.storageClass
,persistence.persistentVolumeClaim.chartmuseum.storageClass
andpersistence.persistentVolumeClaim.jobservice.storageClass
.如果你想同时使用默认的和指定的
StorageClass
, 设置persistence.persistentVolumeClaim.registry.accessMode
,persistence.persistentVolumeClaim.chartmuseum.accessMode
andpersistence.persistentVolumeClaim.jobservice.accessMode
为ReadWriteMany
, 并确保不同pod之间能共享persistent volumes.你也可以使用现存的 PVCs 来存储数据, 需要设置
persistence.persistentVolumeClaim.registry.existingClaim
,persistence.persistentVolumeClaim.chartmuseum.existingClaim
andpersistence.persistentVolumeClaim.jobservice.existingClaim
.如果你没有跨节点共享的PVCs, 你可以使外部对象存储镜像和Chart,将job日志存储在数据库。Set the
persistence.imageChartStorage.type
to the value you want to use and fill the corresponding section and setjobservice.jobLogger
todatabase
. -
Replica :设置
portal.replicas
,core.replicas
,jobservice.replicas
,registry.replicas
,chartmuseum.replicas
,notary.server.replicas
andnotary.signer.replicas
ton
(n
>=2).使得Harbor的各个组件均有多个副本
2.1.5 安装Harbor Helm Chart
在完成Chart的配置后,使用Helm安装Harbor Helm Chart。请按照如下命令进行安装,其中my-release为部署名。
Helm 2:
helm install --name my-release .
Helm 3:
helm install my-release .
安装完成后,可通过“kubectl get pod”命令查看Pod的状态。
2.2 多Kubernetes集群的高可用方案
2.1节介绍了使用Harbor Helm Chart在单个Kubernetes集群中搭建Harbor高可用环境的方案,其中实现了 Harbor 服务的高可用,但服务的整体可用性还是受到其运行所依赖的Kubernetes集群可用性的影响,如果集群崩溃,则会导致服务的不可用。在某些生产环境下会对可用性有更高的要求,因而基于多数据中心部署的多Kubernetes集群的高可用方案尤为重要。本节提供在多个跨数据中心的Kubernetes集群上构建Harbor高可用环境的参考方案。
2.2.1 安装Harbor
请参考2.1节依次安装Harbor到不同数据中心的Kubernetes集群中。注意:在多次安装过程中都需要保证values.yml配置项core.secretName和core.xsrfKey的值相同,其他配置项可根据不同数据中心的需求自行配置。关于core.secretName和core.xsrfKey值相同的具体原因,详见2.3节关于多Harbor实例之间需要共享的文件或者配置部分的内容。
2.2.2 多Kubernetes集群的高可用架构
这里假设用户有两个数据中心,在两个数据中心的Kubernetes上分别安装好Harbor后,可实现主从(Active-Standby)模式的高可用方案,其中只有一个数据中心的Harbor提供服务,另一个数据中心的Harbor处于Standby(待用)状态。当处于Active状态的Harbor出现故障时,通过软件方式将处于Standby状态的Harbor激活,保证Harbor应用在短时间内恢复可访问状态。
在一个数据中心的Kubernetes集群外部,通过LTM(Local Traffic Manager)来实现服务负载均衡。在两个数据中心的负载均衡服务上层,通过GTM(Global TrafficManager)来实现全局流量引导。GTM通过LTM汇报的状态监控数据中心服务状态,当GTM发现Active状态的数据中心发生故障时,可将网络流量切换至Standby状态的数据中心,如下图所示所示。
从上图可以看到,Harbor在两个数据中心分别拥有独立的数据和内容存储。在两个数据中心之间配置了Harbor自带的远程复制功能,实现了对Artifact数据的复制(如镜像复制)。也就是说,在两个 Kubernetes 集群的数据存储上,通过远程复制来保证 Artifact的一致性。而对于两个数据中心之间的PostgreSQL和Redis的数据一致性,这里需要用户基于不同类型的数据中心提供自己的数据备份方案,目的是保持两个数据中心的PostgreSQL和Redis数据的一致性。本方案使用了Harbor主从(Active-Standby)模式,由于采用了镜像等Artifact远程复制,在数据同步上有一定的延时,在实际使用中需要留意对应用的影响。对实时性要求不高的用户,可参考此方案搭建跨数据中心多Kubernetes集群的高可用方案。
2.3 基于离线安装包的高可用方案
基于Kubernetes集群搭建的高可用架构是Harbor官方提供的方案。但用户可能出于某种原因无法部署独立的Kubernetes集群,更希望创建基于Harbor离线安装包的高可用方案。
Harbor官方鼓励用户使用Kubernetes集群实现高可用,因为Harbor官方会维护Harbor的Helm Chart版本,并为社区提供技术支持。而基于离线安装包的高可用方案由于用户环境千差万别,需要用户去探索并解决各自环境下的问题。同时,由于官方未提供基于离线安装包的高可用方案,所以也不能提供相应的技术支持。
基于 Harbor 离线安装包搭建高可用系统是一项复杂的任务,需要用户具有高可用的相关技术基础,并深入了解 Harbor 的架构和配置。本节介绍的两种常规模式仅为参考方案,主要说明基于离线安装包实现高可用时,用户需要解决的问题和需要注意的地方。建议先阅读本章的其他内容,理解 Harbor 的安装及部署方式,在此基础上再结合各自的实际生产情况进行修改并实施。
在下面的两种方案中均使用了负载均衡器作为网关,需要用户自行安装并配置负载均衡器。同时,负载均衡器的搭建和配置及如何用负载均衡器调度多个 Harbor 实例,不在本节的讨论范围内。
2.3.1 基于共享服务的高可用方案
此方案的基本思想是多个Harbor实例共享PostgreSQL、Redis及存储,通过负载均衡器实现多台服务器提供Harbor服务,如下图所示。
1 关于负载均衡器的设置
在安装Harbor实例的过程中,需要设置每个Harbor实例的配置文件的external_url项,把该项地址指定为负载均衡器的地址。通过该项指定负载均衡器的地址后,Harbor将不再使用配置文件中的hostname作为访问地址。客户端(Docker和浏览器等)通过external_url提供的地址(即负载均衡器的地址)访问后端服务的API。如果不设置该值,则客户端会依据hostname的地址来访问后端服务的API,负载均衡在这里并没有起到作用。也就是说,服务访问并没有通过负载均衡直接到达后端,当后端地址不被外部识别时(如有NAT或防火墙等情况),服务访问还会失败。
Harbor 实例在使用了 HTTPS,特别是自持证书时,需要配置负载均衡器信任其后端每个Harbor实例的证书。同时,需要将负载均衡器的证书放置于每个Harbor实例中,其位置为harbor.yml配置项中data_volume指定路径下的“ca_download”文件夹中,该文件夹需要手动创建。这样,用户从任意Harbor 实例的UI下载的证书就是负载均衡器的证书,如下图所示。
2 外置数据库的配置
用户需要自行创建PostgreSQL共享实例或者集群,并将其信息配置到每个Harbor实例外置的数据库配置项中。注意:外置PostgreSQL需要预先为Harbor Core、Clair、Notary Server及NotarySigner组件分别创建空数据库registry、clair、notary_server及notary_singer,并将创建的数据库信息配置到相应组件外置的数据库信息部分。Harbor在启动时,会自动创建对应数据库的数据库表。
3 外置Redis的配置
用户需要自行创建Redis共享实例或者集群,并将其信息配置到每个Harbor实例外置的Redis配置项中。
4 外置存储的配置
用户需要提供本地或云端共享存储,并将其信息配置到每个 Harbor 实例的外置存储配置项中。
5 多个Harbor实例之间需要共享的文件或者配置
基于离线安装包安装的高可用方案需要保证以下文件在多个实例之间的一致性。同时,由于这些文件是在各个 Harbor 实例的安装过程中默认生成的,所以需要用户手动复制这些文件来保证一致性。
private_key.pem和root.crt文件
Harbor在客户端认证流程中(参考第5章)提供了证书和私钥文件供Distribution创建和校验请求中的Bearer token。在多实例Harbor的高可用方案中,多实例之间需要做到任何一个实例创建的Bearer token都可被其他实例识别并校验,也就是说,所有实例都需要使用相同的private_key.pem和root.crt文件。
如果多实例Harbor之间的这两个文件不同,在认证过程中就可能发生随机性的成功或失败。成功的原因是请求被负载均衡器转发到创建该Bearertoken的实例中,该实例可以校验自身创建的bearer token;失败的原因是请求被负载均衡器转发到非创建该Bearer token的实例中,该实例无法解析非自身创建的token,从而导致认证失败。因为private_key.pem文件同时用于机器人账户的JWT token的校验,所以如果不共享此文件,机器人账户的登录也会发生随机性的成功或失败,原因同上。
private_key.pem文件位于harbor.yml配置项data_volume 指定路径的“secret/core”子目录下。root.crt文件位于harbor.yml配置项data_volume 指定路径的“secret/registry”子目录下。
csrf_key
为防止跨站攻击(Cross Site RequestForgery),Harbor启用了csrf的token校验。Harbor会生成一个随机数作为csrf的token附加在cookie中,用户提交请求时,客户端会从cookie中提取这个随机数,并将其作为csrf的token一并提交。Harbor会依据这个值是否为空或者无效来拒绝该访问请求。那么,多实例之间需要做到任何一个实例创建的token都可被其他任意实例成功校验,也就是需要统一各个实例的csrf token私钥值。
该配置位于Harbor安装目录下的“common/config/core/env”文件中,用户需要把一个Harbor实例的值手动复制到其他实例上,使该值在所有实例上保持一致。
注意:手动修改以上文件或配置时,均需要通过docker-compose重启Harbor实例以使配置生效。另外,如果后续要使用Harbor安装包中的prepare脚本,则需要重复上述手动复制过程,因为该脚本会随机创建字符串并改写以上文件或配置,导致手动复制的文件或配置被覆盖而失效。
2.3.2 基于复制策略的高可用方案
此方案的基本思想是多个Harbor实例使用Harbor原生的远程复制功能实现Artifact的一致性,通过负载均衡器实现多台服务器提供单一的Harbor服务,如下图所示。
负载均衡器的配置及多实例之间需要共享的资源和配置方法同方案1。方案2与方案1不同的是,在安装Harbor实例时不需要指定外置的PostgreSQL、Redis及存储,每个实例都使用自己独立的存储。Harbor 的多实例之间通过远程复制功能实现Artifact数据的一致性。关于PostgreSQL和Redis的数据一致性问题,需要用户自行实现数据同步的解决方案。基于复制的多实例解决方案,其实时性不如基于共享存储的方案,但相比之下搭建更为简单,用户使用Harbor离线安装包提供的PostgreSQL、Redis即可。
Reference
- https://www.cncf.io/wp-content/uploads/2020/08/harbor-cncf-webinar-1.pdf
- Harbor权威指南,张海宁等
- https://goharbor.io/docs/2.3.0/install-config/harbor-ha-helm/