ARTICLE · INTELLIGENCE

战地情报 · 详情页

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

国产开源制品管理工具Hadess实战:从部署到CI集成

国产开源制品管理工具Hadess实战:从部署到CI集成 先说一个真实场景上周同事找我说测试环境找不到上个迭代的war包开发机上翻来翻去只找到一堆带日期后缀的zip最后只能让QA先去用前一天的包顶着。这其实就是典型的制品管理缺失——构建产物散在开发机、CI机器、网盘和个人微信传输记录里版本对不对、谁打的包、部署过没有全靠口口相传。Hadess就是解决这个问题的国产开源制品管理工具它可以把你所有构建产物jar、npm包、镜像、二进制文件集中存储、统一版本、按权限分配让团队不再为了找包和确认版本反复拉扯。我前前后后在几套环境里用过它从单机测试到对接CI流水线都跑过一遍这篇文章把完整过程写清楚适合刚接手制品库搭建、想替换掉手工作业方式的开发/运维/测试同学直接照着做。1. 为什么需要制品管理工具先梳理痛点再谈选型1.1 没有制品库时研发流程有多痛很多人一开始觉得制品管理这个词很虚觉得我构建产物放在FTP上不也一样吗。我在一个小团队待过当时所有程序包都丢在一台共享机器的目录里按日期建文件夹。真正跑起来之后问题全出来了第一是版本追溯困难线上出了事故要回滚运维拉下来一个包没人能确认这是不是当初上线验过的那一个第二是权限失控谁都能删文件、覆盖文件有一次安装包被某个构建脚本误覆盖成了一半第三是整个团队的时间都耗在传包、找包、催包这种无意义沟通上。最可怕的是时间一长服务器上的目录就变成了一堆v2_final_20230115.tar.gz、v2_final_2_fixed.tar.gz根本没人敢清理。制品管理工具解决的就是这三件事存储所有产物都进仓库目录结构清晰、版本每次上传都是不可变记录随时可回溯、权限谁能上传、谁能下载、谁能删除都有明确规则。一句话解释它是什么你平时网购用的平台是商品的集散地Hadess就是软件构建产物的集散地开发把包寄上去运维和测试再按需取出来全流程有记录。1.2 为什么选Hadess而不是Nexus/Artifactory这里我不回避对比。Nexus和Artifactory是国外老牌制品仓库方案功能确实成熟。但很多国内团队落地时会碰几个现实问题商业版收费高小团队很难为制品库单独申请预算社区版虽然免费但像权限分组、高可用这些企业功能基本都要付费另外就是使用习惯和中文资料方面遇到问题去查资料英文论坛里翻半天也不一定能找到对口答案。Hadess是国产开源方案我用了之后的直观感受是上手门槛低常见功能都有文档和社区交流没有语言障碍。它把仓库管理、权限控制、外部仓库代理、构建工具对接这几个核心能力都做了对大部分中小团队来说完全够用。我选型时专门列过一张对比表列几个我当时关注的点能力维度团队原始方案FTP/网盘Hadess商业制品库集中存储有目录但无版本概念按仓库类型管理版本可追溯强项功能齐全权限管控基本无细粒度角色权限细粒度权限AD/LDAP集成外部依赖加速无Proxy仓库代理缓存支持学习成本无低中文文档中等成本无开源免费按GB/年费授权这表不是替你做决定但能提供一个思考框架如果团队只有二三十个人、制品体量不大、又不想在基础设施上花太多钱Hadess这类国产开源工具是性价比很高的选择。如果你们有严格的审计、高可用、多数据中心诉求那再评估商业方案也不迟。2. 安装前的环境准备这些不规划好后面全是坑2.1 软硬件要求与版本选型建议先说结论Hadess本身对服务器要求不算高我甚至在一台2核4G的旧机器上做过验证性部署日常小团队使用完全能撑住。但要跑得稳还是要按实际并发和制品大小留出余量。参考建议是4核8G起步系统盘之外单独挂一块数据盘。这跟很多中间件的要求一样不是配置越高越好而是要看瓶颈在哪里——制品库的瓶颈几乎都在磁盘IO和网络带宽CPU反而不是主要矛盾。软件方面Hadess基于Java技术栈安装前需要确认JDK版本。我用的版本要求JDK 11及以上装之前最好统一一下团队环境。这里有个小提醒如果你服务器上同时有多个Java应用别轻易改系统全局JAVA_HOME可以把Hadess的启动脚本里单独指定JAVA_HOME路径避免影响其他服务。操作系统上CentOS 7/8、Ubuntu 20.04、以及国产化操作系统如麒麟、统信我都见过有人跑适配性不错。版本选型上有一点要特别说不要一上来就追最新版。我当时犯过这个错一个刚发布的版本装上去发现有个插件兼容性问题折腾了半天又降级。合理做法是下载页面选稳定版标识的版本同时看一眼release notes里有没有已知问题。如果团队后续要用流水线集成尽量在测试环境先跑通一套再推广到生产。2.2 存储、端口与目录规划端口规划是新手最容易忽略的。很多同学装完发现启动失败查了半天才发现是端口被占了。Hadess默认端口是18080建议装之前先ss -lntp | grep 18080看一眼有没有被占用。如果公司内网有安全策略记得在防火墙/安全组里放通这个端口。另外它内部还有几个辅助端口用来做数据同步和RPC通信如果你用默认配置单机部署其实不用额外开但如果后面做集群部署这些端口就要一起规划好。目录规划我直接给一个我实际在用的标准/opt/hadess/server # 程序主目录 /opt/hadess/data # 制品数据目录 /opt/hadess/logs # 运行日志目录 /opt/hadess/backup # 备份脚本与备份产物目录最核心的决定是把data目录放到大容量数据盘上千万别把制品库数据和系统盘混在一起。制品库的数据增长速度远超预期一个中大型项目跑一年加上代理缓存几十个GB很正常。系统盘满了可不是小事轻则构建失败重则整个服务器写不进日志、各种服务连带出问题。我见过有人图省事直接装在 root 盘半年后磁盘告警迁移数据又停机又折腾得不偿失。2.3 生产环境部署前的一次性准备如果是正式环境我建议启动服务前先做三件事第一创建独立的运行用户不要用 root 跑Java服务。第二配置好系统文件描述符上限Java服务在高并发下文件句柄用尽会直接卡死。第三把数据目录的自动快照或备份策略先定好哪怕刚开始只是crontab里一条简单的rsync脚本。这里说一下为什么要用普通用户运行Hadess管理界面本身有权限体系但进程如果以 root 身份运行一旦Web界面出现漏洞或者被攻破攻击者就直接拿到服务器最高权限了。用普通用户运行至少把风险控制在一个隔离的账户里。创建用户和调整文件描述符上限都是常规操作列一下命令# 创建专用运行用户 useradd -r -s /sbin/nologin hadess # 调整文件描述符限制 echo hadess soft nofile 65535 /etc/security/limits.conf echo hadess hard nofile 65535 /etc/security/limits.conf3. 安装配置全流程从下载到Web界面初始化3.1 下载安装包、校验与解压去官网下载页找最新的稳定版压缩包文件名一般是hadess-server-1.4.2.tar.gz这种格式。这里要提醒一句下载后务必做校验。开源软件分发环节偶尔会出现文件被篡改的情况虽然概率低但这是基本安全习惯。正规项目一般会在下载页同时提供SHA256校验值用下面的方式核对一下sha256sum hadess-server-1.4.2.tar.gz把输出和官网核对一致了再解压。解压路径按之前规划好的目录来放到/opt/hadess/server下tar -zxvf hadess-server-1.4.2.tar.gz -C /opt/hadess mv /opt/hadess/hadess-server-1.4.2 /opt/hadess/server解压完成后看一眼目录结构熟悉一下bin/启动脚本、etc/配置文件、data/数据初始化目录大概都放了什么。这里面etc/application.yml就是核心配置文件后面大部分改动都在这里。3.2 JVM内存与核心配置修改打开配置文件之前先说一下原理Hadess作为Java应用启动时JVM会申请一块固定的堆内存。默认配置一般比较保守比如只给了2G。如果后续仓库里缓存了大量代理制品或者上传大文件时内存吃紧就可能在运行时频繁GC表现为界面卡顿、上传超时。我实际调整配置时主要改了这几处先看示例server: port: 18080 hadess: data: base-dir: /opt/hadess/data storage: max-size: 100GB jvm: heap-xms: 4g heap-xmx: 4g第一是server.port确认是目标端口第二是数据目录base-dir务必指向大容量数据盘第三是存储上限这个很实用相当于给制品库的磁盘占用设一个天花板防止它无节制增长把磁盘吃满第四是JVM内存的Xms和Xmx生产环境可以都设成4g让JVM启动时就把内存到位运行中不会动态伸缩。不要小看这个Xms/Xmx的设置我踩过一次坑默认起始堆特别小跑了一段时间后界面响应越来越慢排查了半天才发现是JVM一直在频繁做内存扩容和回收。把Xms和Xmx设为相同值后内存波动立刻小了。当然如果你服务器内存不大就老实按实际可用内存来设不要盲目贪大否则服务和数据库抢内存一样卡。3.3 用systemd管理服务再也不用手动启停了很多初学教程喜欢教你bin/hadess.sh start直接启动这样用着用着就会遇到问题进程是前台运行的SSH断开服务可能就挂了开机也不会自动启动。既然要生产化使用我建议直接注册成systemd服务。在/etc/systemd/system/hadess.service里写配置[Unit] DescriptionHadess Artifact Manager Afternetwork.target [Service] Typesimple Userhadess Grouphadess ExecStart/opt/hadess/server/bin/hadess.sh run ExecStop/opt/hadess/server/bin/hadess.sh stop Restarton-failure RestartSec10 WorkingDirectory/opt/hadess/server LimitNOFILE65535 [Install] WantedBymulti-user.target这里需要注意User和Group就是前面创建的专门运行账户不要用rootExecStart里的run参数是关键表示前台运行模式让systemd接管进程生命周期。配置好之后执行systemctl daemon-reload systemctl enable hadess systemctl start hadess通过systemctl status hadess能看到状态journalctl -u hadess -f可以实时看日志。这一步做完服务就具备了开机自启和崩溃自动拉起的能力比手动启动规范得多。3.4 Web界面初始化管理员账号与首个登录服务启动后浏览器访问http://服务器IP:18080会进入初始化向导。第一步是设置管理员账号密码。这里我要强调别再用admin/admin123这种默认密码制品库里存的是团队所有构建产物一旦被恶意下载或者被篡改损失的不只是代码泄露还有可能是上线包被替换的安全事故。我见过内部系统上用默认密码跑了大半年没人改的想起来都后怕。初始化向导里通常还会让你创建一个仓库组或者第一个仓库这一步可以跳过后面按实际需要配置。初始化完成后用管理员账号登录界面左侧一般就是仓库管理、权限管理、系统设置几个模块。刚开始会觉得界面元素比Nexus少但核心功能都在用熟悉之后会发现这种简洁设计反而省心。登录后建议立刻做的事情依次是修改默认管理员密码、开启操作审计日志、在系统设置里确认数据目录和日志路径是否正确。4. 仓库体系设计与权限管理先设计再动手4.1 三种仓库类型hosted、proxy、group我一开始用Hadess时看到仓库类型列表有点懵不知道从哪入手。它的仓库类型跟Nexus类似分三种hosted仓库本地托管仓库、proxy仓库代理仓库、group仓库聚合仓库。实操中理解这几种类型最好的方式是生活类比。hosted仓库就像你家楼下的自提柜团队自己构建的成品都放在这里别人来取号就可以拿走proxy仓库像一个代购你请求一个外部依赖时它先去中央仓库或阿里云镜像拉一份缓存到本地下次再要同一个依赖就不用再跑出去了group仓库是前台把好几个自提柜和一个代购合并成一个统一入口用户只需要配置一个地址就能同时用到本地制品和代理缓存。这三种仓库配合起来解决了两个核心问题让团队内部制品有固定存放处同时让外部依赖下载又稳又快。我实际环境里是这么搭的1个hosted仓库hadess-maven-local放自己项目构建的jar包1个proxy仓库hadess-maven-proxy代理Maven中央仓库和阿里云镜像1个group仓库hadess-maven-public把上面两个聚合成一个地址团队所有人只需要记住hadess-maven-public这一个地址就行。这个设计不是Hadess特有的是所有制品库的标准玩法但它确实是我建议每个团队先抄起来的基础架构。4.2 创建和配置仓库的实操步骤在Web界面左侧进入仓库管理点击新建仓库。以最常用的Maven类型为例填写几个关键字段仓库名称填maven-local这样的语义化名称别用拼音缩写后续配置要反复引用仓库类型选 hosted版本策略这里有个坑要按项目实际情况选 Release正式版或 Snapshot快照版如果你有个仓库想两种都放就选 Mixed。但我不建议轻易用Mixed因为正式版和快照版混在一起后续清理和溯源都会变麻烦存储路径默认就行实际文件会落在数据目录里proxy仓库的配置多一个上游仓库地址字段填你要代理的源。国内环境我一般建议填阿里云公共仓库https://maven.aliyun.com/repository/public如果你们有专门的内网源也是填这里。这里有个原理要说一下proxy仓库不是每次请求都去上游拉一遍它会把拉取过的文件缓存到本地下次直接返回缓存。所谓慢的只是第一次。group仓库创建时把刚才的 hosted 和 proxy 仓库都勾选加入。之后你给团队一个 group 地址就够用了。这里有一个排序的小细节group仓库里如果有多个库同时包含同一个包它会按你添加的顺序优先返回靠前的仓库内容。所以一般建议把本地hosted仓库放在列表前面保证团队自己上传的制品优先被匹配到。4.3 权限模型用最小权限原则划分角色权限设计这块很多团队初期会忽略想着反正就几个人用大家都给管理员就行了。我劝你不要这么做。制品库的权限失控后果比代码仓库严重因为制品是构建好能直接运行的包别人拿走去部署你根本不知道。Hadess的权限模型核心是用户-角色-仓库三层先建用户再建角色把仓库的具体操作权限绑到角色上最后把用户挂到角色下。实际操作中可以按这个模板划分角色权限范围适用人群制品管理员全部仓库的读、写、删除、配置管理基础设施管理员开发者所有仓库读 指定hosted仓库写团队开发人员只读访客指定仓库读测试/运维/审计这么设计背后的逻辑是开发需要上传自己的制品但不应该能删掉别人上传的包测试要能从group仓库下载依赖和验证包但不应该能往仓库里写东西只有管理员有全局配置和删除权限。逻辑说起来简单但落地时真正注意能读的不能写能写的不能删已经能避免大部分管理事故了。5. 集成实战让Maven构建和CI流水线都用上Hadess5.1 配置Maven的settings.xml仓库建好、权限分好接下来最关键的一步是让开发人员的构建工具真正用上它。对于Java项目这一步的载体就是Maven的settings.xml。以我之前环境中的maven-public仓库为例最关键的两段配置servers server idhadess/id usernamedeveloper/username password你的密码/password /server /servers这段是告诉Maven上传制品到id为hadess的仓库时用什么账号密码。然后配镜像和仓库地址mirrors mirror idhadess-mirror/id mirrorOf*/mirrorOf urlhttp://你的服务器地址:18080/repository/maven-public//url /mirror /mirrorsmirrorOf写作*表示所有仓库请求都走Hadess。这里多说一句不要真的所有项目都用*如果有的项目必须直连外部特定仓库源可以用external:*或者指定仓库名例如mirrorOfexternal:*,!central/mirrorOf否则会有依赖拉取异常。我实战时对部分老项目就是这样留下了一个直连通道避免一次性迁移引发太多兼容问题。配置完成后在项目里执行一遍mvn clean package观察日志里构建时请求的地址是否都已经指向Hadess。也可以去Web界面看proxy仓库的热度如果能看到新增的缓存文件说明镜像配置生效了。5.2 项目发布制品到hosted仓库依赖拉取搞定后第二步是把团队自己的制品发布上去。在项目pom.xml的distributionManagement里配置上传目标distributionManagement repository idhadess/id nameHadess Release/name urlhttp://你的服务器地址:18080/repository/maven-local//url /repository snapshotRepository idhadess/id nameHadess Snapshot/name urlhttp://你的服务器地址:18080/repository/maven-local-snapshots//url /snapshotRepository /distributionManagement注意几点这里的idhadess/id必须和settings.xml里server的id完全一致这样Maven才会拿对应的账号密码去做认证。然后执行mvn deploy第一次执行可能会报401认证失败。排查思路很简单确认server id是不是对得上、密码是不是明文写对、用户是不是有对应repo的写权限。这些都没问题基本一次就过。发布成功后去Web界面打开maven-local仓库能看到按groupId/artifactId/version组织的目录结构以后任何环境需要这个包配置同一个group地址就能拉下来。这里还有个经验正式版本号和SNAPSHOT版本号的规范要尽早定下来。Release版本应该是不可变的一次性记录上传后不要覆盖Snapshot版本则可以重复覆盖表示当前开发中的最新快照。这两种语义要在项目规范里写清楚否则仓库时间一长版本号混乱的源头就是你自己的团队规范。5.3 接入Jenkins/GitLab CI的流水线手工执行mvn deploy只是第一步制品管理的真正价值要在CI流水线里体现。我拿Jenkins举例。在流水线里做制品上传只需要在构建阶段后面加一个步骤stage(Deploy Artifact) { steps { sh mvn deploy -DskipTests } }如果项目已经配好了distributionManagement这一句就够了Jenkins会用构建服务器上settings.xml里配置的账号完成上传。核心要点是构建服务器的settings.xml文件路径和使用方式尽量和开发环境统一避免出现本地能发布、流水线发不上这种奇怪问题。GitLab CI类似在.gitlab-ci.yml里加一个job核心也是调用mvn deploy。关键在于把访问仓库的账号信息通过CI/CD变量注入不要硬编码在配置文件里。我见过有团队把密码直接写在脚本里仓库代码一泄露制品库也跟着失守。正确做法是在Jenkins的凭据管理或GitLab的CI/CD Variables里定义变量在流水线中动态替换到settings.xml。5.4 另一种常见需求直接上传/下载二进制制品不是所有项目都是Maven项目有时候我们就是想把一个.tar.gz或者安装包放上去给同事下载。Hadess也支持。有些版本自带raw仓库类型直接创建一个hosted类型的raw仓库然后在Web界面上传文件即可。我在界面里上传过一个约2GB的离线安装包中间没有断点续传的话容易超时所以大文件我强烈建议用命令行工具或者API方式上传稳定性高很多。平时描述这类直接上传网关其他人点链接就能下载的场景我会优先用raw仓库因为它最没有格式限制。比如一些配置文件、二进制数据库驱动、内部小工具脚本都可以丢进去。路径访问模式一般是http://服务器地址:18080/repository/raw/工具名/版本号/文件名直接在浏览器打开这个地址就能下载配合角色权限设置可以做到只有认证用户才能下载不放公网裸奔。6. 常见问题与排查技巧实录6.1 我实际踩过的五个问题用的过程中踩了不少坑有些问题当时折腾了很久我把典型问题归纳成了一张排查表现象可能原因解决思路服务启动后Web界面无法访问端口被占/防火墙未放通/systemd配置错误先看journalctl -u hadess -f日志再确认端口监听与安全组mvn deploy时报401settings.xml的server id与pom不一致、密码错误、用户无写权限逐项核对id/凭据/角色权限依赖拉取总是超时代理仓库上游地址失效/网络不通/源不稳定尝试换阿里云源或公司内网源注意第一次拉取就是慢磁盘占用越来越大没有配置存储上限代理缓存无限累积设置存储上限定期执行仓库清理策略上传大文件中断Web界面上传超时或连接被断开改用API/命令行方式上传或调大服务超时参数这里重点说第一个。服务起不来时很多人第一反应是重启一下。但systemd模式下最有效的动作是journalctl -u hadess -f看实时日志启动过程中的异常基本都会打到日志里。常见情况有数据目录权限不对用普通用户跑的但目录是root创建的、Java版本不匹配、端口被别的服务占了。日志里一般都能直接看到关键错误比瞎猜高效得多。6.2 关于备份、恢复与升级的建议制品库沉淀时间越长价值越高但同时风险也越大。如果服务器磁盘坏了制品全丢研发流程会被打断到接近瘫痪。所以备份这事我从第一天就在做。最简单可靠的备份方案是冷备在crontab里定期给数据目录打tar包或者用rsync同步到另一台机器/网盘。我自己的脚本大致长这样#!/bin/bash # 每日凌晨2点执行增量备份 rsync -avz --delete /opt/hadess/data/ backup-server:/data/hadess-backup/这段脚本看起来简单但增量备份的本质是利用rsync的差异传输每天只同步新增和变化的部分速度快、占用带宽小。如果是异地容灾要求更高的环境可以再加一个对备份目录的定期快照。至少要做到数据在另一台机器上有副本这是底线。升级这块我建议核心原则是升级前先备份升级时先读release notes升级后在测试环境跑通一遍再动生产。有一次我图省事直接在生产环境升了一个小版本结果配置格式有兼容性变更服务起不来差点影响当天发布。后来就学乖了先备份数据目录再在测试机模拟一遍升级流程确认没问题才在生产操作。整体来说Hadess的升级路径还算平滑只要别跳过版本太远基本就是把新包解压迁移旧数据目录重启服务。这里有个小技巧分享一下升级后如果界面出现异常但日志没有明显错误先清一下浏览器缓存或者换无痕窗口再试。我有一次纠结了好久最后发现是浏览器缓存了旧的静态资源清了之后一切正常。听起来很基础但真轮到自己排查时这种低级问题最容易忽略。6.3 权限模型的后期维护权限配置不是一次性的活团队人员会流动、项目会新增所以要定期梳理。我建议每季度做一次权限盘点重点看有没有离职人员账号还在有效状态、有没有人拥有超过岗位需求的权限、有没有仓库处于无主状态。Hadess里删除用户前先确认该用户名下是否还有作为构建账号被引用的场景比如CI里用到的账号一旦禁用了CI就会全部失败。我当时就吃过亏在Jenkins配置里用了某个账号后来清理权限时把这个账号禁了结果第二天流水线全挂了才想起来这个账号不只是给人用的。合理做法是区分人用的账号和流水线用的服务账号服务账号单独创建、密码定期轮换、权限严格限定在需要的仓库上。这个规划越早越好越到后期越难改。最后说点实际操作中的体会从第一次装Hadess到现在我最大的体会是制品管理工具的价值不是装完那一刻体现的而是跑了一两个月、经历过一次事故回滚之后才真正显现出来。当你发现线上这个包确定就是当初验过的那一个时那种底气是没做过制品管理的人体会不到的。如果让我给刚入手的团队三个建议一是提前规划好仓库类型和目录结构不要边用边改二是权限一开始就按最小权限原则分好宁可先收紧、后续再放开三是把备份策略定下来越早执行越好。这三点做到了基本不会出大问题。后面我还打算把Hadess和容器镜像仓库的联动、以及跨机房的制品同步实践整理出来等跑完一整套再分享。
RELATED READING

延伸阅读

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