首页 / 资讯中心 / 文章详情

CubeStudio离线部署全流程:镜像导出、Harbor搭建到内网落地

CubeStudio离线部署全流程:镜像导出、Harbor搭建到内网落地 ★ FEATURED ARTICLE
接到这个任务的时候我其实没太当回事——内网部署嘛不就是把镜像导出再导入吗真正动手才发现CubeStudio的离线部署远不是一条docker save就能解决的。你要面对的是一个“完全无外网”的物理隔离环境机器装的是信创系统还有可能是ARM架构Docker镜像、模型文件、离线依赖包全都得靠一台“出口机”想办法弄进去。这篇文章我把整套流程拆开讲清楚从镜像导出、Harbor内网搭建到目标机拉取部署每一步的关键参数、配置内容和避坑点都会提到。如果你正在做企业大模型平台的私有化落地或者在信创环境做安全交付这篇实操记录可以直接拿来当作业抄。1. 先把问题想清楚离线部署到底难在哪1.1 CubeStudio这类平台的部署形态CubeStudio本质上是一个面向大模型应用开发和调度的企业级平台交付形态上至少包含Web前端、后端API、任务调度引擎这几个组件。这类平台现在主流的交付方式是容器化——一套Docker Compose或者Kubernetes编排文件加上十几个到几十个镜像再附带若干GB的模型权重文件。也就是说你要往内网搬的不是一个软件包而是一整套镜像仓库和运行环境的依赖链。问题就出在这里内网机器没有外网装完系统之后Docker本身可能能用但机器上没有镜像、没有依赖、没有基础运行库。如果只是手动docker load一个个导镜像多了根本维护不了后面想回滚、想扩容、想多节点部署基本就废了。所以第一步不是急着跑部署脚本而是先把“软件如何进入内网”这条链路设计清楚。这也是我把这一篇定位成“全流程实操”的原因——真正值钱的不是某一条命令而是命令背后的整体思路。1.2 为什么选Harbor而不是裸registry我一开始也想过内网用一个registry:2镜像搭个最简仓库几百MB搞定简单直接。但实际对比之后我发现对于交付场景来说registry根本扛不住对比维度裸 registryHarbor界面管理无全靠命令行Web UI项目/用户/镜像管理清晰权限控制无按项目分用户支持LDAP对接审计日志无操作记录完整交付验收常需要漏洞扫描无内置Trivy扫描镜像复制手动支持多实例复制对后面异地交付有帮助部署复杂度极低中等离线包也就几百MB可接受信创环境交付经常要提供一套软件资产清单和镜像列表这些是裸registry给不了的。另外部署完不是结束后面内网还要持续补镜像、升级版本Harbor的Web UI对同事来说友好太多了。如果你只是想临时验证裸registry可以但生产环境和正式交付我建议直接上Harbor。1.3 内网链路里要置办几个角色整条链路我设计了三类角色缺一不可角色网络环境职责出口机临时可访问外网拉取镜像、导出成离线包中转存储内网运行Harbor统一接收镜像并对外提供拉取目标机内网从Harbor拉取镜像运行CubeStudio这里需要特别说明一下“出口机”这个角色。它指的是整个网络里唯一被允许在特定窗口期临时接入外网的那台机器作用是充当“采购员”和“搬运工”——在外面把货买齐、打包再通过合规的摆渡方式把离线包送进内网。整个过程不建立任何常驻的跨网连接出口机在完成下载后物理断开。这套设计最大的好处是内网全程自闭环Harbor只暴露内网IP出口机不参与运行不存在“内外网直连”的通道。2. 出口机备货镜像导出阶段的几个关键动作2.1 出口机环境确认出口机不需要很高配置但有两件事必须提前确认。第一Docker版本。建议20.10以上原因是后面导出的镜像默认使用OCI格式老版本Docker在load和push时容易出现兼容问题。我实测过18.09在push大镜像时偶尔会报“layer already exists”的假失败换新版之后基本没这个毛病。第二磁盘空间。至少要留出镜像总大小2倍的余量。假设CubeStudio相关的镜像加起来30GB导出tar包时占一份30GB在目标机load时又要解压一份临时文件一多很容易把磁盘打满。更别说还有模型文件这块空间宁多勿少。我习惯先在出口机上建一个工作目录比如/opt/cubestudio-offline把镜像清单、校验文件、配置模板全放进去逻辑清晰后面拷进内网也方便。2.2 拉取镜像并统一打tag拿到交付方提供的镜像清单之后不要急着docker pull先按目标Harbor的地址规划好命名。假设内网Harbor地址是192.168.209.133:8443项目名是cubestudio那么每条镜像都要重打成这样docker tag cubestudio/backend:3.2.1 192.168.209.133:8443/cubestudio/backend:3.2.1 docker tag cubestudio/frontend:3.2.1 192.168.209.133:8443/cubestudio/frontend:3.2.1 docker tag cubestudio/scheduler:3.2.1 192.168.209.133:8443/cubestudio/scheduler:3.2.1这一步经常被人偷懒跳过觉得load的时候不需要保留仓库地址。我给你一个必须做的理由Harbor是根据镜像名里的“仓库地址/项目名”来路由存储路径的如果镜像名还是原始的样子push的时候要么被拒要么全部挤到library项目里后面镜像一多就彻底分不清了。别省这个功夫每条镜像都老老实实重打tag。除了业务镜像基础镜像也要清单化。CubeStudio这类平台经常依赖ubuntu:22.04、nvidia/cuda:12.1.1-base-ubuntu22.04之类的基础镜像把这些提前拉下来能避免内网部署时发现缺基础运行环境。2.3 docker save导出与校验导出镜像用docker save不要用docker export。这两个容易搞混我专门说清楚export导出的是容器文件系统没有镜像的分层历史和元数据save导出的是完整镜像包含构建历史、层级信息和配置是唯一能保证load回来能原样运行的方式。导出时我倾向于一张镜像一个tar而不是全部打成一个包。原因也是踩过坑大包在拷贝时校验难而且如果日后只需要更新其中一个组件重新导出那一张就行了不用每次都搬几十GB的数据。批量导出可以写个循环cat images.list 192.168.209.133:8443/cubestudio/backend:3.2.1 192.168.209.133:8443/cubestudio/frontend:3.2.1 192.168.209.133:8443/cubestudio/scheduler:3.2.1while read img; do filename$(echo $img | tr / _ | tr : _).tar docker save -o ./images/$filename $img echo $img saved as $filename done images.list导出完成后做一次sha256校验生成校验文件随包带走。内网load之后可以先核对完整性别等到启动报错才回头查是哪一步坏了cd images sha256sum *.tar sha256sums.txt这一步成本很低但能让整个交付过程少很多“背锅”环节。2.4 模型文件和离线依赖同样要打包除了容器镜像CubeStudio通常会带模型权重文件。这类文件我单独放一个目录同样做sha256校验。注意模型的版本号要和镜像里的默认路径对应上不然平台起来后加载模型直接失败查起来还特别隐蔽。另外如果目标机需要离线安装Docker或者一些系统依赖docker-ce的.deb或.rpm包、docker-compose-plugin包也要在出口机上一并下载。这个细节很多人到现场才想起来结果内网装不上Docker整个部署直接卡住。我建议在出口机上提前建一个os-packages/目录把目标机操作系统对应的安装包装进去有备无患。3. 内网Harbor搭建离线交付的“货物中转站”3.1 离线安装包处理Harbor官方发布页提供harbor-offline-installer-版本号.tgz文件名的offline是关键字。这个离线包把Harbor的所有组件镜像都打好了你只需要把tgz拷进内网解压后按配置启动即可。tar -zxvf harbor-offline-installer-v2.9.0.tgz cd harbor cp harbor.yml.tmpl harbor.yml这里有一个非常关键的坑离线包里的Harbor组件镜像需要先导进本机Docker。如果内网机器上没有任何Harbor组件镜像执行install.sh的时候脚本会尝试从外网拉镜像然后直接卡死。所以解压后先把Harbor自带的那几个镜像tar文件全部docker load一遍再跑安装脚本。这是我第一次搭Harbor时踩过的坑当天浪费了两个小时。3.2 配置harbor.yml端口、数据盘、密码harbor.yml是整个Harbor安装的核心我贴一份适合内网http交付的最小配置hostname: 192.168.209.133 http: port: 8443 # 内网无证书环境把https相关注释掉 # https: # port: 443 # certificate: /your/cert.pem # private_key: /your/privkey.pem harbor_admin_password: Harbor12345 database: password: change_me_2024 data_volume: /data/harborport选8443而不是默认80原因很现实现场经常有其他应用占用80端口改成高位端口能少很多冲突。harbor_admin_password是初始管理员密码首次登录必须改。data_volume建议指向一块独立的数据盘后面镜像越存越多Harbor的数据目录增长很快系统盘很容易被写满。3.3 insecure-registries怎么配因为配置的是http而Docker默认只允许https访问仓库所以要在所有需要访问Harbor的机器上把Harbor地址加进Docker的insecure-registries配置里。修改/etc/docker/daemon.json{ insecure-registries: [192.168.209.133:8443] }改完必须重启Dockersystemctl restart docker注意重启Docker会重启本机所有容器操作前确认业务影响。在大规模集群里最好一台一台滚动操作避免所有节点同时宕。这个坑我见得太多了有人改完daemon.json忘了重启然后死活push不上去疯狂怀疑Harbor装错了。Docker的daemon配置不像nginx那样reload就能生效不重启就是不认。3.4 安装Harbor并做推送自检确认配置没问题后直接跑安装脚本./install.sh等几分钟看到类似✔ ----Harbor has been installed and started successfully.----的日志就说明装好了。浏览器访问http://192.168.209.133:8443用admin账号登进去。登录后的第一件事先在Web UI里新建一个项目cubestudio然后把出口机打包好的镜像推上去测试。Harbor建项目这一步很关键不建项目就push镜像会被拒收或者被塞到公共项目里。docker push 192.168.209.133:8443/cubestudio/backend:3.2.1第一次推镜像如果看到dial tcp之类的报错不用慌这个是内网部署最高频的网络问题后面第5节专门讲怎么定位。4. 目标机部署镜像入库、编排启动4.1 load、重推、从Harbor拉取目标机装好Docker后把离线包拷贝过去先做一次完整性校验tar -xzf images.tar.gz cd images sha256sum -c sha256sums.txt校验通过后逐张导入for tarfile in *.tar; do docker load -i $tarfile; doneload完之后有个常见疑问docker images显示的镜像名是完整的Harbor地址前缀比如192.168.209.133:8443/cubestudio/backend:3.2.1这是正常的不要把它当成异常去改。更要留意的是如果某些镜像的REPOSITORY列显示为none说明导出前镜像tag不全或者image misnamed需要回到出口机重新处理。接下来把这批镜像推到Harbor上。目标机上也要配insecure-registries然后docker push 192.168.209.133:8443/cubestudio/backend:3.2.1有的读者可能会问为什么load完了还要再push一次因为内网所有机器都以Harbor为唯一镜像源。把镜像收进Harbor之后后续扩容、多节点部署只需要从Harbor拉取不必再拿着U盘到处docker load。这也是我坚持在出口机打tag时带上Harbor地址的原因——tag不对load进内网后连push都做不了。4.2 编排文件里的镜像路径镜像进Harbor之后部署CubeStudio时把编排文件里的镜像路径统一改成Harbor地址。Docker Compose版大概长这样services: backend: image: 192.168.209.133:8443/cubestudio/backend:3.2.1 container_name: cubestudio-backend restart: always volumes: - /data/cubestudio/backend:/app/data frontend: image: 192.168.209.133:8443/cubestudio/frontend:3.2.1 container_name: cubestudio-frontend restart: always ports: - 8080:80然后在目标机上执行docker compose pull docker compose up -d如果你用的是Kubernetes流程类似deployment里的image字段改成Harbor地址同时给Harbor配置一个imagePullSecret让K8s节点有权限从Harbor拉取私有镜像kubectl create secret docker-registry harbor-secret \ --docker-server192.168.209.133:8443 \ --docker-usernameadmin \ --docker-passwordyourpasswordK8s这边还有个额外操作所有工作节点都要在/etc/containerd/config.toml里加Harbor地址的insecure_skip_verify配置或者正常签发证书。这一步经常被遗漏结果Pod一直ImagePullBackOff。4.3 数据卷与模型目录CubeStudio跑起来之后第一件事不是访问Web界面而是确认数据卷和模型目录挂载是否正常。我的经验是提前把编排文件里的volume路径都检查一遍确保数据目录落在本地磁盘最好软链到独立数据盘。模型文件我建议放在/data/cubestudio/models这类独立目录然后在编排文件里挂载进容器。这样以后升级镜像不会冲掉模型数据单独替换模型文件也方便。如果发现模型加载失败先看容器日志里的路径对不对再核对模型目录的权限是不是1000这种常规uid。5. 现场问题排查实录这些坑我基本都趟过5.1 dial tcp connection refused怎么定位这个报错是内网Harbor部署里出现频率最高的Error response from daemon: Get https://192.168.209.133:8443/v2/: dial tcp 192.168.209.133:8443: connect: connection refused很多人一看connection refused就觉得是防火墙问题其实定位顺序应该是这样的先在Harbor所在机器上测试本机端口能否访问curl http://127.0.0.1:8443/v2/。如果本机都连不上多半是Harbor容器没起来docker ps看下harbor-core、harbor-portal这些容器是否在运行。如果本机正常从执行push的机器上测试网络连通性telnet 192.168.209.133 8443。连不通就是防火墙或网络策略拦截放行这个端口。确认本机和远端都通了再看Docker是否走了错误的协议https/http这个报错里的URL是https如果你配置的是http可能需要加insecure-registries或改push命令前的配置。还有一个细节如果Harbor容器起来了但docker ps显示端口映射异常多半是重启时端口被占用导致映射失败这种情况重启Harbor就能恢复。5.2 x509证书相关的根源如果报错是x509: certificate signed by unknown authority说明Docker还在尝试用https访问而且它不信任Harbor的证书。两个处理方向一是给Harbor配上内网CA签发的正式证书把配置里的https段解开填入证书路径重新执行./install.sh --with-trivy之类的参数重建配置二是确认所有需要访问Harbor的机器都加了insecure-registries并且重启了Docker。记住只改daemon.json不重启Docker是不生效的这一条能帮你省掉大量排查时间。5.3 镜像load后显示docker images里看到REPOSITORY列是none这通常意味着镜像在导出前没有打上有效的tag。有可能是镜像同时有多个tagsave的时候只带了其中一个导出后丢了解析关系也有可能是出口机上发生过二次tag操作原始镜像名被覆盖了。处理办法是回到出口机用docker images --filter danglingtrue找出悬空镜像重新docker tag之后再save。如果你已经在内网了也没关系可以用docker history看镜像的原始配置但这种方法比较费劲我还是建议在出口机阶段就干干净净地把tag打好。5.4 ARM与x86的架构错位信创环境里最常见的架构是ARM鲲鹏、飞腾和x86海光、兆芯这在拉镜像的时候就要分清楚目标机架构。一个典型的翻车场景是在x86出口机拉了一堆amd64镜像结果拷到ARM内网机器上load没问题但启动直接报exec format error。解决方案有两个方向如果交付方提供多架构镜像在出口机拉取时用docker pull --platform linux/arm64指定架构如果不支持就要找一台与目标机相同架构的机器重新拉取和导出。这个检查请在出口机阶段完成到内网才发现就非常被动了。用docker image inspect 镜像名 | grep Architecture能快速确认。5.5 空间告急与版本升级镜像连续load、解压、再push中转过程会占用大量临时空间Harbor的数据盘尤其涨得快。建议给Harbor单独挂数据盘定期在Web UI的“项目-镜像仓库”里清理不再使用的tag再到“系统管理-垃圾回收”里清理悬空层。垃圾回收会重建仓库存储目录耗时较长建议在维护窗口执行。版本升级也是离线环境经常遇到的。Harbor升级需要拿到对应版本的离线包官方支持从特定低版本直接升到高版本但中间不能跳过太多版本升级前务必备份Harbor数据库和data_volume。备份Harbor数据库就是备份PostgreSQL数据目录直接把data_volume里的database目录打包拷走即可。这个备份在离线环境里尤其重要因为没有外网出了问题连临时下载新版本的机会都没有。我做完这一轮之后最大的体会是离线部署最难的不是技术本身而是你在现场没有“试错”的机会——外网拉不到镜像内网报错查不到文档所以前期的镜像清单、tag规范、离线包完整性校验才真正决定交付成败。我的建议是在出口机阶段就把images.list、sha256校验文件、harbor.yml配置全部整理好拷进内网之后按步骤来不要边部署边找原因。把Harbor搭好、镜像推进内网之后后续的部署就和在线环境几乎没有差别了。最后再分享一个小技巧每次部署完把出口机上整理好的images.list、编排文件、Harbor配置都备份到内网的一台管理机上形成“交付基线”。以后不管是扩容还是回滚都有据可查不至于两三周之后自己都想不起来当时用的哪个镜像版本。这是一个很容易被忽略但长期收益很高的小动作。
阅读完成 · 觉得有帮助?
咨询建站