harbor的镜像复制
1. 理论部分
在较大的容器集群中,往往需要多个Registry服务器做负载均衡,可以采用主从发布模式,镜像只需要发布一次,就可以推送到多个Registry实例中。同时还支持双主复制和层次型的多级镜像发布,如下图所示:
在不同的Registry实例之间复制镜像是十分普遍的需求,过去常见的做法是通过拷贝镜像数据,比如定期通过rsync同步文件系统中镜像的数据,使用harbor,我们可以降低这种依赖,并提高灵活性
在控制方面,我们引入了一个新的组件,Job Service,用来对镜像复制任务进行管理。当以项目为单位进行复制时,会以镜像为单位生成一系列任务(job)由Job Service 调度管理,Job Service在执行任务的过程中将每个任务的状态更新到数据库中, 以便用户通过UI查看。大体结构如下图所示:
下面介绍一下Job Service 的实现,从外部看它也是通过REST API接收请求调度并执行任务,面临的问题主要有两点,首先,接收到大量复制请求时需要进行限流以免消耗过多IO资源;其次,复制策略有可能在任务执行过程中改变,比如失效,这就需要一种机制能从外界对运行中的任务进行干预。
我们通过任务队列,分发器(dispatcher)和worker pool实现了生产者消费者模型,利用Go语言内置的channel,每个任务会通过scheduler放到channel里,dispatcher 通过channel获得任务,同时,worker在工作结束后会被放入另一个channel, dispatcher 通过这个channel与worker配对(放在这个channel上的work都是没事干的,空闲的,dispatcher与这些空闲的work联系,分配任务),于是,空闲的worker通过dispatcher获得任务id并执行任务,这样可以很方便地通过worker pool(其实就是下边的channel中为worker提供的位置总和)中 worker数量来控制并发数:
对于另一个问题,每一个 worker内部是一个抽象的状态机(state machine),通过给不同状态注册处理器(handler)完成具体工作,同时,状态机可以受到干预,可以中途取消(cancel)任务,或在任务执行发生异常时将任务置为错误(error)状态丢弃或交给调度器(scheduler)重试。 另外由于状态机的状态是可定制的,这样就很方便扩展和调整。这里再说的直白一点,就是说worker可以给任务反馈不同的状态,针对上边说的第二个问题,如果复制策略失效了,这个时候worker就可以给这个任务一个pending的状态或者retry的状态,而不是直接丢弃,这样就可以解决复制策略变化带俩的负面影响。对于一个抽象的任务来说,它的状态转移如下图所示:
而对于具体远程同步镜像的任务来说,Running 状态会被进一步细分成多个子状态(这里展示的是pull的running的状态分析,其实就是作为接收同步镜像的一方,对于这一方来说,细分的过程如下),如下图所示:
首先, 从源Harbor实例下载相应tag的manifest,分析其所包含的blob,针对每一个blob,检查其在目标实例中是否已经存在,如果不存在,则同步此blob。最后,检查manifest在目标实例中是否已存在,如果不存在,则上传manifest。检查blob的存在性,可以有效减少不必要的网络流量。对同一个镜像中的每一个tag重复以上过程,就可以完成整个镜像的同步工作。
上图不太合适,应该把"has tag"去掉
关于manifest和blob的说明在docker部分“04-docker镜像仓库”中有详细说明,此处不做赘述
2. 操作部分
现在已经具备了两个安装好的harbor和一个docker客户端,主机及ip情况如下所示
主机 | ip | 角色 |
---|---|---|
host1 | 192.168.20.120 | docker |
host2 | 192.168.20.121 | harbor1 |
host3 | 192.168.20.122 | harbor2 |
在harbor1上创建项目kgc
在harbor1上设置复制目标
在harbor1上创建复制规则
现在我们去客户端配置的docker、登陆harbor,并上传镜像到kgc项目
[root@localhost ~]# vim /usr/lib/systemd/system/docker.service
14 ExecStart=/usr/bin/dockerd --insecure-registry 192.168.20.121
[root@localhost ~]# systemctl daemon-reload
[root@localhost ~]# systemctl restart docker
[root@localhost ~]# docker login -u admin -p Harbor12345 192.168.20.121
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
[root@localhost ~]# docker tag centos 192.168.20.121/kgc/centos:latest
[root@localhost ~]# docker push 192.168.20.121/kgc/centos
The push refers to repository [192.168.20.121/kgc/centos]
d69483a6face: Pushed
latest: digest: sha256:ca58fe458b8d94bc6e3072f1cfbd334855858e05e1fd633aa07cf7f82b048e66 size: 529
去harbor1上查看镜像是否上传
由上图可以看出,harbor1的镜像复制到了harbor2上,下面我们登陆harbor2进行查看验证
OK,大功告成,此处发现harbor2已具备镜像,主从复制成功
更多推荐
所有评论(0)