Harbor高可用理论及实践(汇聚篇)
一、理论概述
什么是harbor
Harbor是一个用于存储和分发Docker镜像的企业级Registry服务器,可以用来构建企业内部的Docker镜像仓库。
harbor是基于docker registry进行了相应的企业级扩展,从而获得了更加广泛的应用,新特性包括:管理用户界面,基于角色的访问控制 ,AD/LDAP集成以及审计日志等。
harbor要解决的问题
以Docker为代表的容器技术的出现,改变了传统的交付方式。通过把业务及其依赖的环境打包进Docker镜像,解决了开发环境和生产环境的差异问题,提升了业务交付的效率。如何高效地管理和分发Docker镜像?是众多企业需要考虑的问题。
有了docker自带的registry为什么还要用harbor
- harbor的安全机制
可以根据角色灵活的进行权限控制,如访客只需给pull权限即可
- harbor的镜像同步机制
为什么需要镜像同步
1. 对系统稳定性要求高,需要多个仓库保证高可用性
2. 更常用的场景是,在企业级软件环境中,会在软件开发的不同阶段存在不同的镜像仓库
传统镜像同步方式是采用RSYNC服务来定义两个仓库之间的镜像数据同步!!
harbor同步机制
1. 采用用Harbor自己的API来进行镜像下载和传输,作到与底层存储环境解耦。
2. 利用任务调度和监控机制进行复制任务的管理,保障复制任务的健壮性。在同步过程中,如果源镜像已删除,Harbor会自动同步删除远端的镜像。在镜像同步复制的过程中,Harbor会监控整个复制过程,遇到网络等错误,会自动重试。
3. 提供复制策略机制保证项目级的复制需求。在Harbor中,可以在项目中创建复制策略,来实现对镜像的同步。与Docker Registry的不同之处在于,Harbor的复制是推(PUSH)的策略,由源端发起,而Docker Registry的复制是拉(PULL)的策略,由目标端发起。
- 可利用图形界面进行镜像等等的管理
- 提供分层传输机制,优化网络传输
Docker镜像是是分层的,而如果每次传输都使用全量文件(所以用FTP的方式并不适合),显然不经济。必须提供识别分层传输的机制,以层的UUID为标识,确定传输的对象。
harbor的架构组件
- Harbor在架构上主要由五个组件构成:
1. Proxy:Harbor的registry,UI, token等服务,通过一个前置的反向代理统一接收浏览器、Docker客户端的请求,并将请求转发给后端不同的服务。
2. Registry: 负责储存Docker镜像,并处理docker push/pull 命令。由于我们要对用户进行访问控制,即不同用户对Dockerimage有不同的读写权限,Registry会指向一个token服务,强制用户的每次docker pull/push请求都要携带一个合法的token,Registry会通过公钥对token 进行解密验证。
3. Core services: 这是Harbor的核心功能,主要提供以下服务:
UI:提供图形化界面,帮助用户管理registry上的镜像(image), 并对用户进行授权。
webhook:为了及时获取registry 上image状态变化的情况, 在Registry上配置webhook,把状态变化传递给UI模块。
token 服务:负责根据用户权限给每个docker push/pull命令签发token. Docker 客户端向Regiøstry服务发起的请求,如果不包含token,会被重定向到这里,获得token后再重新向Registry进行请求。
4. Database:为core services提供数据库服务,负责储存用户权限、审计日志、Dockerimage分组信息等数据。
5. Log collector:为了帮助监控Harbor运行,负责收集其他组件的log,供日后进行分析。
- Harbor每个组件实现方式
Harbor的每个组件都是以Docker容器的形式构建的,因此很自然地,我们使用Docker Compose来对它进行部署。
在源代码中(https://github.com/vmware/harbor), 用于部署Harbor的Docker Compose 模板位于/Deployer/docker-compose.yml. 打开这个模板文件,会发现Harbor由5个容器组成:
1. proxy:由Nginx 服务器构成的反向代理。
2. registry:由Docker官方的开源registry 镜像构成的容器实例。
3. ui: 即架构中的coreservices, 构成此容器的代码是Harbor项目的主体。
4. mysql: 由官方MySql镜像构成的数据库容器。
5. log: 运行着rsyslogd的容器,通过log-driver的形式收集其他容器的日志。
这几个容器通过Docker link的形式连接在一起,这样,在容器之间可以通过容器名字互相访问。对终端用户而言,只需要暴露proxy (即Nginx)的服务端口。
Harbor工作原理
由于只说干货比较抽象,我们用具体的命令作为表现形式研究工作流程
- docker login登录命令
假设我们将Harbor部署在IP 为192.168.1.10的机器上。用户通过docker login命令向这个Harbor服务发起登录请求:
docker login 192.168.1.10
当用户输入所需信息并点击回车后,Docker 客户端会向地址 “192.168.1.10/v2/” 发出HTTP GET请求。 Harbor的各个容器会通过以下步骤处理:
1.. 1.10机器上收到该请求,会有映射到宿主机80端口的容器接收到。根据匹配规则,容器中Nginx将请求转发给registry容器;
2.. registry容器,由于基于token认证,registry返回错误代码401,提示docker客户端访问token去访问token服务绑定的URL。在harbor中,这个URL指向的是CoreServices(核心服务组件);
3.. Docker 客户端在接到这个错误代码后,会向token服务的URL发出请求,并根据HTTP协议的BasicAuthentication规范,将用户名密码组合并编码,放在请求头部(header);
4.. 这个请求通过1.10:80发送到proxy容器后,Nginx根据规则吧请求转发给UI容器,UI容器监听token服务网址的处理程序,接收到请求后,将请求头解码,得到了用户名和密码;
5.. 得到用户名、密码后,UI容器中的代码会查询数据库,将用户名、密码与mysql容器中的数据进行比对。比对成功的话,UI容器返回表示成功状态吗,用秘钥生成token,放在响应体中返回给docker客户端
docker push 192.168.1.10/library/hello-word
1.. docker客户端重复login的过程,首先发送请求到registry,之后得到token服务的地址;
2.. 之后,docker客户端在访问UI容器的token服务时会提供额外的信息,指明它要申请一个对library/hello-word进行push操作的token;
3.. token服务在经过Nginx转发得到了这个请求后,访问数据库合适当前用户是否有权限对该image进行push操作。如果有权限,会把image信息以及push动作进行编码,并且用私钥签名,生成token返回给docker客户端
4.. 得到token之后docker客户端将token放在请求头部,向registry发出请求,师徒开始推送image。registry收到请求后会用公钥解码token并且进行核对,一切成功后,image传输就开始了
二、部署harbor及其主从复制
环境
主机名 | IP地址 | 角色 |
---|---|---|
harbor1 | 192.168.111.3 | harbor仓库 |
harbor2 | 192.168.111.4 | harbor备份仓库 |
client | 192.168.111.5 | docker客户端 |
本案例搭建harbor镜像仓库的高可用,但是由于harbor并没有相应官方方案推荐,本案例只是简单采用主主高可用,并且基于keepalived的VIP实现
- 部署docker
- 三台机器部署社区版docker
[root@localhost ~]# yum -y install yum-utils device-mapper-persistent-data lvm2
#安装依赖
[root@localhost ~]# wget -O /etc/yum.repos.d/docker-ce.repo https://download.docker.com/linux/centos/docker-ce.repo
#下载docker的repo
[root@localhost ~]# yum -y install docker-ce
[root@localhost ~]# mkdir /etc/docker
[root@localhost ~]# vim /etc/docker/daemon.json
{
"registry-mirrors":["https://*******.mirror.aliyuncs.com"]
}
#阿里云镜像加速
#systemctl start docker
地址需要个人前往阿里云获得,参考这篇文档
在本案例中,一开始我初心是想要部署一个基于https的高可用harbor镜像仓库,但是后来生成证书时发现应该是必须要用域名才可以,但是如果用域名的话,我的高可用VIP如何实现,故去除https的配置,用普通连接
- 部署harbor
- 两个harbor部署
从 github harbor 官网 release 页面下载指定版本的安装包。
1、在线安装包
$ wget https://github.com/vmware/harbor/releases/download/v1.1.2/harbor-online-installer-v1.1.2.tgz
$ tar xvf harbor-online-installer-v1.1.2.tgz
2、离线安装包
$ wget https://github.com/vmware/harbor/releases/download/v1.1.2/harbor-offline-installer-v1.1.2.tgz
$ tar xvf harbor-offline-installer-v1.1.2.tgz
[root@harbor1 ~]# mv harbor /usr/local/
[root@harbor1 ~]# vim /usr/local/harbor/harbor.cfg
hostname = 192.168.111.3
ui_url_protocol = http
[root@harbor2 cert]# vim /usr/local/harbor/harbor.cfg
hostname = 192.168.111.4
ui_url_protocol = http
- 两个harbor部署docker-compose
curl -L https://github.com/docker/compose/releases/download/1.18.0/docker-compose-`uname -s`-`uname -m`
[root@harbor2 ~]# mv docker-compose /usr/local/bin/docker-compose
[root@harbor2 ~]# chmod +x !$
chmod +x /usr/local/bin/docker-compose
- 启动配置
[root@harbor2 ~]# sh /usr/local/harbor/install.sh
[root@harbor1 ~]# sh /usr/local/harbor/install.sh
#此过程比较慢
浏览器访问测试http://192.168.111.3/
和http://192.168.111.4/
- 测试
[root@localhost anchors]# docker pull cirros
[root@localhost anchors]# docker login 192.168.111.3
Username: admin
Password:
[root@localhost anchors]# docker tag cirros:latest 192.168.111.3/joinbest1/cirros:test1
[root@localhost anchors]# docker push 192.168.111.3/joinbest1/cirros:test1
The push refers to repository [192.168.111.3/joinbest1/cirros]
abbd6d6ac643: Pushed
75b99987219d: Pushed
0cc237193a30: Pushed
test1: digest: sha256:96137d51e0e46006243fa2403723eb47f67818802d1175b5cde7eaa7f19446bd size: 943
- 部署主主复制(实现任何一个镜像仓库有改动,都要同步到另一侧)
两端都是如此
这时,在对端harbor已经可以看到刚才创建的测试镜像了。
由于部署是主主,对端harbor仓库也要进行以上操作
- 小测试
[root@localhost anchors]# docker tag cirros:latest 192.168.111.4/joinbest1/cirros:test2
[root@localhost anchors]# docker push 192.168.111.4/joinbest1/cirros:test2
The push refers to repository [192.168.111.4/joinbest1/cirros]
abbd6d6ac643: Layer already exists
75b99987219d: Layer already exists
0cc237193a30: Layer already exists
test2: digest: sha256:96137d51e0e46006243fa2403723eb47f67818802d1175b5cde7eaa7f19446bd size: 943
#上面的部分输出含义是该层数据已经存在,但是不影响,因为在harbor中并不是每个镜像都要全量上传,而是分层存储,更利于节省空间,以层的UUID为标识
这时两个仓库上都有了该镜像
也就是说,无论我再任何一个仓库操作,都会同步给其它的任何仓库
- 部署keepalived高可用实现
本案例太多因素出自笔者主观,也许可靠,也许不可靠
两台harbor安装keepalived
#yum -y install keepalived
[root@harbor1 harbor]# cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
script_user root
#需要制定脚本运行用户
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 192.168.200.1
smtp_connect_timeout 30
router_id LVS_DEVEL
vrrp_skip_check_adv_addr
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_script check_harbor {
script "/opt/harbor.sh"
interval 2
weight 20
}
#使用监控脚本来监控自身80端口,因为他是整个harbor的访问入口
vrrp_instance VI_1 {
state MASTER
interface ens32
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.111.100/32 dev ens32 label ens32:2
}
track_script {
check_harbor
}
}
--------------注意修改关键配置项------------
[root@harbor2 harbor]# cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
script_user root
#需要制定脚本运行用户
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 192.168.200.1
smtp_connect_timeout 30
router_id LVS_DEVEL1
vrrp_skip_check_adv_addr
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_script check_harbor {
script "/opt/harbor.sh"
interval 2
weight 20
}
vrrp_instance VI_1 {
state BACKUP
interface ens32
virtual_router_id 51
priority 90
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.111.100/32 dev ens32 label ens32:2
}
track_script {
check_harbor
}
}
----------故障切换脚本-----------
[root@harbor1 harbor]# vim /opt/harbor.sh
#!/bin/bash
sum=`netstat -lnpt | grep -wo 80 | wc -l`
if [ $sum -eq 0 ]; then
pkill -9 keepalived
fi
[root@harbor1 harbor]# chmod +x /opt/harbor.sh
[root@localhost anchors]# vim /usr/lib/systemd/system/docker.service
#主机3
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --insecure-registry 192.168.111.3 --insecure-registry 192.168.111.4 --insecure-registry 192.168.111.100
#将VIP添加入可不安全访问
[root@localhost anchors]# docker login 192.168.111.100
Authenticating with existing credentials...
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 anchors]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
192.168.111.4/joinbest1/cirros test2 bc94bceaae77 5 months ago 10.3MB
cirros latest bc94bceaae77 5 months ago 10.3MB
192.168.111.3/joinbest1/cirros test1 bc94bceaae77 5 months ago 10.3MB
#镜像也正常
[root@harbor1 harbor]# docker-compose stop
Stopping harbor-jobservice ... done
Stopping nginx ... done
Stopping harbor-ui ... done
Stopping harbor-adminserver ... done
Stopping redis ... done
Stopping registry ... done
Stopping harbor-db ... done
Stopping harbor-log ... done
#测试故障切换
[root@harbor2 harbor]# ip a | grep ens32
2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
inet 192.168.111.4/24 brd 192.168.111.255 scope global noprefixroute ens32
inet 192.168.111.100/32 scope global ens32:2
#ip切过来了
- 测试keepalived的VIP的写入是否同步其余仓库
[root@localhost anchors]# docker tag cirros:latest 192.168.111.100/joinbest1/cirros:test3
[root@localhost anchors]# docker push 192.168.111.100/joinbest1/cirros:test3
The push refers to repository [192.168.111.100/joinbest1/cirros]
abbd6d6ac643: Layer already exists
75b99987219d: Layer already exists
0cc237193a30: Layer already exists
test3: digest: sha256:96137d51e0e46006243fa2403723eb47f67818802d1175b5cde7eaa7f19446bd size: 943
#目前正常写入
#通过web界面对111.3和111.4的joinbest1仓库看看镜像是否同步
#这里先把刚才测试关闭的harbor1仓库给启动
Starting log ... done
Starting registry ... done
Starting mysql ... done
Starting adminserver ... done
Starting ui ... done
Starting redis ... done
Starting jobservice ... done
Starting proxy ... done
#好,我这里是全部可以正常同步,就算是刚才客户端上传时,harbor1是宕机的,但是重新启动后,还是会进行同步,不过应该是有触发机制,我后来又创建了一个test4,刚开始harbor1是没有test3的,我上传test4之后出发了同步机制,这时harbor1的镜像仓库也是正常工作了,便将3.4一起同步过去了
三、总结
- 1.本高可用方案,生产环境有待考量
- 2.刚开始是尝试着做基于https的连接,但是因为诸多因素:ssl工具或许不支持基于ip的加密只支持域名,但是要配合keepalived肯定是需要ip的,故舍弃https;经过思考,如果只是做私有仓库使用的话,那么不使用https或许也是非常可行的。
- 3.keepalived很好用,很有感触
- 4.本案例环境都是在测试环境,在生产环境的相应压力中,并不知道会有怎么样的后果
报错
raise Exception("Error: the protocol must be https when Harbor is deployed with Notary")
Exception: Error: the protocol must be https when Harbor is deployed with Notary
#我输入得命令是sh install.sh --with-notary --with-clair
#其中使用--with-notary含义是启用镜像签名;必须是https才可以,把该选项去掉即可·
[root@localhost anchors]# docker login 192.168.111.3
Username: admin
Password:
Error response from daemon: Get https://192.168.111.3/v2/: dial tcp 192.168.111.3:443: connect: connection refused
#客户端连接报错,默认使用的是https我需要修改为可以使用http来进行连接
[root@localhost anchors]# vim /usr/lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --insecure-registry 192.168.111.3 --insecure-registry 192.168.111.4
Harbor高可用理论及实践(汇聚篇)的更多相关文章
- Redis高可用之主从复制实践(四)
0.Redis目录结构 1)Redis介绍及部署在CentOS7上(一) 2)Redis指令与数据结构(二) 3)Redis客户端连接以及持久化数据(三) 4)Redis高可用之主从复制实践(四) 5 ...
- harbor高可用部署
文章转载自:https://blog.csdn.net/networken/article/details/119704025 harbor高可用简介 harbor目前有两种主流的高可用方案: 多ha ...
- harbor高可用集群配置
目录 说明 双主复制 主从同步 双主复制说明 多harbor实例共享后端存储 方案说明 环境说明 配置说明 安装redis和mysql 导入registry数据库 配置harbor 挂载nfs目录 修 ...
- HBase高可用原理与实践
前言 前段时间有套线上HBase出了点小问题,导致该套HBase集群服务停止了2个小时,从而造成使用该套HBase作为数据存储的应用也出现了服务异常.在排查问题之余,我们不禁也在思考,以后再出现类似的 ...
- docker仓库之harbor高可用 (三)
基于上一篇部署完成了企业级仓库harbor的部署,今天我们来聊聊什么是harbor的高可用 Harbor 支持基于策略的 Docker 镜像复制功能,这类似于 MySQL 的主从同步,其可以实现不同的 ...
- Harbor高可用
项目需求: 实现Harbor的HTTPS高可用,由于Harbor 服务器配置不高,直接做HTTPS对上传下载镜像时,若docker客户端多时,会非常慢,为了提高harbor的效率,采用以下方式来解决. ...
- (5.15)mysql高可用系列——MHA实践
关键词:MHA,mysql mha [1]需求 采用mysql技术,实现MHA高可用主从环境,预计未来数据量几百G MHA概念参考:MYSQL高可用技术概述 [2]环境技术架构 [2.1]MHA简介 ...
- harbor高可用集群搭建
高可用harbor集群搭建 一.安装部署 1.节点角色 角色 数量 名称 备注 harbor主节点 2 harbor-1 harbor-2 双主模式 haproxy 2 HA-1 HA-2 需要通过k ...
- Redis(九)高可用专栏之《简介篇》
在互联网的大趋势下,用户体验.服务的可用性日趋重要.任何一个服务的不可用,都可能导致连锁式功能故障. 前言 高可用模型的已经逐渐形成一种套路: 主备/主从模式 集群模式 主备/主从模式 至少有两台服务 ...
随机推荐
- Linux记录-SVN+Jenkins+jdk+maven自动化集成部署
1.svn部署 yum -y install subversion svnserve --version 查看版本 mkdir -p /usr/app/svn svnadmin create /usr ...
- 报错:Error starting Jetty. JSON Metrics may not be available.java.net.BindException:地址已在使用
报错背景: 刚在CDH中集成Flume插件,启动报错 报错现象: Error starting Jetty. JSON Metrics may not be available. java.net.B ...
- locate home of running java application
1. find the target process id of your java app jps [-lm] in my case: [lenmom@Mi- bin]$ jps -l sun.to ...
- 单机prometheus vs 集群kube-prometheus+prometheus-operator
prometheus 组件: node-exporter:9100端口 https://segmentfault.com/a/1190000017959127
- 【GStreamer开发】GStreamer基础教程13——播放速度
目标 快进,倒放和慢放是trick模式的共同技巧,它们有一个共同点就是它们都修改了播放的速度.本教程会展示如何来获得这些效果和如何进行逐帧的跳跃.主要内容是: 如何来变换播放的速度,变快或者变慢,前进 ...
- Flask 数据库连接
Flask拥有丰富的扩展组件,数据库管理方面Flask-SQLAlchemy简化了数据库管理的操作.SQLAlchemy是一个很强大的关系型数据库框架,支持多种数据库后台.其不但提供了高层ORM,而且 ...
- PHP比较两个版本的方法
PHP比较两个版本的方法 写app接口经常要用到 PHP接口的版本和app里面的版本做比较 如果app版本低于接口版本 那么就要提示他升级 <pre><?php/** * 版本处理类 ...
- 通过减少 IO 实现性能的优化
原始地址见 这里 本文是工作中一点点简单的思考,不能保证是完全正确的,可能也仅仅是适用于部分场景. 场景 1:获取用户关注的好友列表中,每个好友的名字.头像等信息. 在很多公司中,不同的服务是由不同的 ...
- MySQL 索引最佳实践
原文请关注 这里 这是 文章 的翻译,在翻译过程中,会对其中涉及到的语句加上一些个人理解以及 SQL 语句的执行,并进行特别的标注. 1. 你做了一个很棒的选择,因为: 对于普通开发者和 DBA,理解 ...
- Java的设计模式(5)-- 策略模式
定义一系列算法,把它们一个个封装起来,并且使它们可以相互替换,本模式使得算法可以独立于使用它的客户而变化.策略模式包括以下三种角色 策略(Strategy):策略是一个接口,该接口定义若干个算法标识, ...