
3.3 高可用方案
随着Harbor被越来越多地部署在生产环境下,Harbor的高可用性成为用户关注的热点。对于一些大中型企业用户,如果只有单实例的Harbor,则一旦发生故障,其从开发到交付的流水线就可能被迫停止,无法满足高可用需求。
本节提供基于 Harbor 的不同安装包的高可用方案,目标是移除单点故障,提高系统的高可用性。其中,基于 Harbor Helm Chart 的高可用方案为官方验证过的方案,基于多Kubernetes集群和基于离线安装包的高可用方案为参考方案。
3.3.1 基于Harbor Helm Chart的高可用方案
Kubernetes 平台具有自愈(self-healing)能力,当容器崩溃或无响应时,可自动重启容器,必要时可把容器从失效的节点调度到正常的节点。本方案通过 Helm 部署 Harbor Helm Chart 到 Kubernetes 集群来实现高可用,确保每个Harbor组件都有多于一个副本运行在Kubernetes集群中,当某个Harbor容器不可用时,Harbor服务依然可正常使用。
1.安装Harbor的基本要求
在安装Harbor之前,需要满足如表3-22所示的基本要求。
表3-22

续表

2.高可用架构
为实现Harbor在Kubernetes集群中的高可用,Harbor的大部分组件都是无状态组件。有状态组件的状态信息被保存在共享存储而非内存中。这样一来,在Kubernetes集群中只需配置组件的副本个数,即可借助Kubernetes平台实现高可用。
◎ Kubernetes平台通过协调调度(Reconciliation Loop)机制使Harbor各组件达到期望的副本数,从而实现服务的高可用。
◎ PostgreSQL、Redis 集群实现数据的高可用性、一致性和前端会话(session)的共享。
◎ 共享数据存储实现Artifact数据的一致性。
关于存储层,这里推荐用户使用高可用的PostgreSQL和Redis集群存储应用信息,使用可持久化的存储或者高可用的对象存储来存储镜像或者Chart文件,如图3-5所示。

图3-5
3.配置Harbor Helm Chart
使用如下命令下载Harbor Helm Chart:

编辑配置文件values.yaml的参数,使其符合高可用的要求,详细配置请参考3.2.3节。
◎ Ingress rule:需要配置expose.ingress.hosts.core和expose.ingress.hosts.notary。
◎ External URL:配置externalURL为Harbor外部访问的URL地址。
◎ External PostgreSQL:设置database.type配置项的值为“external”,并填充数据库信息到database.external配置项中。外置的PostgreSQL需要预先为Harbor Core、Clair、Notary Server 及 Notary Signer 组件分别创建空数据库 registry、clair、notaryserver及notarysinger,并将创建的数据库信息配置到相应组件外置的数据库信息部分。Harbor在启动时,会自动创建对应数据库的数据库表。
◎ Storage:在部署Kubernetes集群时需要一个默认的StorageClass来提供持久卷用于存储Artifact、Chart及Job的日志。
(1)如果需要指定StorageClass,则需要配置persistence.persistentVolumeClaim.registry.storageClass、persistence.persistentVolumeClaim.chartmuseum.storageClass、persistence.persistent VolumeClaim.jobservice.storageClass。
(2)如果使用StorageClass,则无论是默认的还是自定义的StorageClass,都需要设置persistence.persistentVolumeClaim.registry.accessMode、persistence.persistentVolumeClaim.chartmuseum.accessMode、persistence.persistentVolumeClaim.jobservice.accessMode为ReadWriteMany,并确保持久卷在Node之间共享。
(3)如果使用已有的 PersistentVolumeClaims 存储数据,则需要设置 persistence.persistentVolumeClaim.registry.existingClaim、persistence.persistentVolumeClaim.chartmuseum.existingClaim、persistence.persistentVolumeClaim.jobservice.existingClaim。
(4)如果没有可在Node之间共享的PersistentVolumeClaims,则可以使用外置的对象存储来存储Artifact和Chart,使用数据库存储Job日志。需要设置persistence.imageChartStorage.type的值到相应的存储类型及设置jobservice.jobLogger为database。
◎ Replica:设置portal.replicas、core.replicas、jobservice.replicas、registry.replicas、chartmuseum.replicas、clair.replicas、trivy.replicas、notary.server.replicas及notary.signer.replicas的数值大于等于2,使得Harbor的各个组件均有多个副本。
4.安装Harbor Helm Chart
在完成Chart的配置后,使用Helm安装Harbor Helm Chart。请按照如下命令进行安装,其中my-release为部署名。
◎ Helm2:

◎ Helm3:

安装完成后,可通过“kubectl get pod”命令查看Pod的状态,如图3-6所示。

图3-6
3.3.2 多Kubernetes集群的高可用方案
3.3.1节介绍了使用Harbor Helm Chart在单个Kubernetes集群中搭建Harbor高可用环境的方案,其中实现了 Harbor 服务的高可用,但服务的整体可用性还是受到其运行所依赖的Kubernetes集群可用性的影响,如果集群崩溃,则会导致服务的不可用。在某些生产环境下会对可用性有更高的要求,因而基于多数据中心部署的多Kubernetes集群的高可用方案尤为重要。本节提供在多个跨数据中心的Kubernetes集群上构建Harbor高可用环境的参考方案。
1.安装Harbor
请参考3.3.1节依次安装Harbor到不同数据中心的Kubernetes集群中。注意:在多次安装过程中都需要保证values.yml配置项core.secretName和core.xsrfKey的值相同,其他配置项可根据不同数据中心的需求自行配置。
关于core.secretName和core.xsrfKey值相同的具体原因,详见3.3.3节关于多Harbor实例之间需要共享的文件或者配置部分的内容。
2.多Kubernetes集群的高可用架构
这里假设用户有两个数据中心,在两个数据中心的Kubernetes上分别安装好Harbor后,可实现主从(Active-Standby)模式的高可用方案,其中只有一个数据中心的Harbor提供服务,另一个数据中心的Harbor处于Standby(待用)状态。当处于Active状态的Harbor出现故障时,通过软件方式将处于Standby状态的Harbor激活,保证Harbor应用在短时间内恢复可访问状态。
在一个数据中心的Kubernetes集群外部,通过LTM(Local Traffic Manager)来实现服务负载均衡。在两个数据中心的负载均衡服务上层,通过GTM(Global Traffic Manager)来实现全局流量引导。GTM通过LTM汇报的状态监控数据中心服务状态,当GTM发现Active状态的数据中心发生故障时,可将网络流量切换至Standby状态的数据中心,如图3-7所示。

图3-7
从图3-7可以看到,Harbor在两个数据中心分别拥有独立的数据和内容存储。在两个数据中心之间配置了Harbor自带的远程复制功能,实现了对Artifact数据的复制(如镜像复制)。也就是说,在两个 Kubernetes 集群的数据存储上,通过远程复制来保证 Artifact的一致性。而对于两个数据中心之间的PostgreSQL和Redis的数据一致性,这里需要用户基于不同类型的数据中心提供自己的数据备份方案,目的是保持两个数据中心的PostgreSQL和Redis数据的一致性。
本方案使用了Harbor主从(Active-Standby)模式,由于采用了镜像等Artifact远程复制,在数据同步上有一定的延时,在实际使用中需要留意对应用的影响。对实时性要求不高的用户,可参考此方案搭建跨数据中心多Kubernetes集群的高可用方案。
3.3.3 基于离线安装包的高可用方案
基于Kubernetes集群搭建的高可用架构是Harbor官方提供的方案。但用户可能出于某种原因无法部署独立的Kubernetes集群,更希望创建基于Harbor离线安装包的高可用方案。
Harbor官方鼓励用户使用Kubernetes集群实现高可用,因为Harbor官方会维护Harbor的Helm Chart版本,并为社区提供技术支持。而基于离线安装包的高可用方案由于用户环境千差万别,需要用户去探索并解决各自环境下的问题。同时,由于官方未提供基于离线安装包的高可用方案,所以也不能提供相应的技术支持。
基于 Harbor 离线安装包搭建高可用系统是一项复杂的任务,需要用户具有高可用的相关技术基础,并深入了解 Harbor 的架构和配置。本节介绍的两种常规模式仅为参考方案,主要说明基于离线安装包实现高可用时,用户需要解决的问题和需要注意的地方。建议先阅读本章的其他内容,理解 Harbor 的安装及部署方式,在此基础上再结合各自的实际生产情况进行修改并实施。
在下面的两种方案中均使用了负载均衡器作为网关,需要用户自行安装并配置负载均衡器。同时,负载均衡器的搭建和配置及如何用负载均衡器调度多个 Harbor 实例,不在本节的讨论范围内。
方案1:基于共享服务的高可用方案
此方案的基本思想是多个Harbor实例共享PostgreSQL、Redis及存储,通过负载均衡器实现多台服务器提供Harbor服务,如图3-8所示。

图3-8
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下载的证书就是负载均衡器的证书,如图3-9所示。

图3-9
2)外置数据库的配置
用户需要自行创建PostgreSQL共享实例或者集群,并将其信息配置到每个Harbor实例外置的数据库配置项中。注意:外置PostgreSQL需要预先为Harbor Core、Clair、Notary Server及Notary Signer组件分别创建空数据库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之间的这两个文件不同,在认证过程中就可能发生随机性的成功或失败。成功的原因是请求被负载均衡器转发到创建该Bearer token的实例中,该实例可以校验自身创建的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 Request Forgery),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:基于复制策略的高可用方案
此方案的基本思想是多个Harbor实例使用Harbor原生的远程复制功能实现Artifact的一致性,通过负载均衡器实现多台服务器提供单一的Harbor服务,如图3-10所示。

图3-10
负载均衡器的配置及多实例之间需要共享的资源和配置方法同方案1。
方案2与方案1不同的是,在安装Harbor实例时不需要指定外置的PostgreSQL、Redis及存储,每个实例都使用自己独立的存储。Harbor 的多实例之间通过远程复制功能实现Artifact数据的一致性。关于PostgreSQL和Redis的数据一致性问题,需要用户自行实现数据同步的解决方案。基于复制的多实例解决方案,其实时性不如基于共享存储的方案,但相比之下搭建更为简单,用户使用Harbor离线安装包提供的PostgreSQL、Redis即可。