Docker 从 0 到 1 构建一个企业级的私有镜像仓库 Harbor

欲野法师 · January 29, 2021 · Last by 小新 replied at January 30, 2021 · 3884 hits

知其然知其所以然

Harbor 官网
Harbor 源码地址

初识 Harbor

Harbor 简介
Harbor 是一个用于存储和分发 Docker 镜像的企业级 Registry 服务器。Harbor 和 Registry 都是 Docker 的镜像仓库,但是 Harbor 作为更多企业的选择,是因为相比较于 Regisrty 来说,它具有很多的优势

Harbor 介绍
说起镜像仓库,可能很多小伙伴还是很陌生,但是最近几年,docker 异军突起,热度一直居高不下,相信很多玩 docker 的小伙伴,都知道 docker 有个叫 dockerhub 的东西,没错,这个玩意就是 docker 的官方镜像仓库,而 Harbor 就是一个企业级的镜像仓库,Harbor 主要是基于 dockers 官方镜像的存储,harbor 使用的是官方的 docker registry(v2 命名是 distribution) 服务去完成。harbor 在 docker distribution 的基础上增加了一些安全、访问控制、管理的功能以满足企业对于镜像仓库的需求。harbor 以 docker-compose 的规范形式组织各个组件,并通过 docker-compose 工具进行启停。docker 的 registry 是用本地存储或者 s3 都是可以的,harbor 的功能是在此之上提供用户权限管理、镜像复制等功能,提高使用的 registry 的效率。Harbor 的镜像拷贝功能是通过 docker registry 的 API 去拷贝,这种做法屏蔽了繁琐的底层文件操作、不仅可以利用现有 docker registry 功能不必重复造轮子,而且可以解决冲突和一致性的问题。

#Harbor 架构

Harbor 主要组件

Proxy

1. Proxy:对应启动组件 nginx。它是一个 nginx 反向代理,代理 Notary client(镜像认证)、Docker client(镜像上传下载等)和浏览器的访问请求(CoreService)给后端的各服务;
2. UI(Core Service):对应启动组件 harbor-ui。底层数据存储使用 mysql 数据库,主要提供了四个子功能:
3. UI:一个 web 管理页面 ui;
4. API:Harbor 暴露的 API 服务;
5. Auth:用户认证服务,decode 后的 token 中的用户信息在这里进行认证;auth 后端可以接 db、ldap、uaa 三种认证实现;
6.Token 服务(上图中未体现):负责根据用户在每个 project 中的 role 来为每一个 docker push/pull 命令 issuing 一 token,如果从 docker client 发送给 registry 的请求没有带 token,registry 会重定向请求到 token 服务创建 token。

Registry

Registry 主要对应启动组件 registry。负责存储镜像文件,和处理镜像的 pull/push 命令。Harbor 对镜像进行强制的访问控制,Registry 会将客户端的每个 pull、push 请求转发到 token 服务来获取有效的 token。

Admin Service

AdminService 主要对应启动组件 harbor-adminserver。是系统的配置管理中心附带检查存储用量,ui 和 jobserver 启动时候需要加载 adminserver 的配置;

Job Sevice

Job Sevice 主要对应启动组件 harbor-jobservice。负责镜像复制工作的,他和 registry 通信,从一个 registry pull 镜像然后 push 到另一个 registry,并记录 job_log

Log Collector

Log Collector 主要对应启动组件 harbor-log。日志汇总组件,通过 docker 的 log-driver 把日志汇总到一起

Volnerability Scanning

Volnerability Scanning 主要对应启动组件 clair。负责镜像扫描

Notary

Notary 主要对应启动组件 notary。负责镜像认证

DB

DB 主要对应启动组件 harbor-db,负责存储 project、 user、 role、replication、image_scan、access 等的 metadata 数据。
需要注意的是,harbor 的每个组件都是以 Docker 容器的形式构建的,可以使用 Docker Compose 来进行部署,当然,如果你的环境中使用了 kubernetes,harbor 也提供了 kubernetes 的配置文件。
如下 docker 镜像:

harbor-jobservice, 
nginx, harbor-core,
redis, 
harbor-portal, 
harbor-db,
registry, 
registryctl, 
harbor-log

Harbor 主要有以下几个容器组成

- ui:harbor的核心服务。
- log:运行着rsyslog的容器,进行日志收集。
- mysql:由官方mysql镜像构成的数据库容器
- nginx:使用Nginx做反向代理
- registry:官方的Docker registry
- adminserver:harbor的配置数据管理器
- jobservice:Harbor的任务管理服务。
- redis:用于存储session

Hbarbor 的安装

## 基础准备工作
服务器一台:centos7
基础软件环境配置:jdk1.8, dockers 和 docker-Compose,生成一个证书临时的 https 证书

实战安装

wget https://github.com/goharbor/harbor/releases/download/v2.1.1/harbor-offline-installer-v2.1.1.tgz
解压
tar zvxf harbor-offline-installer-v2.1.1.tgz

生成自己服务器的 https 证书

mkdir ssl && cd ssl
# 注意:一般生成的目录,应该放在nginx/conf/ssl目录
# 1.创建服务器证书密钥文件 server.key:
openssl genrsa -des3 -out server.key 2048
# 输入密码,确认密码,自己随便定义,但是要记住,后面会用到。
# 2.创建服务器证书的申请文件 server.csr
openssl req -new -key server.key -out server.csr
# 输出内容为:
Enter pass phrase for root.key: ← 输入前面创建的密码 
Country Name (2 letter code) [AU]:CN ← 国家代号,中国输入CN 
State or Province Name (full name) [Some-State]:BeiJing ← 省的全名,拼音 
Locality Name (eg, city) []:BeiJing ← 市的全名,拼音 
Organization Name (eg, company) [Internet Widgits Pty Ltd]:MyCompany Corp. ← 公司英文名 
Organizational Unit Name (eg, section) []: ← 可以不输入 
Common Name (eg, YOUR name) []: ← 此时不输入 
Email Address []:admin@mycompany.com ← 电子邮箱,可随意填
Please enter the following ‘extra’ attributes 
to be sent with your certificate request 
A challenge password []: ← 可以不输入 
An optional company name []: ← 可以不输入
# 4.备份一份服务器密钥文件
cp server.key server.key.org
# 5.去除文件口令
openssl rsa -in server.key.org -out server.key
# 6.生成证书文件server.crt
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt


mkdir  /usr/local/nginx/conf/ssl
cp * /usr/local/nginx/conf/ssl/

## 安装 Harbor
修改配置文件

vim harbor.yam
主要修改如下
注释掉http模式
hostname修改成自己的域名,我这里就偷懒 设置成harbor.com
certificate: 添加自己的https证书
private_key: 添加证书key
其他的根据自己修改,默认的也可以

回到 harbor 目录执行如下命令

cd ~/harbor
./install.sh

执行完成之后,本地会创建,上面说到的八个容器,这这些容器都是使用 docker-Compose 管理的

Harbor 登录过程

假设 Harbor 部署在域名为 Harbor.com 的主机上。用户运行 docker 命令将登录请求发送到 Harbor:的主机上。用户运行 docker 命令将登录请求发送到 Harbor:

docker login Harbor.com

用户输入所需凭证后,Docker 客户端向地址 “Harbor.com/v2/” 发送 HTTP GET 请求。Harbor 的不同容器将按照以下步骤进行处理:

  • 首先,该请求由监听 443 端口的代理容器接收。容器中的 Nginx 将请求转发到后端的 registry 容器。
  • Registry 容器已配置为基于令牌的身份验证,因此它返回错误代码 401,通知 Docker 客户端从指定的 URL 获取有效的令牌。在 Harbor,这个 URL 指向核心服务的令牌服务;
  • Docker 客户端收到此错误代码后,会根据 HTTP 规范的基本认证向令牌服务 URL 发送请求,将请求头部嵌入用户名和密码;
  • 通过端口 80 将该请求发送到代理容器后,Nginx 会根据预先配置的规则再次将该请求转发给 UI 容器。UI 容器内的令牌服务接收请求,解码请求并获取用户名和密码;
  • 获取用户名和密码后,令牌服务将检查数据库,并通过 MySql 数据库中的数据验证用户。当令牌服务配置为 LDAP / AD 身份验证时,它将对外部 LDAP / AD 服务器进行身份验证。认证成功后,令牌服务返回一个表示成功的 HTTP 代码。HTTP 响应体包含由私钥生成的令牌。

Docker push 的过程

(这里我暂时忽略不说代理转发步骤,架构图显示了 Docker 推送过程中不同组件之间的通信)
用户成功登录后,Docker Image 将通过 Docker Push 命令发送到 Harbor:

docker push Harbor.com/library/hello-world
  • 首先,码头客户端通过向注册表发送请求重复类似登录的过程,然后取回令牌服务的 URL;
  • 随后,当接触令牌服务时,Docker 客户端提供附加信息以在 image(library/ hello-world)上应用推送操作的令牌;收到 Nginx 转发的请求后,令牌服务查询数据库查询用户的角色和权限,以推送 image。如果用户具有适当的权限,则对 Push 操作的信息进行编码,并用私钥对其进行签名,并向 Docker 客户端生成一个令牌;
  • 在 Docker 客户端获取令牌之后,它向包含令牌的头部向 Registry 发送推送请求。一旦 Registry 接收到请求,它将使用公钥解码令牌并验证其内容。公钥对应于令牌服务的私钥。如果 Registry 找到令牌有效推送 Image,则 Image 传输过程开始。

Harbor 高可用

提到系统的高可用(High Availability),我个人一般会从这几个方面来设计:

  1. 计算高可用;
  2. 存储高可用;
  3. 网络高可用;
  4. 其他方面;

主要围绕前两个方面,即计算高可用和存储高可用来展开讨论

如上图所示,Replication Service 目前不支持多实例的并行同步,我们暂时去掉,只需要考虑其他模块,为了保证整个 Harbor 系统的高可用,除 Replication Service 以外的组件均需扩展为 3 个;

个人实践方案一

独立的 3 个 Harbor 实例 + MySQL Galera 集群 + 镜像共享存储,如下图

3 个独立的 Harbor 实例,通过一个 Load Balancer 来做流量转发。同时采用了共享会话方式,把会话的信息保存在 MySQL 数据库中,这样无论哪个实例响应用户的请求,都不会丢失会话;3 个 Harbor 的 Docker Registry 共享一个存放镜像数据的存储,例如阿里云 OSS、GlusterFS、NFS 等,可参考 Harbor 或 Docker Distribution 的文档配置;MySQL 由于不能共享存储,采用了 Galera 集群,这是一个多主的 MySQL 集群,每个节点均可读可写,同时支持同步复制数据,保证了高可用,具体的部署在这里就不展开讨论,可以参考下面的链接:
GlusterFS
Galera 集群

个人实践方案二

独立的 Harbor 子模块 + MySQL Galera 集群 + 镜像共享存储,如下图

独立的 Harbor 子模块之间,通过负载均衡来通信,MySQL Galera 集群和镜像共享存储和方案 1 基本一样。这个方案的优点是各个子模块相互独立,每个子模块都有 2 个备份,通过负载均衡实现高可用,这里使用 Kubernetes Service 非常容易实现 LB,下面的章节会展开来说。

Harbor 基于 Kubernetes 的高可用实现

这里我们选择上面的方案 2,使用 Kubernetes 的 Replication Controller 来实现单个模块的备份,通过 Service 来实现服务发现和负载均衡。如果不想用共享存储,可以用 Kubernetes 提供的 PV 和 PVC(host path 模式),整体架构如下图所示:

# 实践

1. 部署 Replication Controller

make/kubernetes/*/.rc.yaml 文件里面定义的组件副本数目为 1 个,可修改为多个,例如:replicas: 3, 如下图所示:

2. 部署 ConfigMap

ConfigMap 可通过编辑 harbor.cfg 文件之后,由./prepare 脚本自动生成,存放在 templates 目录下,以下是一个生成的 yaml 文件样例:

部署 PV & PVC

PV 和 PVC 的配置定义了 Harbor 每个组件使用的存储,缺省是本机文件系统,可以改成 NFS,GlusterFS 等共享存储,以实现高可用。

在 Kubernetes 上启动 Harbor 后,高可用的镜像仓库就完成了,可以通过 Nginx 的服务地址来访问

Dome

共收到 4 条回复 时间 点赞

Mark 一下

好多字,先 mark😂

挺有用的 感谢分享

4Floor has deleted
5Floor has deleted
需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up