根据harbor官方的描述,harbor高可用方案有以下几种:
- 通过helm chart的方式部署于kubernetes中,以多副本的形式运行,借助k8s自愈性维护自身状态,通过pvc来存储数据,连接外置的PostgreSQL和Redis集群。
- 多个harbor实例共享PostgreSQL、Redis及存储,上层搭建负载均衡器。
- harbor组件单独部署,基于复制策略实现Artifact的一致性,通过上层负载均衡器提供统一入口,PostgreSQL和Redis的数据一致性需要用户自己解决。
可以看到第三种方式是最简单的,下面以第三种方式搭建harbor2.4.2环境。
环境描述
ip地址 | 系统版本 | 内核版本 | cpu(C) | mem(G) | disk(GB) |
---|---|---|---|---|---|
192.168.100.10 | CentOS 7.6.1810 | 3.10.0-957.el7.x86_64 | 2 | 4 | 40 |
192.168.100.11 | CentOS 7.6.1810 | 3.10.0-957.el7.x86_64 | 2 | 4 | 40 |
高可用部署
以下步骤在两台测试机器分别执行。
基础环境准备
1 | systemctl status firewalld |
安装docker
1 | yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo |
安装docker-compose
1 | curl -SL https://github.com/docker/compose/releases/download/v2.4.0/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose |
安装harbor
1 | wget https://github.com/goharbor/harbor/releases/download/v2.4.2/harbor-offline-installer-v2.4.2.tgz |
配置harbor
1 | cd harbor |
根据本地环境实际情况来修改harbor.yml文件。
https需要涉及到证书操作,暂时先将https部分注释掉,下面是对比原始文件修改的部分。
hostname:处改成对应节点的ip地址
1 | diff harbor.yml.tmpl harbor.yml |
安装harbor
执行./prepare
,下载镜像,并根据harbor.yml生成docker-compose.yml文件。
1 | ./prepare |
harbor离线包解压后,进入目录中看到的
harbor.v2.4.2.tar.gz
为对应组件的镜像,可提前通过docker load到本地。
执行./install.sh
进行安装。
1 | ./install.sh |
使用docker-compose ps 命令可以查看容器启动情况。
1 | docker-compose ps |
浏览器访问http:<$节点ip>:80
部署keepalived
keepalived是一个高可用软件,通过VRRP协议来防止服务单点故障。
1 | yum install -y keepalived |
按需编辑配置文件。
此次测试中,keepalived并没有加检测harbor组件状态的脚本
1 | cat > /etc/keepalived/keepalived.conf <<EOF |
启动keepalived
。
1 | systemctl enable keepalived && systemctl start keepalived |
此时分别查看两台测试机的网卡信息,可以看到VIP已经绑定在了一个节点上。
1 | ip a|grep ens33 |
设置复制策略
由于 v2.0 版本中的主要 API 更改以支持OCI。您无法从 Harbor v1.x 复制到 v2.0 及更高版本,也无法将带有manifest list的artifacts 从 v2.0 及更高版本复制到 v1.x。
添加远程仓库
分别浏览器访问两台镜像仓库地址,系统管理
-仓库管理
-新建目标
,填写目标镜像仓库信息。
设置复制策略
系统管理
-复制管理
-新建规则
字段 | 说明 |
---|---|
复制模式 | 支持主动推送和基于拉取策略 |
资源过滤器 | 支持基于tag和标签的过滤(匹配/排除),资源包括all、image、artifact |
仓库扁平化 | 在复制image时支持处理image层次结构,可选择展平的级别 |
触发模式 | 手动(删除操作不会被复制); 定时(通过定义 crontab定期复制资源,删除操作不会被复制) ;事件驱动(基于推送、重新标记和删除操作) |
带宽 | 设置每个复制任务的最大网络带宽,须注意并发执行数,每个job-service pod默认值为10 |
测试过程与问题
测试的过程大致描述下,两个镜像仓库分别设置了基于事件驱动的复制策略:
推送一些镜像到其中一个节点,此时可以看到很快就同步到了另外一台;
推送一个较大的镜像,再推送的过程中进行VIP切换,此时推送的过程会中断,再次执行推送任务时可正常进行(测试时会有切换VIP再次推送镜像卡死现象,等待大概5分钟后可恢复)。
关闭其中一台镜像仓库节点,推送一些镜像(此时都存储在另一台),过段时间后恢复关闭的节点,此时查看复制任务都还处于失败的状态,并且任务都不会再次执行。须点击复制按钮触发任务来完成。
附上一些任务截图。
垃圾清理
最早之前harbor垃圾清理要在后台跑一个程序实现,当前已经集成到了页面上。
harbor提供了项目级别的tag保留策略,所有未标记的artifacts 都将被删除。
为避免损坏上传artifact,垃圾收集引入了一个时间窗口(2 小时)来保留最近上传的图层layers。垃圾收集不会扫描时间窗口中具有时间戳的清单和 blob 文件。目前并未提供修改该时间窗口的地方。
为了避免过于频繁地触发垃圾收集过程,GC Now按钮的可用性受到限制。垃圾收集每分钟只能运行一次。
artifact
查阅官方文档时很多地方提到artifact,对比新老版本的界面也发现了其中的不同
旧版本(v1.4.0)
测试版本(v2.4.2)
可以看到artifacts和images的digests保持一致
点击artifact的详情查看如下
测试过程中的问题
因为测试是搭建了两个独立的harbor,镜像层面可以通过设置复制策略解决,虽然高版本中取消了之前的“即刻”模式,也就导致当一台机器异常后,直到恢复时的这段时间产生的镜像差异不会自动的同步,需要手动的重启下复制策略,或者是设置个基于定时任务的复制策略。
对于用户管理等功能是存储在数据库中的,低版本是mysql,高版本变为了postgreSQL,尝试同步两台镜像仓库的数据库来使用户管理等数据保持一致(暴力的方式直接同步宿主机上的PG数据目录),但此时会引发另一些问题:
页面上看到的数据都会被覆盖,比如复制策略被覆盖了,需要重新添加;项目下的镜像仓库、artifacts等被覆盖,此时推送镜像到一个镜像仓库,另一台镜像仓库的UI也会刷新该镜像的信息,导致即使配置了复制策略,也会运行失败。
从docker pull镜像流程可知,未在仓库中找到对应的manifest。
高可用方案来说,多harbor实例连接外置redis与PostgreSQL集群,建立统一访问入口,挂载共享存储目前还是最稳定且推荐的做法。
参考
https://goharbor.io/docs/2.4.0/
https://blog.csdn.net/m0_57776598/article/details/123698967
https://www.jianshu.com/p/fad6b6fb4599
https://github.com/opencontainers/image-spec/blob/main/manifest.md
https://github.com/opencontainers/image-spec/blob/main/config.md