ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Harbor私有镜像仓库搭建全流程:部署、权限管理与故障排查

Harbor私有镜像仓库搭建全流程:部署、权限管理与故障排查

搭建Harbor私有镜像仓库

如果你正在为团队里镜像到处乱放、命名全靠自觉、访问权限几乎为零的现状发愁,又或者已经试过官方Docker Registry但发现连个像样的管理界面都没有,那这篇就是给你写的。我在负责团队内部基础设施的时候,把Harbor私有镜像仓库从零搭到了线上,运维了快一年,过程中踩了不少坑,也积累了一些能直接复用的经验。今天打算把选型思路、部署步骤、参数配置、权限管理和常见故障排查完整地整理出来,让你拿到一篇能照着操作、少走弯路的东西。

先说一下Harbor到底是什么。它本质上是一个开源的云原生制品仓库,最核心的能力是管理容器镜像,同时也支持Helm Chart等云原生制品的存储和分发。相比官方Docker Registry,Harbor额外提供了Web管理界面、基于项目的权限隔离、镜像复制同步、垃圾回收、漏洞扫描、审计日志等功能。它的底层架构是Nginx反向代理加核心API服务、前端Portal界面、Registry存储、数据库和Redis缓存,整体通过Docker Compose编排,部署形态非常成熟,既有在线安装器也有离线安装包,尤其适合无法直连外网的生产环境。这篇文章适合正在规划镜像管理方案的技术人员、刚接手内部系统的运维同学,以及所有被“镜像四散在每个人的笔记本里”这件事折磨过的团队。

1. 为什么说私有镜像仓库是团队协作的必需品

1.1 团队早期使用Docker官方Registry的真实痛点

我们团队早期其实不是没有镜像仓库,用的是Docker官方开源的Registry镜像,Docker Compose跑一个容器,外挂一块存储目录,看起来挺干净。但真正用起来之后,问题一个接一个冒出来。最难受的就是没有UI,所有镜像列表都得通过HTTP API去查,非常不直观。镜像多起来之后,想找一个特定版本的镜像,就得手工去翻标签,完全没有搜索能力。更大的问题是访问控制,官方Registry本身只有非常基础的单用户鉴权,谈不上细粒度的权限管理。今天张三push了,明天李四也能删,项目之间完全没有隔离。一旦要审计谁在什么时间操作过哪个镜像,根本无从查起。

后来镜像数量从几十个涨到几百个,命名也开始失控,有人叫myapp,有人叫my-project-backend-v2,有人直接把本机IP当仓库名用。每次部署都要临时问“那个镜像叫什么来着”,效率非常低。更离谱的是,有一回某位同事的本地镜像被误删了,恢复无门,整个团队陪着他重新构建打包发布,白白折腾了大半天。那段时间大家明显感觉到,镜像管理这件事已经不能再靠自觉和临时脚本去维持了,必须上一套正经的内部镜像管理系统。

1.2 主流私有镜像仓库方案横向对比

在确定选Harbor之前,我其实把市面上常见的几套方案都过了一遍。单纯从“能放镜像”这个角度来说,官方Registry最轻量,一个容器直接跑,但它只解决了“能存”的问题,管理、权限、审计这些全都欠账。Sonatype Nexus也有一批用户喜欢用,它更像一个通用制品库,Maven依赖、npm包、Docker镜像全能塞,但它的Docker镜像管理体验比较“通用化”,在镜像专用特性和云原生生态整合上不够深入。还有一类是云厂商提供的镜像仓库服务,托管式、功能全,但对内部环境来说存在外部依赖,而且绝大多数是公网服务,不适合完全离线的生产场景。

相比之下,Harbor的优势非常明确。它是专门为容器镜像和云原生制品设计的仓库,原生支持项目概念,一个项目一套权限体系,成员角色清晰可控。镜像复制、漏洞扫描、垃圾回收、Webhook通知、基于Tag的保留策略,这些日常运维高频能力它全都内置了,而且安装部署是标准的Docker Compose,不像Nexus那样涉及复杂的应用内配置。所以最终我们团队选择了Harbor,核心原因就是它真正围绕着镜像的生命周期把该有的功能都做齐了,操作路径清楚,不用我这个负责运维的人天天写胶水脚本去补基础能力的窟窿。

1.3 一套仓库解决的不只是存储问题

实际上,一个像样的私有镜像仓库解决的绝对不只是“把镜像放在哪”的问题。它对日常研发交付流程的推动是立竿见影的。镜像仓库就相当于代码仓库,一套命名规范、一套权限模型,天然就把不同团队、不同项目的产物隔离开了,A组做的镜像不会无意中覆盖掉B组的。配合简单的Web界面,任何一个开发同学打开浏览器就能看到自己项目的所有镜像版本,不用再去命令行敲一堆API。从质量管控的角度,Harbor的漏洞扫描能力也能在镜像push之后自动触发,把基础镜像层和依赖层的已知漏洞暴露出来,安全团队再也不用挨个节点去查。

从后续扩展性来看,Harbor的多实例复制功能让我们在做容灾和跨机房部署时非常从容,只要在主仓库配一条复制规则,镜像就能自动同步到备份仓库,这个能力对规模化团队来说几乎是刚需。所以如果你所在团队已经有了一定规模,或者正在从“每人一台机器随便折腾”往“统一交付流水线”的方向演进,上一套Harbor是一个性价比极高的决策。

2. 部署前置条件:硬件、软件与安装包选型

2.1 最低硬件要求和真实生产建议

Harbor本身对硬件的要求并不高,官方推荐的其实比较保守,但你可以根据实际情况来调整。单纯搭建一个内部测试用的仓库,2核CPU、4G内存、50GB磁盘就够跑了,我在一台虚拟机上用这个配置跑过半年,镜像总量在两百个左右,日常使用没什么压力。如果是团队正式使用,我需要多说一句内存的事。Harbor的Trivy漏洞扫描组件和Jobservice容器对内存都比较敏感,扫描大量镜像的时候内存会明显上升。平台后期我一定会推荐至少4核8GB起步,存储空间则要根据团队镜像的增长速度来估算,保守一点按“每个服务每周产生5个Tag,单镜像平均800MB”这个模型去算,半年下来轻松超过100GB,所以磁盘最好独立挂载并预留足够的余量。

这里还需要提醒的是,Harbor的数据目录默认在/date目录下面(这个后面会具体讲),如果你用的是系统盘,等仓库跑起来再想迁移数据就会非常被动,必须停服、同步、再切换,中间一刀出错镜像全没。所以一定在部署前就把数据目录规划到独立分区或者独立存储盘上,这个规划往往决定了后续运维的轻松程度。

2.2 Docker与Docker Compose版本要求

Harbor部署依赖Docker和Docker Compose,安装之前需要确认两条线上均满足版本要求。Harbor依赖的Docker版本一般在17.06.0及以上,考虑到现在主流的Linux发行版自带的Docker通常都已经比较新,这一条基本不会卡住你。但Docker Compose版本容易忽略,如果是老机器上原装的docker-compose 1.18这类旧版本,Harbor的编排文件可能会报错提示版本过低。我用过的方案是直接安装官方独立的docker-compose二进制文件,推荐使用比较新的v2.x版本,同时执行chmod +x赋予可执行权限,再放到/usr/local/bin下面。实测下来,用新版Compose跑Harbor的编排文件没有任何兼容性问题。

另外,部署之前还需要检查端口占用。Harbor默认通过80和443端口对外提供服务,如果服务器上已经跑了Nginx或者别的Web服务,大概率会出现端口冲突。解决办法之一是直接改Harbor配置文件里的HTTP端口,比如改成8080,后续所有客户端访问、docker login都使用这个端口,记得同步放通防火墙。我不建议在没搞清楚当前端口占用情况的前提下就直接跑安装了,很多第一印象里“Harbor死活用不了”的案例,最后查出来都不过是端口被占。

2.3 在线安装包与离线安装包的取舍

Harbor官方提供两种安装方式:在线安装器和离线安装器。在线安装器是一个很小的脚本包,运行时会从Docker Hub拉取Harbor相关的全部镜像,优点是下载体积小,但缺点也很明显——安装过程完全依赖外网,网络一波动就各种失败,还容易遇到Docker Hub限速的问题。离线安装包则把全部镜像文件打包在一个几百MB的压缩包里面,解压即用,安装过程完全不依赖外网,这对内网环境来说几乎是唯一的正确选择。就算你的服务器有外网能力,我也推荐用离线包,因为生产环境部署讲究的是确定性和可重复性,离线包版本锁定、镜像内容一致,不存在“昨天能装今天报404”的玄学问题。

下载离线包的时候注意核对文件校验码,Harbor官方发布页面会同时给出对应的SHA256值。我之前因为手滑下错过一个不完整的压缩包,解压时直接报错,浪费了一些时间。生产环境尽量养成每次下载都跑一遍校验和的习惯,这不是多余,是基础习惯。

2.4 证书策略选择:HTTPS还是HTTP

Harbor支持HTTPS和HTTP两种对外服务方式。生产环境当然应该用HTTPS,但如果你是内网自用,没有可信的CA证书,配置HTTPS容易给团队添堵。因为客户端机器如果不信任你自签的证书,docker login会直接报“certificate signed by unknown authority”,到时候每个人都要手动把证书塞进系统信任目录,操作成本完全取决于团队规模。所以在内部环境的实际部署中,我更推荐先以HTTP方式跑起来,然后在每台客户端Docker的daemon.json里配置insecure-registries,把这个仓库地址声明为“非安全仓库”,这样Docker就允许以HTTP方式访问。这个方案在内网环境非常稳,也不用维护证书生命周期。

如果确实需要走HTTPS或者未来要暴露给更广的访问范围,那就把正式的SSL证书放到Harbor配置里,同时修改harbor.yml中的certificate和private_key路径,再重新执行prepare和install。这部分我建议在规划期就想好,因为中途从HTTP切HTTPS,客户端daemon.json的改动还要再推一轮。

3. Harbor离线安装全流程实操

3.1 解压安装包与初始配置

拿到离线安装包之后,把它放到规划好的安装目录,直接解压。解压之后目录里会出现一个harbor.yml.tmpl文件,这是官方给我们的配置模板,后续所有关键参数都在这个文件里改。还记得我前面提到的端口和数据目录规划吗,现在就需要用它们了。先执行复制命令,把harbor.yml.tmpl重命名成harbor.yml:

cp harbor.yml.tmpl harbor.yml

用vim编辑文件,重点修改几个参数。hostname必须填客户端能访问到的地址,如果是演示环境就用服务器IP,比如192.168.1.100,如果有解析好的内部域名也可以填内部域名。HTTP端口我建议不要用80,尤其在服务器上可能还有别的服务在监听的时候,改成8080最省心:

hostname: 192.168.1.100 http: port: 8080 https: port: 443 certificate: /your/certificate/path private_key: /your/private/key/path

需要注意,官方模板默认把https段落写在里面,如果你打算用HTTP一键跑起来,一定要把https相关的三行全部注释掉,否则prepare阶段会因为找不到证书文件直接报错。harobr_admin_password是admin管理员的初始密码,默认是Harbor12345,部署之前就改成你们团队自己的强密码,别等到上线后才想起改,这时候配置已经固化进去了,改起来反而麻烦。data_volume对应数据目录,改成你规划好的挂载盘路径,例如/opt/harbor-data。数据库密码我也建议直接改掉,Harbor会把默认密码写入数据库容器,不做修改就太像是一把公共钥匙了。

3.2 运行prepare与install脚本

配置保存后先执行prepare脚本,这个脚本的作用是根据harbor.yml生成容器编排所需的配置文件和证书材料,可以说它是整个安装流程里最容易暴露问题的阶段。如果输出出现类似“ERROR:root:Please set hostname”这类信息,基本可以断定是harbor.yml里必填项缺了或者格式错了,回头检查即可。

prepare运行没有报错之后,直接执行install.sh。如果你需要启用漏洞扫描组件Trivy,可以带上参数,比如:

./install.sh --with-trivy

我建议在正式环境把Trivy加上,Harbor界面里就能直接看到镜像漏洞报告,这是我们团队能及时处置基础镜像漏洞的关键一环。另外如果你团队有Helm Chart管理需求,也可以在后面追加--with-chartmuseum参数,不过现在新版Harbor已经把Chart管理功能整合进了制品类型里,没有单独组件那么割裂的感觉了。带不带参数取决于你的实际需求,但不要一上来就全量启用所有组件,组件越多,占用的资源越多,出问题时的排查面也越广。

启动过程会输出一系列Creating network、Creating container之类的日志,最后以“✔ ----Harbor has been installed and started successfully----”结尾,就代表安装成功了。这时候用docker ps看一眼,正常会看到harbor-core、harbor-registry、harbor-jobservice、harbor-portal、harbor-db、harbor-redis、nginx等容器处于Up状态,其中nginx就是统一入口。

3.3 启动后的初始验证与密码问题

安装完成后,在浏览器地址栏输入服务器IP和端口,例如http://192.168.1.100:8080,应该能看到Harbor的登录界面。用admin和你刚才配置的密码登录,进入之后先看左侧的“系统管理”,把项目配额、默认仓库配额这些按团队实际使用习惯设置一下,不要让它无限制增长,后期磁盘爆满才不会猝不及防。

如果你中途把密码弄丢或者忘了,最稳妥的还是在部署前把harbor.yml里的配置留存好。真到了密码丢失的情况,官方其实提供了一套通过PostgreSQL直接重置密码的方法,但步骤很繁琐,需要手工生成bcrypt哈希再更新数据库。我个人的建议是,正式部署之前就把密码写进团队密码管理工具,别把唯一的密码只放在自己的记事本里。

3.4 安装过程中最容易翻车的几个地方

安装过程看似简单,最容易翻车的点其实集中在三类。第一类是防火墙没有放通端口,浏览器访问页面卡死,看起来像Harbor挂了,但容器全是Up状态。这时候先确认防火墙规则,把访问端口放行即可。第二类是配置文件中少了必要参数或者格式不对,尤其是缩进错误,YAML对空格很敏感,一个缩进错位就会让prepare阶段报错。第三类是系统时间或者时区问题导致日志时间错乱,排查问题的时候看着日志总觉得对不上号,建议在部署前就把系统时区统一成Asia/Shanghai。这些都是我第一次部署Harbor时踩过的坑,记录下来,主要是为了让你绕过它们。

4. 客户端接入:从配置Docker到成功推送镜像

4.1 客户端Docker的安全配置

镜像推送和拉取全部依赖每台客户端机器上的Docker命令行,所以配置完Harbor服务端之后,还要在每一台需要访问镜像仓库的机器上配置Docker daemon。在/etc/docker/daemon.json中加入insecure-registries节点,这里举一个配置示例:

{ "insecure-registries": ["192.168.1.100:8080"] }

保存之后执行systemctl restart docker重启Docker服务。如果没有这个配置,单纯用HTTP访问Harbor时,docker login就会因为证书不信任直接拒绝你。配置里的地址格式要与harbor.yml中的hostname和端口完全一致,包括协议之外的所有部分,否则Docker依然不认账。这里还有个小细节,如果你后续把Harbor的hostname从IP改成了内部域名,所有客户端daemon.json都要同步改,尽量让这个地址保持稳定。

4.2 创建第一个项目和用户

进入Harbor Web界面后,左侧选择“项目”菜单,点击“新建项目”。项目名称建议和代码仓库名保持一致,比如我们内部有个订单服务,项目名就叫order-service,镜像前缀直接用项目名,后续所有该服务的镜像都push到这个项目下面。项目访问级别有“公开”和“私有”两个选项,内部基础设施我建议全部设为私有,虽然现在团队有权限管理系统,但公开项目意味着任何登录Harbor的人都能直接拉取镜像,这个风险没必要冒。只有那些公开的基础镜像层,比如构建缓存、通用工具镜像,才考虑公开。

然后进入“系统管理”下的“用户管理”,创建团队成员账号,并为每个项目分配相应的角色。Harbor的角色体系相对清晰,项目管理员拥有项目的完整管理权限,维护者可以推送和拉取镜像并管理标签,开发人员可以推送和拉取镜像,访客只能拉取。给每个项目至少配一个维护者,把核心开发成员设为开发人员,把只读使用者设为访客,这个模型对大部分团队都够用。

4.3 docker login与镜像推送的完整链路

现在在客户端机器上试一下登录:

docker login 192.168.1.100:8080 -u 用户名 -p 密码

登录成功之后,给本地镜像打上Harbor仓库地址的Tag。假设本地有一个nginx:1.24镜像,想推送到order-service项目里,正确做法是:

docker tag nginx:1.24 192.168.1.100:8080/order-service/nginx:1.24 docker push 192.168.1.100:8080/order-service/nginx:1.24

这里的镜像名称拼接逻辑要理解清楚,仓库地址+项目名+镜像名+版本号,整个串起来才是Harbor库里唯一标识。推送完成之后,回到Harbor的Web界面,刷新项目的仓库页面就能看到刚才推上去的镜像了。

4.4 镜像推送实践的几点经验

用了一段时间后,我总结了几个镜像推送环节的经验。Tag命名一定要有规范的版本策略,不要直接打latest,生产环境务必带具体版本号,最好是Git版本号或CI流水号,因为latest只适合手动测试,一旦多人同时push,基于latest做部署回滚就会变得非常痛苦。另外尽量在镜像推送之前就把漏洞扫描的触发规则配好,Harbor支持在项目里开启“自动扫描镜像”,这样每次推送完就不用手动去触发扫描,安全状态一目了然。最后我建议项目内开启镜像保留策略,比如保留最近30个版本,超出自动清理,这能有效阻止镜像数量无限膨胀。

5. 权限模型与多团队隔离的落地经验

5.1 项目、仓库与镜像三层模型的含义

Harbor把权限体系设计成了三层结构:项目、仓库和镜像Tag。项目是权限控制的基本单元,类似于代码仓库里的小组目录;仓库是项目下的具体镜像集合,一般一个仓库对应一个微服务;镜像Tag则是某个仓库里的具体版本。这套模型落到实际使用中,最常见的方式就是按团队或者按业务系统建项目。比如支付团队的所有镜像放在payment项目里,订单系统放order-service项目里,各项目之间默认隔离。这种隔离方式比单纯地在同一个仓库里靠命名区分清晰得多,哪怕两个团队的项目有部分成员重合,也只需要给具体人员单独分配角色就行,不会污染整个仓库的数据结构。

5.2 角色权限矩阵

Harbor内置的角色权限划分比较精细,主要角色之间的差异我用一张表来说明:

角色推送镜像拉取镜像删除镜像管理项目成员管理项目配置查看日志
项目管理员支持支持支持支持支持支持
维护者支持支持支持部分部分支持
开发人员支持支持不支持不支持不支持支持
访客不支持支持不支持不支持不支持仅自操作

这个矩阵在实际使用中非常够用。项目管理员一般由技术负责人承担,维护者可以放宽到每个服务的核心开发,开发人员是日常写代码主力,访客则给那些只是需要用镜像但不产出镜像的角色,比如测试和运维。实践下来,权限模型最忌讳的是把所有成员都设成项目管理员,一旦有问题需要追溯,你会发现谁都看了、谁都改了、谁都删了,审计无从谈起。所以即便在一个很小的团队,也建议维持“角色最小化”的原则。

5.3 多团队隔离的配置技巧

在多个团队共用一个Harbor实例的情况下,有几个配置技巧能有效减少摩擦。每个团队的项目名称建议带上团队前缀,比如team-pay-order-service,虽然名字长了一点,但在全局搜索镜像时能一眼看出归属,避免出现两个团队都建了叫common-base的项目时搞不清楚是哪个交付物的问题。项目配额也建议按团队预估用量设置单独配额,尽量不要用统一默认的无限配额,否则某团队误传一个大镜像就能把整块数据盘占满,其他团队全部遭殃。团队成员分配角色时,尽量用“批量导入用户再分配”的方式。如果公司有LDAP或者OAuth统一认证,Harbor也支持对接,这样成员进离职时的账号权限就能自动同步,省去的运维工作不是一点半点。

6. 镜像复制同步与规模化落地

6.1 复制功能解决的场景

当Harbor真正跑起来之后,你会发现基础设施的规模不会停留在“一台机器一个仓库”的阶段。我们团队很快就遇到了两个实际场景。一是容灾需求,主仓库所在的服务器一旦出现磁盘故障或者数据中心级故障,客户端就完全没法拉镜像了,业务交付直接中断。二是跨地域部署需求,远程机房的机器每次从总仓库拉取大镜像,跨广域网的传输速度让人抓狂,几百MB的镜像可能要拖十几分钟。Harbor的镜像复制功能正好覆盖这些场景,它允许你在一个Harbor实例上定义复制规则,将特定项目或特定镜像自动同步到另一个Harbor实例。

6.2 创建复制规则的配置要点

创建复制规则的入口在“系统管理”->“复制管理”,新建规则时需要指定目标实例和资源过滤器。目标实例可以是另一个Harbor实例,也可以是其他与Docker Registry API兼容的仓库。以两个Harbor实例为例,在源实例上填写目标实例的地址、访问凭证,再选择资源过滤方式,比如复制整个项目,或者复制满足命名条件的镜像Tag。触发模式可以选“手动”或“定时”,如果只是为了容灾,我建议先用手动触发,按季度或按发布窗口跑一次;如果是跨机房分发,建议改成“基于事件触发”,也就是镜像push完成后立刻自动同步到远端,这种方式在体验上几乎无感知。

6.3 复制的状态监控与常见问题

复制任务执行时,可以在界面的“复制任务”里看到每条任务的状态。一旦出现复制失败,优先检查源实例和目标实例之间的网络连通性,以及目标实例的账号、密码和端口是否正确。有一回我们复制规则一直报401错误,排查了半天才发现是目标实例升级过一次,admin密码变了,而源仓库里保存的还是旧密码,更新之后立刻恢复。另外跨机房同步时要注意带宽占用,大批量镜像同步会挤占网络链路,建议设置在业务低峰期执行,或者利用带宽限制策略,避免影响正常业务流量。镜像复制功能虽然简单,但它是整个高可用体系里非常坚实的一块基石。

7. 常见故障排查实录

7.1 docker login阶段常见问题

所有用户接触Harbor的第一道工序都是docker login,这里出现问题的概率也最高,我把实际遇到过的情况整理成了一张排查参考表:

症状可能原因解决办法
报x509证书错误客户端未配置insecure-registries在daemon.json加入仓库地址并重启Docker
提示连接被拒绝端口未开放或服务未启动检查防火墙、Harbor容器状态
报401 Unauthorized用户名或者密码错误到Harbor界面用admin重置该用户密码
一直卡在登录网络不通或DNS解析错误用telnet/curl测试端口连通性

除此之外,不少同学容易忽略的还有daemon.json的配置格式问题。insecure-registries一定是数组形式,每一项要完整带上IP和端口,就算Harbor用的是默认80端口也必须写成“192.168.1.100:80”,不能省略端口直接写IP,否则Docker会认为访问的是443。这类配置问题很反直觉,但只要经历过一次就记住绝缘了。

7.2 镜像推送与拉取异常

镜像推送阶段最容易遇到两类情况,一类是磁盘空间不足导致写镜像失败,Harbor的registry容器日志里会出现类似“no space left on device”的报错。这种情况光删镜像未必有效,因为即使你删了Tag,底层数据可能还赖在磁盘上,需要用Harbor的垃圾回收功能来真正释放空间。另一类是push时提示“413 Request Entity Too Large”,这个多见于Nginx层对上传body大小有限制,但Harbor官方镜像默认并没有这个限制,更常见的原因其实是客户端到服务器的整个链路中还有别的代理层在拦截,比如团队统一网关或者自行加的反向代理,走Harbor自带Nginx直连一般没有这个问题。

拉取阶段如果出现“manifest unknown”这类提示,通常是Tag不存在、项目名字拼写错误,或者你拉取的是复制还没完成的远程项目镜像。先到Web界面确认一下镜像是否真实存在,排除前端显示延迟问题,再核对标签名称。

7.3 存储和磁盘空间治理

这是运维Harbor的最核心课题,没有之一。我实际运维中几乎每个月都要处理一次磁盘告警,刚建仓时只有一个项目几十个镜像,感觉非常宽裕,一旦CI/CD流水线跑起来,每天都能有上百个新Tag生成,Tag只增不减,磁盘空间呈线性上涨。Harbor本身并不自动修剪旧Tag,需要我们主动配置保留策略和定期垃圾回收。

保留策略配置在项目详情里,可以设置每条仓库保留最近N个Tag,超出部分由系统自动清理,这对防止仓库膨胀非常有效。垃圾回收则负责真正从存储层面清理索引和残留数据,在“系统管理”->“垃圾回收”里手动新建任务,或者按周期计划执行。需要特别提醒的是,垃圾回收期间Harbor的Registry组件是只读的,如果团队还在跑线上发布,尽量把GC任务放在低峰期,同时Harbor新版提供了“暂停Registry”的选项,配合GC使用可以确保一致性。GC结束之后,数据卷里的碎片空间才会被真正释放,磁盘大小不会下降在UI上显示,别误以为GC没生效。

7.4 服务层面的异常排查思路

Harbor整体是Docker Compose编排的容器集群,日常服务异常排查思路和普通容器服务类似。先看容器状态,docker ps确认哪些容器是Up,哪些是Exited或Restarting。如果某个关键容器反复重启,多半是配置错误、数据目录权限不对,或者某个底层依赖没初始化完成。这时候看日志是最直接的,执行docker logs命令查看具体报错信息。比如harbor-db容器启动失败,日志里十有八九会提示权限问题。有一回我们换了挂载盘,忘记了数据目录的属主配置,导致数据库容器一直无法初始化,最终通过chmod调整目录权限解决。遇到Harbor整个界面打不开的情况,优先确认core服务和nginx日志是否正常,很多看似诡异的问题最终都落在网络层,先确认端口能通再考虑其他。

7.5 升级与备份的小白操作流程

Harbor更新的节奏官方维护得不错,我基本上每隔一段时间就会升级一次。升级流程官方在文档里已经写得很清楚,先用新版本离线包同目录解压覆盖旧包,然后执行./upgrade.sh,脚本会自动检测当前版本并迁移数据。但升级前一定要做备份,强烈建议把数据目录和harbor.yml配置文件整体打包一份,尤其数据库里的元数据。备份时机放在低峰期,打一个带时间戳的tar包,放到非系统盘里,我建议保留至少3份滚动备份。升级完后马上用docker ps和Web界面验证一遍,确认镜像列表、权限配置、复制规则都还在,再让团队成员继续使用。这个过程只要做过一次,后续升级就会非常从容。

8. 结语:把镜像仓库当成基础设施来认真对待

搭建Harbor本身不算难,难的是把它持续稳定地维护下去。我在实际运维过程中最大的体会是,镜像仓库不是搭完就能不管了,它和代码仓库一样,需要在初期就定好命名规范、项目划分、权限策略、保留策略,并且随着团队规模增长而不间断地调整。个人推荐给团队至少准备一份内部文档,把Tag命名规范、登录方式、常见问题快速排查方法都写进去,新人来了不用每次反复问。镜像仓库做得规范了,整个交付链路都会变得非常顺畅:CI/CD流程能安心把构建产物推上来,生产部署节点能快速拉到准确版本,安全团队也能通过漏洞扫描守住基础镜像的质量底线。希望这篇实操记录能帮你少踩一些坑,如果有遇到其他奇怪的问题,欢迎按照文中的排查思路一步一步去试,绝大多数问题到最后都会有明确答案。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进