在早期的版本中,Harbor的功能主要围绕Docker镜像的管理展开。Harbor的开发者希望让用户通过一个统一的地址同时进行推送和拉取,以及利用图形界面对镜像进行浏览和其他管理工作。关于推送和拉取这一部分功能,Docker公司开源的Distribution项目应用广泛,可以支持不同类型的存储,而且比较成熟和稳定。因此,Harbor选择由Distribution处理客户端镜像的推送和拉取请求,并通过围绕Distribution增加其他组件的方式来提供管理功能。这种方式一方面减少了开发工作量;另一方面由于Distribution基本上是镜像仓库的事实标准,所以保证了镜像的推送和拉取功能的稳定。后来,随着版本的迭代,Harbor逐渐减少了对Distribution的依赖,但是在镜像的读写、存取等功能上,Distribution仍然是Harbor和用户存储之间的桥梁。
如图2-11所示是Harbor 2.0的架构示意图,从上到下可分为代理层、功能层和数据层。
其中代理层功能比较简单,可将其理解为Harbor的门户(gateway)。代理层实质上是一个Nginx反向代理,负责接收不同类型的客户端的请求,包括浏览器、用户脚本、Docker及其他Artifact命令行工具如Helm、ORAS等,并根据请求类型和URI转发给不同的后端服务进行处理。它保证了Harbor的所有功能都是通过单一的主机名(hostname)暴露的。功能层是一组HTTP服务,提供Harbor的核心功能,包括核心功能组件Core、Portal、JobService、Docker Distribution和RegistryCtl,以及可选组件Notary、ChartMuseum和镜像扫描器。在实际部署中,除了Notary组件包括server和signer这两个容器,其他组件都由一个容器组成。这些组件被设计为无状态的组件,以便通过多实例的方式进行水平扩展。
数据层包括PostgreSQL关系型数据库、Redis缓存服务,以及用户提供的存储服务(文件系统、对象存储)。这些服务被各个功能组件共享,用于存储不同场景的应用数据。由于功能组件都是无状态的,所以在规划 Harbor 的高可用部署时,只要保证应用数据一致而且不会丢失就可以了。组件可划分为两大类:核心组件和可选组件,将在下面两节中介绍。