Docker镜像管理:为什么Harbor是首选

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: Docker镜像管理:为什么Harbor是首选

关注【云原生百宝箱】公众号,获取更多云原生消息


“Harbor ”这个名字本身就与容器镜像有关。Harbor 是容器镜像装卸的场所。而且,“Harbor ”简单易读、易记,是项目推广的有力选择。

历史

Harbor 是 CNCF 毕业项目,它提供合规性、性能和互操作性,帮助你跨 K8s 等云原生计算平台一致、安全地管理工件。

Harbor 是开源的,并且纯粹是云原生的。

由 VMware 创建,并于 2018 年 7 月 31 日加入 CNCF。它通过添加用户通常需要的功能(例如安全性、身份和管理)来扩展开源 Docker 发行版,并支持在镜像仓库之间复制映像。

经过多年的发展,Harbor 已成为一个完整的 OCI 兼容的云原生工件镜像仓库。这意味着Harbor现在支持OCI(开放容器计划)镜像和OCI镜像索引。

使用 Harbor v2.0,用户可以管理镜像、manifest 列表、Helm 图表、CNAB、OPA 等,这些都遵守 OCI 镜像规范。它还允许拉、推、删除、标记、复制和扫描此类工件。

为什么选择Harbor

你可能会问既然我们已经有了 Docker 镜像仓库为什么还需要 Harbor 呢?嗯,Harbor 是 Docker 镜像仓库的企业级扩展,用途更广泛。这些新的企业级功能包括:

  • • 管理用户界面
  • • 基于角色的访问控制
  • • AD/LDAP 集成
  • • 审计日志记录

另外,Harbor 是云原生的,它不仅存储镜像,还可以扫描其内容是否存在安全问题。Harbor 还允许开发人员使用个人密钥对推送到镜像仓库的镜像进行签名,从而将镜像标记为可信。

基于Helm部署Harbor

Harbor 的大部分组件现在都是无状态的。所以可以简单的增加 Pod 的副本,确保组件分布到多个 Worker 节点,并利用 K8S 的 Service 机制来保证 Pod 之间的连通性。

部署openebs 持久存储

harbor默认启用了数据持久化,依赖默认存储类提供pv卷,这里使用openebs:

helm repo add openebs https://openebs.github.io/charts
helm repo update
helm install openebs openebs/openebs --namespace openebs --create-namespace

安装完成后,你可以使用以下命令查看安装状态:

kubectl get pods -n openebs

这将显示在 openebs 命名空间中运行的所有 OpenEBS Pod。

设置openebs-hostpath为默认storageclass

kubectl patch storageclass openebs-hostpath -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'

部署ingress nginx 控制器

harbor 默认使用 ingress 方式暴露服务,依赖ingress控制器,这里使用ingress-nginx:

helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm upgrade --install ingress-nginx ingress-nginx/ingress-nginx \
  --namespace ingress-nginx --create-namespace \
  --set controller.service.type=NodePort

获取ingress nginx 控制器的nodeport

$  kubectl -n ingress-nginx get svc
NAME                                 TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx-controller             NodePort    10.105.128.206   <none>        80:31720/TCP,443:30649/TCP   64m
ingress-nginx-controller-admission   ClusterIP   10.97.5.201      <none>        443/TCP                      150m

部署 Harbor 镜像仓库

添加harbor helm仓库

helm repo add harbor https://helm.goharbor.io

Ingress方式暴露服务

部署harbor仓库,ingress-nginx使用nodeport方式暴露自身,需要在externalURL中配置其 NodePort 端口号。

helm upgrade --install harbor harbor/harbor --namespace harbor --create-namespace \
  --set expose.type=ingress \
  --set expose.ingress.className=nginx \
  --set expose.ingress.hosts.core=core.harbor.domain \
  --set expose.ingress.hosts.notary=notary.harbor.domain \
  --set externalURL=https://core.harbor.domain:30649 \
  --set harborAdminPassword="Harbor12345"

浏览器访问harbor管理界面,如果没有DNS解析,注意将192.168.172.128 core.harbor.domain 加入本地hosts文件中,其中192.168.172.128 为kubernetes集群任意节点IP地址。

NodePort方式暴露服务

helm 部署harbor仓库,使用nodePort方式暴露服务,无需部署ingress-nginx控制器:

export node_ip=192.168.172.128
helm upgrade --install harbor harbor/harbor --namespace harbor --create-namespace \
  --set expose.type=nodePort \
  --set expose.tls.auto.commonName=$node_ip \
  --set externalURL='https://$node_ip:30003'

说明:其中 192.168.172.128 为kubernetes集群任一节点IP地址。

Harbor的架构设计

Harbor的架构设计[1]主要包括了以下几个方面的内容:

架构图

下图是Harbor的架构图:

Harbor架构

如上图所示,Harbor 由以下 3 层组件组成:

数据访问层

kv存储:由Redis组成,提供数据缓存功能,支持作业服务临时持久化作业元数据。

数据存储:支持多种存储,作为镜像仓库和Chart的后端存储,实现数据持久化。

数据库:采用PostgreSQL。存储Harbor模型的相关元数据,如项目、用户、角色、复制策略、标签保留策略、扫描策略、Chart和镜像信息。

基础服务

Proxy:由Nginx Server形成的反向代理,提供API路由功能。Harbor的core,registry,web portal和token服务组件都在这个反向代理的背后。代理将来自浏览器和 Docker 客户端的请求转发到各种后端服务。

Core: Harbor的核心服务,主要提供以下功能:

  • • API 服务器:接受 REST API 请求并响应这些请求的 HTTP 服务器依赖于其子模块,例如“身份验证和授权”、“中间件”和“API 处理程序”。
  • • 请求受到身份验证服务的保护,该服务可以由本地数据库、AD/LDAP 或 OIDC 提供支持。
  • • 启用RBAC机制来对相关操作进行授权,例如:pull/push镜像
  • • 令牌服务旨在根据用户在项目中的角色为每个 docker 推/拉命令颁发令牌。如果 Docker 客户端发送的请求中没有令牌,Registry 会将请求重定向到令牌服务。
  • • 认证与授权
  • • 中间件:提前对一些请求进行预处理,以确定它们是否符合要求的条件,并可以传递给后端组件进行进一步处理。一些功能以中间件的形式实现,例如“配额管理”、“签名检查”、“漏洞严重性检查”和“机器人账户解析”等。
  • • API Handlers:处理相应的REST API请求,主要负责解析和验证请求参数,在相关API控制器之上完成业务逻辑,并写回生成的响应。
  • • 配置管理器:涵盖所有系统配置的管理,如身份验证类型设置、电子邮件设置和证书等。
  • • 项目管理:管理项目的基础数据和相应的元数据,创建这些元数据是为了隔离托管工件。
  • • 配额管理器:管理项目的配额设置并在新推送发生时执行配额验证。
  • • Chart控制器:将Chart相关请求代理到后端chartmuseum,并提供多种扩展来改善Chart管理体验。
  • • 保留管理器:管理标签保留策略并执行和监控标签保留流程
  • • 内容信任:对后端Notary提供的信任能力进行扩展,以支持内容信任过程的顺利进行。目前仅支持容器镜像签名。
  • • 复制控制器:管理复制策略和镜像仓库适配器,触发和监视并发复制过程。实现了许多镜像仓库适配。
  • • Distribution (docker registry)
  • • Docker Hub
  • • Huawei SWR
  • • Amazon ECR
  • • Google GCR
  • • Azure ACR
  • • Ali ACR
  • • Helm Hub
  • • Quay
  • • Artifactory
  • • GitLab Registry
  • • 镜像扫描管理器:管理由不同提供商改编的多个配置的扫描仪,并提供指定工件的扫描摘要和报告。
  • • 支持Aqua Security 提供的Trivy扫描仪、Anchore提供的Anchore Engine扫描仪、CentOS (Redhat) 赞助的Clair扫描仪以及DoSec 提供的DoSec Scanner扫描仪。
  • • 目前,仅支持扫描容器镜像或bundles ,例如清单列表/OCI 索引或 CNAB bundles。
  • • 通知管理器(webhook):Harbor中配置的一种机制,以便Harbor中的工件状态更改可以填充到Harbor中配置的Webhook端点。感兴趣的各方可以通过监听相关的webhook事件来触发一些后续操作。现在支持两种方式:
  • • HTTP POST 请求
  • • Slack channel
  • • OCI Artifact Manager:管理整个 Harbor 镜像仓库中所有 OCI 工件生命周期的核心组件。它提供了 CRUD 操作来管理工件的元数据和相关附加内容,例如扫描报告、容器镜像和自述文件的构建历史、依赖关系以及 Helm Chart 的 value.yaml 等,还支持管理工件标签的功能和其他有用的操作。
  • • 镜像仓库驱动程序:作为镜像仓库客户端 SDK 实现,用于与底层镜像仓库(目前为 docker 发行版)进行通信。“OCI Artifact Manager”依赖此驱动程序从清单中获取附加信息,甚至是位于底层镜像仓库中的指定工件的配置 JSON。

作业服务:通用作业执行队列服务,让其他组件/服务通过简单的 RESTful API 提交并发运行异步任务的请求

Log Collector:日志收集器,负责将其他模块的日志收集到一个地方。

GC 控制器:管理在线 GC 计划设置并启动和跟踪 GC 进度。

Chart Museum:第 3 方Chart存储库服务器,提供Chart管理和访问 API。

DockerRegistry:第3方镜像仓库服务器,负责存储Docker镜像并处理Dockerpush/pull命令。由于 Harbor 需要对镜像实施访问控制,Registry 将引导客户端访问令牌服务,为每个拉取或推送请求获取有效令牌。

Notary:第三方内容信任服务器,负责安全发布和验证内容。

消费者

作为一个标准的云原生工件注册中心,自然会支持相关的客户端,如 docker CLI、notary 客户端、OCI 兼容客户端(如 Oras 和 Helm)。除了这些客户端之外,Harbor 还提供了一个 Web 门户,供管理员轻松管理和监控所有工件。

Web Portal:图形用户界面,帮助用户管理镜像仓库上的镜像

Harbor组件

我们使用Helm机制部署Harbor高可用(Ingress形式)后,得到的服务有

Harbor组件

# 1. Helm 列表
$ helm list -A
NAME    NAMESPACE REVISION UPDATED                                 STATUS   CHART         APP VERSION
# harbor 
harbor  harbor    1        2023-10-31 00:14:00.454746411 +0800 CST deployed harbor-1.13.0 2.9.0      
# 分布式存储
openebs openebs   1        2023-10-30 23:36:48.413658223 +0800 CST deployed openebs-3.9.0 3.9.0  
# 2. Ingress
$ kubectl get ingress -n harbor
NAME             CLASS   HOSTS                ADDRESS          PORTS     AGE
harbor-ingress   nginx   core.harbor.domain   10.105.128.206   80, 443   22h
$ kubectl describe ingress -n harbor harbor-ingress 
Name:             harbor-ingress
Namespace:        harbor
Address:          10.105.128.206
Default backend:  default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
TLS:
  harbor-ingress terminates core.harbor.domain
Rules:
  Host                Path  Backends
  ----                ----  --------
  core.harbor.domain  
                      /api/         harbor-core:80 (10.244.219.69:8080)
                      /service/     harbor-core:80 (10.244.219.69:8080)
                      /v2/          harbor-core:80 (10.244.219.69:8080)
                      /chartrepo/   harbor-core:80 (10.244.219.69:8080)
                      /c/           harbor-core:80 (10.244.219.69:8080)
                      /             harbor-portal:80 (10.244.219.75:8080)
Annotations:          ingress.kubernetes.io/proxy-body-size: 0
                      ingress.kubernetes.io/ssl-redirect: true
                      meta.helm.sh/release-name: harbor
                      meta.helm.sh/release-namespace: harbor
                      nginx.ingress.kubernetes.io/proxy-body-size: 0
                      nginx.ingress.kubernetes.io/ssl-redirect: true
# 3. Harbor组件服务
$ kubectl -n harbor get svc
NAME                TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)             AGE
harbor-portal       ClusterIP   10.107.162.71    <none>        80/TCP              91m
harbor-core         ClusterIP   10.109.31.137    <none>        80/TCP              91m
harbor-jobservice   ClusterIP   10.111.2.109     <none>        80/TCP              91m
harbor-registry     ClusterIP   10.110.228.204   <none>        5000/TCP,8080/TCP   91m
harbor-trivy        ClusterIP   10.98.232.46     <none>        8080/TCP            91m
harbor-database     ClusterIP   10.103.147.242   <none>        5432/TCP            91m
harbor-redis        ClusterIP   10.99.63.102     <none>        6379/TCP            91m
# 4. 持久存储声明
$ kubectl get pvc -n harbor
NAME                              STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS       AGE
data-harbor-redis-0               Bound    pvc-a71789b8-a656-4d34-b046-9be4e666e50b   1Gi        RWO            openebs-hostpath   23h
data-harbor-trivy-0               Bound    pvc-41997997-bede-4ba8-8d52-e769f9bdd310   5Gi        RWO            openebs-hostpath   23h
database-data-harbor-database-0   Bound    pvc-ec5ed590-3013-49c7-a4cb-e6ad8c531765   1Gi        RWO            openebs-hostpath   23h
harbor-jobservice                 Bound    pvc-7f833724-956e-4e8a-9329-8b558bf245e8   1Gi        RWO            openebs-hostpath   23h
harbor-registry                   Bound    pvc-1c28f1a0-fc79-4e84-afd5-cda76fc48083   5Gi        RWO            openebs-hostpath   23h

通过上面我们可知

  • Ingress服务
  • harbor-ingress是Harbor的访问入口,提供对harbor-coreharbor-portal服务的路由转发和负载均衡。
  • Harbor的功能组件
  • • 作用:harbor-trivy是Harbor的漏洞扫描组件,它使用Trivy工具来扫描容器镜像以检测其中的漏洞。
  • • 与其他组件的关系:harbor-trivyharbor-core协作,以触发漏洞扫描任务,并将扫描结果与镜像元数据相关联
  • • 作用:harbor-registry是Docker Registry的扩展,用于存储容器镜像。它支持Docker镜像的推送、拉取和管理。
  • • 与其他组件的关系:harbor-registryharbor-core协作,以确保存储在Harbor中的镜像受到访问控制和安全性的保护。
  • • 作用:harbor-jobservice负责执行后台任务,如镜像复制、扫描和删除,以减轻主要服务的负担。
  • • 与其他组件的关系:harbor-jobserviceharbor-coreharbor-registry协作,接受任务请求并执行任务。
  • • 作用:harbor-core是Harbor的核心组件,负责处理镜像的元数据和权限管理,它维护Harbor中的用户、项目、镜像和仓库信息。
  • • 与其他组件的关系:harbor-coreharbor-portalharbor-registry通信,以响应用户请求,还与harbor-jobservice协作来执行任务,如镜像复制和删除。
  • • 作用:harbor-portal是Harbor的Web界面,提供用户友好的管理界面,用于浏览、搜索、上传和管理容器镜像。
  • • 与其他组件的关系:harbor-portal与其他组件通信以获取信息和执行操作。它向harbor-core提交请求,以管理镜像、项目和用户。
  1. 1. harbor-portal
  2. 2. harbor-core
  3. 3. harbor-jobservice
  4. 4. harbor-registry
  5. 5. harbor-trivy
  • 数据持久化
  • • 如:openebs(本文使用),其他还可使用NFS,Minio等。
  • • 作用:Harbor支持多种存储,作为镜像仓库和Chart的后端存储,实现数据持久化。
  • • 与其他组件的通信:Harbor的核心组件与持久化存储进行读写操作,以存储和检索容器镜像数据。
  • • 数据存放位置:通过PVC持久化到本地或共享存储,高可用部署需要共享分布式存储。
  • • Harbor组件的持久化数据(Helm 默认安装):这些数据卷用于确保数据的持久性和高可用性,并支持Harbor的正常运行和数据管理。
  • • 存放Docker镜像的实际数据。这是Harbor的核心组件,它负责存储和管理容器镜像。这个数据卷将包含Harbor中的各种容器镜像。
  • • Harbor的后台任务服务,可能会在内部使用一些临时数据或任务状态信息。
  • • 存放Trivy容器的数据。Trivy是用于漏洞扫描的组件,这个数据卷可能包含Trivy的扫描结果和相关数据。
  • • 如:data-harbor-redis-0
  • • 作用:Harbor使用Redis作为缓存,提供数据缓存功能,支持作业服务临时持久化作业元数据。保存会话信息。
  • • 与其他组件的通信:Harbor的各个组件可以与Redis进行通信,以快速访问缓存数据。
  • • 数据存放位置:通过PVC持久化到本地或共享存储,高可用部署需要共享分布式存储。
  • • 如:database-data-harbor-database-0
  • • 作用:Harbor使用PostgreSQL数据库来存存储Harbor的相关元数据,如项目、用户、角色、复制策略、标签保留策略、扫描策略、Chart和镜像信息。
  • • 与其他组件的通信: harbor-coreharbor-jobservice需要访问此数据库以维护Harbor的状态和元数据。
  • • 数据存放位置:通过PVC持久化到本地或共享存储,高可用部署需要共享分布式存储。
  • PostgreSQL (PG):
  • Redis:
  • 持久化存储
  1. 1. data-harbor-trivy-0:
  2. 2. harbor-jobservice:
  3. 3. harbor-registry:
参考链接

[1] Harbor的架构设计: https://github.com/goharbor/harbor/wiki/Architecture-Overview-of-Harbor


推荐阅读

相关实践学习
通过容器镜像仓库与容器服务快速部署spring-hello应用
本教程主要讲述如何将本地Java代码程序上传并在云端以容器化的构建、传输和运行。
Kubernetes极速入门
Kubernetes(K8S)是Google在2014年发布的一个开源项目,用于自动化容器化应用程序的部署、扩展和管理。Kubernetes通常结合docker容器工作,并且整合多个运行着docker容器的主机集群。 本课程从Kubernetes的简介、功能、架构,集群的概念、工具及部署等各个方面进行了详细的讲解及展示,通过对本课程的学习,可以对Kubernetes有一个较为全面的认识,并初步掌握Kubernetes相关的安装部署及使用技巧。本课程由黑马程序员提供。 &nbsp; 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情:&nbsp;https://www.aliyun.com/product/kubernetes
目录
相关文章
|
3天前
|
缓存 Linux 网络安全
docker的镜像无法下载如何解决?
【10月更文挑战第31天】docker的镜像无法下载如何解决?
119 28
|
17天前
|
缓存 监控 持续交付
|
5天前
|
存储 监控 Linux
docker构建镜像详解!!!
本文回顾了Docker的基本命令和管理技巧,包括容器和镜像的增删改查操作,容器的生命周期管理,以及如何通过端口映射和数据卷实现容器与宿主机之间的网络通信和数据持久化。文章还详细介绍了如何使用Docker部署一个简单的Web应用,并通过数据卷映射实现配置文件和日志的管理。最后,文章总结了如何制作自定义镜像,包括Nginx、Python3和CentOS镜像,以及如何制作私有云盘镜像。
56 2
|
7天前
|
关系型数据库 MySQL Docker
docker环境下mysql镜像启动后权限更改问题的解决
在Docker环境下运行MySQL容器时,权限问题是一个常见的困扰。通过正确设置目录和文件的权限,可以确保MySQL容器顺利启动并正常运行。本文提供了多种解决方案,包括在主机上设置正确的权限、使用Dockerfile和Docker Compose进行配置、在容器启动后手动更改权限以及使用 `init`脚本自动更改权限。根据实际情况选择合适的方法,可以有效解决MySQL容器启动后的权限问题。希望本文对您在Docker环境下运行MySQL容器有所帮助。
15 1
|
8天前
|
存储 Java 开发者
成功优化!Java 基础 Docker 镜像从 674MB 缩减到 58MB 的经验分享
本文分享了如何通过 jlink 和 jdeps 工具将 Java 基础 Docker 镜像从 674MB 优化至 58MB 的经验。首先介绍了选择合适的基础镜像的重要性,然后详细讲解了使用 jlink 构建自定义 JRE 镜像的方法,并通过 jdeps 自动化模块依赖分析,最终实现了镜像的大幅缩减。此外,文章还提供了实用的 .dockerignore 文件技巧和选择安全、兼容的基础镜像的建议,帮助开发者提升镜像优化的效果。
|
13天前
|
存储 缓存 Java
Java应用瘦身记:Docker镜像从674MB优化至58MB的实践指南
【10月更文挑战第22天】 在容器化时代,Docker镜像的大小直接影响到应用的部署速度和运行效率。一个轻量级的Docker镜像可以减少存储成本、加快启动时间,并提高资源利用率。本文将分享如何将一个Java基础Docker镜像从674MB缩减到58MB的实践经验。
24 1
|
19天前
|
Docker 容器
docker:记录如何在x86架构上构造和使用arm架构的镜像
为了实现国产化适配,需将原x86平台上的Docker镜像转换为适用于ARM平台的镜像。本文介绍了如何配置Docker buildx环境,包括检查Docker版本、安装buildx插件、启用实验性功能及构建多平台镜像的具体步骤。通过这些操作,可以在x86平台上成功构建并运行ARM64镜像,实现跨平台的应用部署。
218 2
|
3月前
|
存储 安全 Ubuntu
Docker 镜像与 Docker 容器的区别
【8月更文挑战第27天】
271 5
|
3月前
|
存储 Ubuntu 应用服务中间件
在Docker中,怎么快速查看本地的镜像和容器?
在Docker中,怎么快速查看本地的镜像和容器?
|
4月前
|
Shell Linux Docker
docker常用命令大全(基础、镜像、容器、数据卷)
这些命令仅仅是 Docker 命令行工具的冰山一角,但对于日常操作来说已经非常全面。通过熟练地使用这些基础命令,用户可以有效地管理 Docker 的镜像、容器、数据卷和网络。随着用户对 Docker 的深入使用,更高级的命令和选项将会变得必需,但上面列出的命令已经为用户提供了一个坚实的起点。对于初学者来说,理解和掌握这些常用命令是深入学习 Docker 的基础。
431 5
docker常用命令大全(基础、镜像、容器、数据卷)