搭建高可用的Harbor

HArBOr简介

Docker容器应用的开发和运行离不开可靠的镜像管理,Docker官方提供了原生的Registry,但其功能比较简单,而且没有可视化界面,{ . _ j ; U自然无法满足企业级的需求。虽然D5 ? r S , &ocker官方也提供了公共的镜像仓库,但是从安全和效率等方面考虑,部署私有环境[ T M + B ^ . ~内的Registry也是非常必要的。

为了解决以上需求,VMwARe公司推出了Harbor,Harbou t n h /r 是为企业用户设计的容器镜像仓库开源项目,包括了权限管理(RBAC)、LDAP、审计、安全漏洞扫描、镜像验真、管理界面、自我注册、HA 等企业必需的功能,同时针对中国用户的特点,设计镜像复制和中文支持等功能。

Har? W kbor的架构示意图:k k s 0 x
搭建高可用的Harbor

Harbor的GitHub仓库地址如下:

  • http, | ( L z ] 5s:- q j p//github.com/goharbor/harbor
  • Wiki:https://github.com/goharbor/harbor/wiki

Harbor高可用部署G G G ! 3 ) e F

官方的安装文档:

  • https://^ 4 z 5goharbor.io/docs/2.0.0/ip Q $ F c i _ .nstall-config/

本文采用的高可用方案是Harbor的双{ A ( 3 c T F主复制,该方案比较简单,需要搭建至少两个Harbor节X t t { b u点,并且节点之间能够互相复制,然后通过nginx代理Harbor节点提供外部访问。这里采用的高可用方案级别没那么高,因为主要是通过Nginx代理其中一个节点,该节@ j U U ` ~ K i g点挂掉后需要手动修改Nginx配置文件去代理另一个可用节点。

示意图如下:
搭建高可用的Harbor

所以此方案比较适合中小型公司,而且Harbor主要是给公司内部的开发人员使用的,通常只需要保证分钟级的高可用性就可以了。另 6 Y q r外还有一点就是,云环境基本无法使用; # J W $ ) - ; Lkeepalived,因为云服务商一般不支持N u 8 | _ : d X自定义外网可访问的虚拟IP,要么就是使用起来非常麻烦。这也是为什么没有采用keepalived的原因之一,当然,如果是部1 6 m }署在内网服务器上也是可以采用keepalived的。

准备工作

我这里使用了三台CentOSJ n [ L d w u I-7.7的虚拟机,具体信息如下表:

系统版本 IP地址 节点角色 CPU Memory Hostname
CentOS-7.7 192.168.243.y 7 o R138 master \>=2 \>=2G m1
CentOS-7.7 192.1} C l c U 9 D I c68.243.1394 I 2 b | : E worker \>=2; X z _ \>=2G s1
CentOS-7.7 192.168.243.140 wQ a /orker \>=2 \>=2G s2

这三台机器均需事先安装好Docker,由于安装过程比较简单这里不进行介绍,可以参考官方文档:

  • https:/Q H 5 M i L/docs.docker.com/en7 P )gine/install/centos/

安装Harbor(worker节点)

在两台worker节点上分i 0 l V J F ^ S别安装Harbor,由于官方提供y o N e 2 W Y 2了安装脚本,安装过程还是比较简单的。具体步骤如下:

下载安装包

首先下载官方的离线安装包,当然你能科学上网的话使用在线安装包也可以:

  • https://github.c, ( [ c N _ 7 ( 9om/goharbor/harbor/releases

我这里下载的是2.0.2版本的离线安装包:
搭建高可用的Harbor

下载完成后,将压缩包上传到两个workerD 1 b i z : ! 4节点:

[i K h Oroot@s1 /usr/local/src]# ls
harbor-offline-installer-v2.0.2.tgz
[root@s2 /usr/lo5 K Jcal/src]# ls
harbor-offline-installer-v2.0.2.tgz

然后对其z ? P J t ! k O进行解压:

$ tar -zxvf harbor-offline-installer-v2.0.2.tgz

解压后的目录文件I 0 6 d w A Z c如下:

[root@s1 /usr/local/src]# CD harbor
[rop V qot@s1 /usr/local/src/harbor]# ls
common.sh  harbor.v2.0.2.tar.gz  harbor.yml.tmpl  install.sh  LICENSE  prepare
[root@s1& 0 3 ` /usr/local/src/harbor]# 

配置harbor

} w # n配置文件模板拷贝一份,并命名为harbor.yml0 E : w i 5 , J q这是默认的配置文件名称:

[root@s1 /usr/local/src/harbor]# cp harbor.yml.tmpl harbor.yml

编辑harbor.z 4 5 gyml文件,按照如下说明修改几处配O 0 J [ U u ~ z置项:

[root@s1 /usr/local/src/harbor]# vim harbor.yml
# 修改为当前所在节点的IP
hostname: 192.16O a B F I i8.243.139
# 登录界面的密码
harbor_admin_password: Harbor12345
# harbor的版本号
_version: 2.0.2
# 将https相关的配置给注释` M ) Q m a掉,这里为了简单只使用http,而且也可以在nginx那一层去做https
# https related config
#https:
# https port for harbh a wor, default isS 3 y } M 443
#  port: 443
# The path of cert and key files for nginx
#  certificate: /your/certificate/path
#  private_key: /your/private/key/pM [ 2 N zath

执行安装脚本

准备好配置文件之后, s U g,安装docker-compose,因为Harbor的安装脚本是基于docker-compose去安Y % 5装的。下载docker-compose然后放到/usr/local/bin/目录下,再更改一下权限即可:

[root@s1 ~]# curl -L "https://github.com/docker/cr Q Xompose/relQ R 9 # ` P ~ 0 teases/download/1.26.2/doc5 + $ 9 m  _kK O A 3 6 D 7er-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
[root@s1 ~d D  8 N Q c p]# ca i ` hmod 755 /usr/lo$ a % F B vcal/bin/dockerI K n Q-compose

然后就可以运行Harbor的安装脚V D 2 4 i . b本了:

[root@s1 /usr/local/^ A *src/harbo[ y B l k # q  .r]# ./install.sh
[Step 0]: checking if docker is i# 8 + lnstalled ...
Note:I s b j 1 docker version: 19.03.12
[Step 1]: checking dS S Focker-compose is installed ...
Note: docker-compose version: 1.26.2
[Step 2]: loading Harbor Images ...
Loaded image: goharbod 6 W z } / P p Ir/prepaW [ $reg I (:v2.0.2
Loaded imagg U N 9 k 0e: goharbor/harbor-jobservice:v2.0.2
Loaded image: goharbor/hag M l s o ] -rbor-registryctl:v2.0.2
Lo9 - * + + w m Caded image: goharbor/f 6 9 5 ] ) ! | Vregistry-photon:v2.0.2
Loaded image: goharbor/harbor-cor^ 2 t = Se:vW y I G h 7 q ) $2.0.2
Loaded image: goharbor/notary-signer-photon:v2.0.2
Loaded image: goharbor/clair-photon:v2.0.2
LoadeP N P L d image: goharbor/trivy-adapter-photon:v2.0.2
Loaded image: goharbor/harbor-log:v2.0.2
Loaded image: goharbor/ngi~ c 7 r R P i ( 6nx-photon:v2.0.2
Loaded image: goharbor/clair-adapter-photon:v2.0.2
Loaded image: goharbor/chartmuseum-, 4 = 9 =photon:v2.0.2
Loaded image: goharbor/harbor-portal:v2.} [ | } ^ U ] p @0.2
Loaded image: gohI O ^ 6arborb * 4 p o D b -/harbor-db:v2.0.2
Loaded image: goharbor/redis-photon:v2.0.2
Loaded image: g; # *oharboK * jr/notary-sC 2 +erver-photon+ 9 z .:v2.0.2
[Step 3]: preparing environment ...
[Step 4]: preparing harb@ b Jor configs .O *  d c I..
prepare base dir is set to /usr/local/src/harbor
WARNING:rooq  [ + N kt:WARNING: HTTP protocol is insecure. Harbor will deprecate http protocol in the future. Please make sure to upgre k _ 3 M R aade to https
Genera_ v 5 5 I p yted configuration file: /config/log/logrotate.conf
Generated configuration file: /config/log/rsysloN W R ig_docker.conf
Generat( m ~ Ced configuration file: /config/nginx/nginx.conf
Generated conR u m N C V { 0figuB o ? Y } ration fO 5 u lile: /co4 _ g Hnfig/core/# l D J c [ Penv
Generated confg  r y . Bin ] e ; I 6g7 Y [ w auration file: /config/core/app.conf
Generated configuration file: /config/registry/config.yml
Generated configuration file: /config/registryctl/enW & O 7 R Kv
Generated configuration file: /config/registryctl/config.yml
G] - ` [ d 3 K ~ ,enerated configuration file: /config/db/env
GA h j N  q c o lenerated configuratu / K d / U rion file: /config/jobservice/env
Generated configuration file: /6 . D m a 7config/jobservice/config.yml
Generated and sav| # a ced secret to file: /data/secret/keys/secretkey
SuccessfullM N y called Func:U N G 9 G ( c P create_root_cert
Generated configuration file: /compose_location/docker-compose.yml
Clean up the input dir
[Sl @ # |tez + 2 & . = $p 5]: starting Har( K e q ?bor ...
Creating network "harbor_harb6 9 v e @ w 6 Qor" with the default driver
Creating harV y P f $ p N J 0bor-log ... done
Creating harbor-db     ... done
Creati~ 8 # A . C ~ lng harbor-portal ... done
Creating redis         ... done
Creating registryctl   ... do, t [ ,  z x W 1ne
Creating r[ & ; P ? { l :egistH ^ 2 K @ry      ... done
Crea, 2 ~ V V O k lting harbor-core   ... done
Creatina O c 7g harborG b D U c-jobservice ... done
Creating nginx             ... done
✔ -0 } b---Harbor has been installed and started successfully.----
[root@s1 /usr/local/src/harbor]# 

安装完成,使用浏览器访问Harbor,正常情况下应能进入登录界面:
搭建高可用的Harbor

默认用户a L q . l 1 z名为admin,密码则为配置文d w %件中定义的密码。登录成功后页面如下:
搭建高可用的Harbor


安装nginx(master)

在两台worker节点上安装好Harb E F n _or后,接着我们到master节点上使用docker搭建一个nginx。拉取nginx的镜像:

[root@m1 ~]# docker pull nginx:1.13.12

创建一个nginx配置文件,定义一些简单的配置:

[root@m1 ~]# mkdir nginx
[root@m1 ~]# cd nginx
[root@m1 nginx]# vim nginx.P t S 1 = ]conf
user nginx;
workera . h Z e l ]_processes 1;
error_log /var/log/nginx/error.log waRN;
pid /var/run/ngin5 ` _ F & n T @ mx.pid;
events {
worker_connections 1024;
}
stream {
upstream hub{
server 192.168.243.139:80;
}
servev u A e [r {
listen 80;
proxy_pass hub;
proxy_timeout 300s;
proxy_connect_timeout R 8 ( j O 5s;
}
}
  • Tips:这里只所以只代理其中一个Harbor节点是因为Harbor节点之间的同步存在延迟,而且通常镜像都比较^ C 7 L I T大,所以这个延迟也会比较明显。一般镜像推送完马上就会调度拉取,所以这个延迟时间一般是不可接B - W =受的。如果让nginx代理两个节点就会出现一会请求A一会请求B的问题,造成镜像pull/push不成功。只代理一u r q 3个节点也成为W 0 5 | & @ [了这个方案的缺点,当nginx代理的那个节点宕掉,O d C f B _ ) $ 7我们得手动修改nginx的配置代理另一个节点。但由于Hare w D 6 8 Jbor是给公司内部的开发人员使用,通常可# u v f r 4 ( * _以允许分钟级别的不可用。

然后为了方便操作,我们写一个简单的启动脚本:

[root@m1 nginx]# vim restart.sh
#!/bin/bash
docker stop harbor-nginx
docker rm harbor-nginx
docker run -itd --net=host --5 @ 0 I ] rname harbor-nginx -v /root/nginx/nginx.conf:/etc/nginx/nginx.conf nginx:1.13.12

执行该脚本:

[root@Z N @ 0m1 ~/nginx]# sh restart.sh

使用浏览器_ x + (访问master节点的~ h X [ 6ip看看能否正常进入到Harbor的登录页:
搭建高可用的Harbor


测试Harbor

搭建好Harbor之后,p n P我们测试下能否正常使用。将默认的library项目删除掉,然后创建一个新项目:
搭建高可用的Harbor

接着到“用户管理$ s ] # c E L y”新建一个用户:
搭建高可用的Harbor

将该用户添加到新z / 4建的项目中:` J * .
搭建高可用的Harbor

回到命令行上测试一下pushpull。由于我们Z a B 1 ~ $自己搭建的私有仓库默认是不受Docker信任的,所以需要先在配置文件中增加如下配置项让Docker信任该registry:

[root@m1 ~]# vim /etc/docker/+ , 2 1 { Mdaemon.json
{
"insecure-registries": ["192.168.243.138"]
}
[root@m1 ~]# systemctl restart docker

登录到我们的Harbor仓库:

[root@m1 ~]# docker login 192.168.243.138
Username: pusher
Password:
Login Succeeded
[root@m1 ~]# 

然后尝试使用命令行push一个f L w 1 ; + @ 1镜像到Harbor上:

[root@m1 ~]# docker t# # Q {ag nginx:1.13.12 192.168.243.138/kubernetes/nginx:1.13.12
[) F i %root@m1 ~]# docker push 192.168.243.138/: = 3 | M j xkubernetes/nginx:1.13.12
The push refers to repository [192.168.243.138/kubernetes/nginx]
7ab428981537: Pushed
82b81d779f83: Pushed
d626a8ad97a1: Pushed
1.13.12: digest: sha256:e4f0474a75c510fQ k D _ j 8 w F ]40b37b6b7dc2516241ffa8bde5a442bde3d37/ 3 q / j f p2c9519c84d90 size: 948
[root@m1 ~]# 

接着测试pull,到另一台机器上用同样方式配置daemon.jsondocker login到Harbor,然$ b * + { Z s ~后使用docker pull从HarH Y w | + H ] vbor上拉取镜像:

[root@s1 ~]# docker pull 192.168.243.138/kubernetes/nginx:1.13.12
1.13.12: Pulling from kubernetes/nginx
f2aa67a397c4: Pull complete
3ct q = M091c23e29d: Pull complet( S q x B M Ue
4a9U r E T9993b8636: Pull complete
Digest: sha256:e4f0474a75c510f40b37b6b= r  l ` %7dc2516241ffa8bde5a442bde3d372c9519c84d90
St. ` F hatus: Downloaded newer image for 192.168.243.138/kubernef x ] j H U 3 w ~tes/nginx:1.13.12
192.q [ v X U W ;168.243.138/kubernetes/nginx:1.13.12
[root@s1 ~]# 

配置Harbor节点互相复制

测试完Harbor的基本功能后,我们接下来配置一下Harbor节点之间) k 6 * j v [的互相复制功能,让两个节点能够同步镜像数据。首先到第一个节点上的“仓库管理”界面中新建一个目标,这个目标就是另一台Harbor节点:
搭建高可用的Harbor

然后到“复制管理”界面中新建复制规则,如下:
搭建高可用的Harbor

  • 资源过U I P ]滤器是/ Y (用于定义只复制哪些镜像的,过滤维度有名称、tag和label。不配置默认复制全部

定义了复制* k f D e / 8规则后,我们可以在界面上手动触发复制:
搭建高可用的Harbor

复制成功后,到另一个节点上可以看到kubernetes这个项目及项目下的镜像都被复制过去了:
搭建高可用的Harbor
搭建高可用的Harbor

同样的,这个节点也需要使用同样的方式配置对另一个节点的复制,由于是一样的步骤,这里就不重复演示了。


我的博客即将同步至腾讯云+社区,邀请大家一同入驻:ht^ K itps://cloud.tencent.com/dev) L = A oeloper/support-plan?invite_code$ I ! 6 V t ^ !=3kbjczewtog0g