ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

CubeStudio信创环境离线部署实战:镜像导出到Harbor内网私有化

CubeStudio信创环境离线部署实战:镜像导出到Harbor内网私有化 CubeStudio 要在完全无外网的内网里做私有化部署我一开始也以为只是把镜像包拷进去就行真上手才发现这是一条特别长的链路。信创环境、离线部署、Harbor 镜像仓库、出口机代理、镜像导出导入每个环节都藏着不少坑。最近我刚把整套流程走通从联网机器导镜像开始再用一台出口机摆渡进内网推到 Harbor最后在 Windows Server 2022 上离线拉起服务。这篇完整记录一下我的实操过程和踩坑经验如果你也卡在“物理隔离网内如何跑容器化服务”这个问题上可以直接参考。1. 整个场景的核心拆解与方案选型1.1 完全无外网环境到底“无”到什么程度所谓完全无外网通常指物理隔离的内网也就是机器不接入互联网没有 DNS 外网解析也没有代理通道。这种环境下所有依赖都得提前准备好比如 CubeStudio 的容器镜像、基础中间件、安装脚本、离线包缺一样都不行。很多人以为只需要把镜像 tar 包带进去再 docker load 就行实际跑起来才发现还有仓库、证书、环境变量、内核特性一堆问题。我在这次的客户现场遇到的环境就是彻底断网的只有一台“出口机”可以插移动硬盘之外没有任何网络通路。这意味着不只是镜像拉不了连apt install、pip install、下载 WSL 内核包这种原本顺手的事情全都变成卡点。所以第一步必须先盘清楚哪些东西是需要从外部带进来的哪些是目标环境自带的。这里的关键不只是“少拉一次镜像”而是所有软件的安装来源都得提前确定。拿 Windows Server 2022 举例如果你打算用 WSL2 跑容器单是 WSL 内核更新包、Ubuntu 根文件系统、docker 离线安装包这三样少了任何一个后面都走不下去。1.2 为什么最终选了“镜像导出 Harbor”这条路线其实一开始的直觉方案很简单直接把 CubeStudio 的镜像 docker save 成 tar拷进内网后 docker load然后用 docker run 启动。听起来没问题试了发现一旦涉及多台目标机、需要更新版本、或者一个服务依赖好几个镜像的时候这种拷贝方式就会变得很乱。镜像文件散落在各个目录没有版本管理没法统一控制谁在哪个节点上跑了哪个版本。再加上信创环境里不同的机器架构、操作系统经常不完全一样有时候某台机器需要重新部署你根本不知道之前拷贝的镜像能不能复用。所以后来我把方案改成了“镜像导出 Harbor 私有仓库”在有外网的工作机上把 CubeStudio 及其依赖镜像全部导出形成离线镜像包通过出口机摆渡进内网在目标内网部署一台 Harbor 作为统一镜像仓库各部署节点只需配置好insecure-registries或证书就能像正常环境一样 pull/push 镜像。这个方案的好处是部署节点不需要依赖移动硬盘来回插也不需要在每台机器上手动 load 镜像。Harbor 承担了“内网 Docker Hub”的角色服务一旦启动后续扩容就简单了。而且 Harbor 自带项目隔离、镜像同步、审计日志在交付信创项目时这套东西也有利于做版本追溯。1.3 信创环境下的隐性差异架构、内核与容器运行时信创环境的坑很多时候不在“离线”而在“差异”。这里说的差异包括 CPU 架构、操作系统发行版、内核版本、默认容器运行时。我这次的目标环境就是国产 CPU 的机器既有 x86_64 也有 arm64这就意味着镜像不能只导一份 amd64 的如果 CubeStudio 镜像没有多架构支持就得按目标机的实际架构分别导出。另一个需要注意的点是容器运行时。有些国产化系统带的是 containerd有些是旧版 docker还有一些内置了 podman。如果目标机已经装了 containerd而你的部署习惯是docker run那么要么额外安装 docker要么把命令改成nerdctl或crictl。在方案选型阶段就要确认好避免到部署现场才发现没有 docker 命令白白浪费时间。还有内核特性比如 WSL2 依赖 Windows 的“虚拟机平台”某些精简版 Windows Server 2022 可能默认没开。这些在原方案里都不容易提前暴露所以我建议在开工前先用一张基础环境清单电话确认每一台机器的系统版本、CPU 架构、已安装容器运行时、磁盘空间。宁可多问几句不要等到搬运完镜像才发现运行不了。2. 第一步在联网机器上准备离线镜像包2.1 确认 CubeStudio 的镜像列表和版本准备工作第一步是把 CubeStudio 部署清单里的所有镜像列表找全。这个列表通常在项目的安装文档或者编排文件里能看到比如 docker-compose.yml 里的image字段、Helm charts 里的 values或者部署脚本里写死的一串镜像名。建议你拿这些来源对照实际镜像仓库把镜像仓库地址、镜像名、tag 全部列成表格。不要想当然只导出主服务的镜像。CubeStudio 这类平台通常附带数据库、消息队列、对象存储、监控组件等甚至有些辅助服务是部署时临时拉取的。光看主服务名并不够最好在联网环境里先把整套编排拉起来跑一遍然后用docker ps -a配合docker inspect看实际运行的镜像把所有运行过的镜像都记录下来。我习惯把镜像清单保存成文件每一行是一对源镜像地址 本地导出名。这样之后导出、导入、重新打 tag 的时候都有据可依不会漏掉。版本号一定要锁死不要用 latest离线环境里没法再拉新的一旦 latest 在导出后发生变化后面就会踩坑。2.2 docker save 和 skopeo copy哪个更靠谱常见的镜像导出方式有两种docker save和skopeo copy。两种我都用过说说我的感受。docker save属于最直觉的做法先把镜像拉下来然后docker save -o 文件名.tar 镜像名:tag。导出的 tar 包用docker load可以原样还原。这个方式的优点是对 docker 用户零学习成本缺点也很明显依赖本机 docker daemon如果你需要导出 containerd 命名空间里的镜像或者本机启动了多个 docker 上下文就容易混乱。skopeo copy则可以直接将镜像从远程仓库复制到本地文件系统格式可以指定为docker-archive、oci-layout或者oci-archive。它不依赖 docker daemon更像一个“镜像搬运工”。因为是无守护进程运行在自动化脚本和信创环境的批量离线准备中更顺手。这次我用的是 skopeo主要原因是我需要同时导出多个架构的镜像并且想要直接拉取远程仓库不污染本地 docker 缓存。以 OCI 格式为例导出命令大致是skopeo copy --override-os linux --override-arch arm64 \ docker://源仓库地址/cubestudio/server:2.4.0 \ oci-archive:cubestudio-server-arm64.tar:2.4.0不过对于大多数只需要 docker load 的场景docker save也是完全够用的。我的建议是如果是一次性给人拷镜像用 docker save 简单如果你想把这件事脚本化、批量导出多个镜像并且后续要对接 Harbor 的同步那 skopeo 更干净。2.3 离线包整理与完整性校验镜像导出之后最忌讳的就是随便扔进一个目录等拿到内网才发现某个 tar 包损坏。我在一次交付中就碰到过 tar 包只有几百兆看着完整推送到 Harbor 中途报错最后回查是因为移动硬盘文件系统问题某个分卷其实没写全。所以现在我的习惯是导出完立刻做两件事对每个 tar 包计算 sha256生成一个 CHECKSUMS 文件写一个 manifest 清单记录源镜像、导出格式、架构、版本、文件大小。在进入内网之后先跑一遍sha256sum -c CHECKSUMS再做后续操作这就把传输损坏问题提前拦住。清单用 CSV 或直接 Markdown 表格都行关键是要让人一眼知道这个包是干嘛的是 amd64 还是 arm64对应 CubeStudio 的哪个组件。如果镜像特别多建议打成一个大压缩包或者分成几个分卷zip/tar 多卷并给每个分卷独立校验。传输时最好用 ext4 或 NTFS 格式的硬盘有些老式移动硬盘是 FAT32超过 4G 的文件会被截断这听起来很基础但实际现场总有人踩到。3. 第二步在内网搭建 Harbor 私有镜像仓库3.1 Harbor 离线安装包要准备哪些东西Harbor 官方提供了 offline installer一个 tgz 包我记得名字类似harbor-offline-installer-v2.11.0.tgz。这个 offline 包不是“免安装版”它里面打包了 Harbor 自己的镜像和一个 install 脚本但前提是安装机已经具备 docker 环境和 docker compose 插件。既然是完全离线环境那么安装机必须具备docker CLI、docker daemon 可运行docker compose 插件docker compose version能跑通tar、openssl、python3、rsync 等基础命令磁盘空间Harbor 运行本身占几个 G建议至少留 50G。如果目标机器上没有 docker最好在“联网准备阶段”把 docker 的离线安装包和 compose 插件的二进制也一起拷进去。我这次使用的安装机是 Ubuntu Server系统版本比较干净但还是提前确认了/etc/os-release的发行版和版本避免包管理器依赖不一致。另外还要记得Harbor 自身也依赖镜像仓库的能力。offline installer 里的 harbor 镜像安装时会被自动 load 到本地 docker所以不要误删安装包里的目录结构。3.2 在 Ubuntu 上部署 Harbor 的完整步骤部署步骤并不复杂但每一步都有容易忽略的细节。先说总体流程解压 offline installer、准备 harbor.yml、执行 install.sh。以我实际操作的示例为例把harbor-offline-installer-v2.11.0.tgz拷到/opt/harbor解压。进入目录复制harbor.yml.tmpl为harbor.yml。修改 hostname、端口、harbor_admin_password还有仓库存储路径。由于内网环境没有有效公共证书我直接禁用了 https采用 http 模式并在后续把 Harbor 地址加入所有客户端 docker 的insecure-registries。执行sudo ./install.sh。Harbor 默认配置会启动多个容器包括 registry、redis、postgresql、portal 等。安装脚本会先做环境检查比如 docker 是否运行、docker compose 版本是否满足要求。如果检查不通过会在终端打印具体错误比较常见的是 docker compose 命令找不到或者 /etc/docker/daemon.json 里的 storage-driver 与文件系统不匹配。我特意把 Harbor 的 hostname 配置成内网 IP 而不是主机名比如hostname: 192.168.209.133。因为客户端机器不一定有内网 DNS用 IP 最简单。如果后续客户端要配证书也是以这个 IP 为准否则就算你配了 HTTPS 也一样报证书不匹配。3.3 仓库规划项目、用户、机器人账号该怎么配Harbor 装好之后第一步不是急着推镜像而是把项目结构和账号体系规划好。连端口都不改就裸奔后面会很难受。我在内网 Harbor 里建了三个项目library放公共基础镜像比如 postgres、redis、nginx这些是所有服务都可能用的cubestudio放 CubeStudio 服务端和相关组件镜像infra放运维工具镜像比如 busybox、alpine/curl方便各节点调试。为什么要分项目因为 Harbor 的项目可以分别设置“公开”还是“私有”。基础镜像项目设为公开后客户端 pull 不需要认证带业务数据的项目设为私有避免不必要的访问。信创交付现场环境比较复杂分项目后即便不同团队共用一套 Harbor权限也容易管控。账号方面不要在业务节点上用 admin 账号去拉镜像安全审计时会很难看。Harbor 提供了机器人账号创建后可以指定只对某个项目有 pull 权限。部署节点就用机器人账号登录这样就算账号泄漏也只有只读权限。如果只需要手动导入镜像用管理员账号操作完再删除即可。这些规划虽然看起来和“部署”没直接关系但实际项目交付中客户会问Harbor 里的镜像谁在拉、谁在传同一个项目里好几个版本怎么标签。提前做好项目划分后面答疑能省很多时间。4. 第三步出口机代理与镜像摆渡4.1 什么是出口机代理为什么它是唯一可行窗口这里的“出口机”我指的是在物理隔离网络里唯一允许插入外部存储介质、或者与外部网络有限的边界进行数据交换的一台机器。出于合规和管理方便内网其他机器都不能直接接触外来数据所有离线包都必须经过出口机中转。所以出口机其实承担的是“文件摆渡代理”的角色不是网络代理。这个环节最关键的是流程纪律。出口机不能乱装软件最好只用来存放、校验、传输文件。我之前遇到过出口机上被人装了不明软件、系统自带一堆服务的情况后续排查起来很麻烦。建议在项目开始前先找客户确认出口机的访问方式是用 U 盘还是用内网共享还是用受控的 FTP。不同方式的效率和坑都不一样。如果条件允许在出口机上只开放一个固定目录比如/data/offline-transfer所有要带进内网的文件统一放这里。进入内网之后也要有专人负责把这里的文件再分发到 Harbor 服务器或部署机上避免文件被误删或覆盖。4.2 从外网工作机到出口机再到 Harbor 的搬运流程我的搬运流程分成三段外网工作机把离线镜像包和依赖软件压缩成一个目录计算 sha256。出口机通过移动硬盘或合规通道接收校验 sha256然后通过内网 scp 拷贝到 Harbor 服务器。Harbor 服务器解压 tar把镜像 load 到本地 docker然后重新打 tagpush 到 Harbor。以 docker save 出来的 tar 包为例在 Harbor 服务器上的操作大致是# 从出口机接收文件 scp 用户名出口机IP:/data/offline-transfer/cubestudio-images/ /data/harbor-transfer/ # 解压并校验 cd /data/harbor-transfer sha256sum -c CHECKSUMS # 目录结构可能按项目分好例如 # cubestudio/cubestudio-server-2.4.0.tar # library/postgres-15.2.tar # 逐个 load docker load -i cubestudio/cubestudio-server-2.4.0.tar docker load -i library/postgres-15.2.tar # 重新打 tag 并 push docker tag 镜像名:2.4.0 192.168.209.133/cubestudio/cubestudio-server:2.4.0 docker login 192.168.209.133 docker push 192.168.209.133/cubestudio/cubestudio-server:2.4.0第一次搬运时我建议先拿一个小镜像走一遍完整流程确认 Harbor 的登录、tag、push 没问题再开始批量导入。批量导入的时候也别省事直接用for循环脚本把 tar 包列表处理但脚本里一定要加set -e任何一个 load 失败都停下来避免push了错的镜像。4.3 推送到 Harbor 时最容易翻车的地方docker push到 Harbor 最常见的错误就是类似这样的日志harbor 推送失败 get https://192.168.209.133/v2/: dial tcp 192.168.209.133: connect: connection refused看到这个报错先不要慌它通常不是 Harbor 服务真的挂了而是客户端访问的地址或协议不对。最典型的原因是客户端 docker 默认用了 HTTPS而 Harbor 配的是 HTTP地址里没有写端口如果 Harbor 的端口不是 443docker 会默认连 443然后被拒绝Harbor 的服务容器还没完全启动客户端就在这个空档推镜像防火墙或安全组没放行 Harbor 端口。解决的第一步永远是确认“客户端和 Harbor 之间网络通不通”。在客户机上直接用curl -v http://192.168.209.133:8080/v2/试一下看看能不能返回 401 或 200。如果连不通用 curl 都不行就是网络层的问题不要一直去调 docker。如果可以通就在/etc/docker/daemon.json里加入 insecure-registries 并重启 docker{ insecure-registries: [192.168.209.133:8080] }注意一旦修改 daemon.jsondocker 会自动重启容器Harbor 所在机器如果也是 docker daemon改了配置会影响正在运行的容器建议不要在 Harbor 服务器上乱调或者在维护窗口操作。5. 第四步在目标机离线部署 CubeStudio5.1 Windows Server 2022 离线启用 WSL 与 Containers这次目标环境里有几台 Windows Server 2022客户要求在这上面跑容器。这里涉及 Windows 功能开关和离线包的问题。Windows Server 的容器支持分 Windows 容器和 Linux 容器如果 CubeStudio 的服务镜像基本都是 Linux 的最省事的方式是启用 WSL2再在 WSL2 里安装 docker。离线环境下不能靠wsl --install自动下载需要把所有组件提前准备好。我准备的清单大概是Windows 功能Microsoft-Windows-Subsystem-Linux、VirtualMachinePlatform、ContainersWSL2 内核更新包一个.msi文件一个导出的 WSL 发行版 tar比如 Ubuntu 22.04 的 rootfsDocker 的离线安装包适用于 Ubuntu 的 docker-ce 二进制包。在线下服务器上用管理员 PowerShell 执行dism /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart dism /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart重启后需要安装 WSL2 内核更新包然后通过wsl --import导入离线 Linux 发行版。这些组件在联网的机器上都是一条命令的事离线环境就麻烦很多每一项都要提前验证版本。特别注意 Windows Server 2022 默认不带图形界面WSL 安装过程用命令行为主别等窗口提示很多步骤是不会弹消息的。5.2 配置 Docker 使用内网 Harbor 仓库WSL2 里的 Ubuntu 启动之后安装 docker。离线安装 docker-ce 的时候如果你已经提前把.deb包和依赖全部列好直接dpkg -i *.deb就行。装好之后最好先确认docker version能过再改 daemon.json。在 WSL2 的 Ubuntu 里编辑/etc/docker/daemon.json加上{ insecure-registries: [192.168.209.133:8080] }然后systemctl restart docker或者手动启动 docker 守护进程。Windows Server 上跑 WSL2 后的 dockerd 启动经常有问题因为 systemd 在 WSL 里默认可能没启用你需要手动执行dockerd或者配置好后台服务。我这次更稳定的是直接用service docker start然后再docker info看输出。配置完成后先登录一次 Harbor 测试拉取docker login 192.168.209.133:8080 docker pull 192.168.209.133/cubestudio/cubestudio-server:2.4.0如果拉取可以成功说明从 Windows 的 WSL2 网络到 Harbor 的链路是通的。这里有个经验WSL2 的 NAT 网络在某些 Windows Server 配置下可能会异常表现为从 WSL2 内能 ping 通 Windows 侧 IP但访问其他内网不通。遇到这种情况可以检查 Windows 上的wsl --network设置必要时用镜像网络模式或把 Windows 作为网桥。5.3 拉取镜像并启动 CubeStudio 服务镜像拉取成功后启动 CubeStudio 前最好先按官方部署模板准备好目录。比如把配置文件、数据目录、日志目录都挂在宿主机这样容器升级也好处理。使用 docker compose 编排的话离线环境下需要提前把镜像 tag 改成 Harbor 地址。一个简化的启动流程创建目录/opt/cubestudio把 docker-compose.yml 和.env放进去。确认镜像引用均已改成本地 Harbor 地址或用.env里的变量统一指定。docker compose pull会从内网 Harbor 拉取。docker compose up -d。第一次启动时一定要看日志不要只看容器状态。CubeStudio 如果有多个服务服务间要等依赖服务起来才能注册成功。如果中途有容器退出docker compose logs是最直接的排查入口。另外端口冲突是常见问题比如 5432 被本机 postgres 占了这时候.env里映射端口就得改掉。6. 常见问题与排查实录6.1 Harbor 推送失败get https://192.168.209.133/v2/ 连接被拒这是我在内网推送镜像时遇到次数最多的错误。日志片段大致是Get https://192.168.209.133/v2/: dial tcp 192.168.209.133: i/o timeout或者本机直接 connection refused。先说我的排查顺序。首先确认 Harbor 容器状态在 Harbor 服务器上执行docker ps看 registry 容器是否在运行。因为 Harbor 启动时如果 SSL 配置有误、端口被占用、或者存储目录没权限某个核心容器可能会反复崩溃但是安装脚本最后显示成功容易漏掉。其次看端口。我这次是把 Harbor 的 HTTP 端口配置成 8080不是默认的 80。内网客户端如果没有在地址里写:8080docker 默认会访问 443出现 https 报错。根本原因就是地址少了端口并不是 Harbor 没起来。这个坑非常隐蔽因为你看到报错里有 IP就会以为是 Harbor 故障。最后看证书。如果 Harbor 使用的是自签 HTTPS 证书客户端需要把证书放到/etc/docker/certs.d/192.168.209.133:8443/ca.crt下或者在 daemon.json 里把这个地址加入insecure-registries。不加的话docker 会拒绝跟这个仓库通信报错也会是 x509 证书错误。所以看到 https 和 dial 相关字样时先按这个顺序排查不要上来就重装 Harbor。6.2 WSL 离线安装失败和 containers 功能无法启用Windows Server 2022 上 WSL 离线安装最常见的坑是安装完成以后执行wsl --list --verbose显示“未安装”。这一般是因为功能开关状态还没生效。你可以在 PowerShell 里重新检查Get-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux Get-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform如果状态是 Disabled说明之前 dism 启用不完整或者需要有两次重启。我实际遇到的情况是第一次重启后子系统功能显示 Enabled但是 WSL 命令仍然不存在原因是路径%SystemRoot%\System32\wsl.exe还没刷新。执行where wsl.exe看系统目录里有没有如果没有就得重新启动到“Windows 功能已配置完成”的状态。假如你已经导入了 Ubuntu rootfs但wsl --import一直报错“找不到指定的文件”大概率是 tar 包格式不对。需要用wsl --export导出的 tar或者手动将 tar 转成兼容格式。还有一点WSL2 要求启用“虚拟机平台”之后才能跑发行版如果这个功能没启用导入后启动会直接报内核错误。此时必须重启机器并安装 WSL2 内核更新包。如果客户要求 Windows 容器模式那就需要启用Containers功能。这个功能和 WSL 不冲突但 Docker 引擎要选对版本。Windows 容器需要的是 docker 的 Windows 镜像而 CubeStudio 大概率是 Linux 容器混用会让你在 docker info 里看到两套环境。建议先明确目标到底是走 WSL2 跑 Linux 容器还是只想跑 Windows 容器。6.3 镜像导入慢、磁盘撑爆、sha256 校验不一致离线镜像搬运的另一个麻烦是大文件。比如一个包含完整 CubeStudio 全家桶的镜像包可能有 20 到 30G拷进内网后导入到 Harbor 服务器往往也是这几十分钟的事。期间如果磁盘不够docker load 会报层文件写入失败而且不会明确提示“空间不足”只说某个 layer 写入失败。所以我在搬运前会在 Harbor 服务器上检查/var/lib/docker所在磁盘的剩余空间。判断 sha256 校验不一致时先不要急着重新拷贝有可能是移动硬盘文件系统导致的字节损坏。可以先看文件的大小和修改时间是不是与源一致。如果大小一致但 sha256 不一致再考虑用二进制差分工具对比看看是哪一块出了问题。很多时候是拷贝过程中内存缓存没刷完拔硬盘太快导致文件不完整重新拷一次就好。镜像导入到 Harbor 里以后占用空间是双倍的Harbor 服务器上的本地 docker 缓存一份Harbor 的 registry 存储目录里又存一份。所以如果你用 docker load 导入了 30G 镜像Harbor 实际可能占 60G 以上。如果空间紧张可以在推完镜像后用docker image prune清理本地 docker 的缓存但要注意别把 Harbor 运行所需的镜像清了。6.4 离线部署全程避坑速查表症状可能原因解决方向docker push 报 https 连接拒绝Harbor 开了 HTTP客户端默认访问 HTTPSdaemon.json 加 insecure-registriesdocker push 报 i/o timeout防火墙/端口未放行或未写端口检查网络连通性确认 Harbor 端口Harbor 容器反复重启证书配置错误、端口冲突、存储目录权限查看 docker logs 定位容器退出原因wsl --import启动失败虚拟机平台未启用、内核包未装启用 VirtualMachinePlatform安装 WSL2 内核docker load 中途报错磁盘空间不足、tar 包损坏检查 inode/磁盘空间校验 sha256镜像推到 Harbor 后客户端拉不到项目设为私有或客户端未登录建立机器人账号并 docker loginCubeStudio 启动后端口不通端口映射被占用或防火墙没开检查 compose 端口映射和安全组规则这张表是我这次全程踩坑后整理的适合在你部署卡壳时先对照一遍。最后分享一点个人经验离线部署这事最怕的不是技术难而是“觉得简单”。每一条看起来顺理成章的路径都可能被某一个离线细节卡住。我在这次交付中最大的收获是坚持把每一步都记录下来包括版本、校验值、命令输出。后面客户要补环境、要扩容时这套记录直接变成了可复用的操作手册。如果你也正在搞 CubeStudio 的信创离线部署建议你也像我一样先在联网环境模拟一遍完整流程把所有需要带进内网的东西列成清单再正式进场。能提前一小时验证的绝不拖到现场再补救。
返回列表