GPUStack 离线(Air-Gapped)环境部署完整指南:镜像同步、导入与安装

原创2026-10-03 18:53:121,628 阅读
文章标签:后端人工智能模型推理服务集群管理可观测性

GPUStack 离线(Air-Gapped)环境部署完整指南:镜像同步、导入与安装

GPUStack 支持在完全无互联网访问的离线(air-gapped)环境中安装与运行。本指南基于 Air-Gapped Installation 展开,系统讲解镜像获取(copy-images / list-images / save-images / load-images 四条命令)、内网镜像仓库搭建、以及 GPUStack 服务器/工作节点的离线启动配置,并结合仓库源码说明底层实现原理。读完本文,你将掌握一套从有网机器到隔离网络环境的完整镜像搬运与部署流程。

总体思路:离线部署的三个阶段

GPUStack 由服务器(server)与工作节点(worker)构成,运行时会拉取多种容器镜像:GPUStack 自身镜像、推理后端(runner)镜像(如 vLLM、SGLang、MindIE、VoxBox)、Higress 网关镜像、基准测试(benchmark-runner)镜像,以及 CSI 存储驱动、SSH 服务器等系统组件镜像。离线部署的核心就是把这些镜像先"搬"进内网,再让 GPUStack 从内网拉取。

整个流程可拆分为三个阶段:

  1. 准备镜像清单:在任意一台能访问互联网的机器上,先确定当前版本需要哪些镜像(list-images)。
  2. 同步镜像:要么直接通过 copy-images 把镜像从公网仓库推送到内网仓库;要么用 save-images 在联网机器上打包下载,再通过 U 盘、内部文件传输等方式拷入离线环境,最后用 load-images 导入本地容器运行时。
  3. 安装与配置:以内部仓库地址启动 GPUStack,并通过环境变量处理仓库认证、非默认命名空间等场景。

GPUStack 运行后,还会在 /help/ 路径下直接托管自身的离线文档,满足隔离网络内的查阅需求。

前置条件

GPU 驱动

确保系统已安装与硬件匹配的 GPU 驱动。不同加速器的驱动与工具链要求不同,详细兼容性请参考 Installation Requirements:

  • NVIDIA GPU:驱动需支持 CUDA 12.8 及以上,并安装 NVIDIA Container Toolkit。
  • AMD GPU:驱动需支持 ROCm 7.0 及以上,并安装 AMD Container Runtime。
  • Ascend NPU:安装 Ascend NPU 驱动与 Ascend Docker Runtime,支持 910C / 910B 系列与 310P3。
  • Hygon DCU、MetaX GPU、MThreads GPU、Iluvatar GPU、Cambricon MLU、T-Head PPU:均需对应的驱动与工具包(如 DTK、MACA SDK 等),部分处于实验性支持状态。

可用 nvidia-smi、amd-smi static、npu-smi info、hy-smi、mx-smi、cnmon、ppu-smi 等命令验证驱动是否就绪。

容器运行环境

离线环境必须安装 Docker。如果系统支持容器工具包(如 NVIDIA Container Toolkit、AMD ROCm Container Toolkit 等),请按需安装并配置,否则 GPUStack 无法在容器内访问加速设备。可通过 sudo docker info 2>/dev/null | grep -q "nvidia" 之类的方式验证工具包是否生效。

容器镜像

GPUStack 的组件镜像与推理后端镜像发布在 Docker Hub 和 Quay.io 上。离线环境无法直接访问这两个源,因此需要借助 GPUStack 提供的镜像管理命令完成搬运。

离线获取镜像的两种工作流

GPUStack 提供四条镜像管理命令,对应两种典型的离线工作流:

命令 用途 适用场景
gpustack copy-images 把一个仓库(registry)中的镜像同步到另一个仓库 内网已有可用镜像仓库,可直连
gpustack list-images 列出当前版本所需的全部镜像清单 确认需要搬运哪些镜像
gpustack save-images 从公网下载镜像并保存为本地 OCI/Docker Archive 包 目标环境完全隔离、无法直连内网仓库
gpustack load-images 将本地镜像包导入容器镜像存储 配合 save-images 使用

四条命令的实现位于 gpustack/cmd/images.py(参数解析与子命令注册)以及 gpustack_runtime.cmds 包(CopyImagesSubCommand、ListImagesSubCommand、SaveImagesSubCommand、LoadImagesSubCommand),底层镜像搬运能力由 containers/skopeo、CLI Reference - save-images 和 CLI Reference - load-images。

从源码可以看到,GPUStack 的镜像清单远不止推理后端:除了 gpustack/runner 系列镜像,还包括 gpustack/benchmark-runner、gpustack/higress-plugins、gpustack/mirrored-higress-*(网关组件)、gpustack/gpustack-operator、gpustack/ssh-server、gpustack/mirrored-kueue、gpustack/mirrored-node-feature-discovery、以及一组 gpustack/mirrored-csi-* 存储驱动镜像。插件(Plugin)还可以通过 extra_image_list() 追加额外的镜像(见 images.py)。这也是为什么离线部署时必须使用官方命令而不是手工拷贝个别镜像——只有它们能保证清单完整。

工作流一:直接同步到内网仓库(copy-images)

如果你的离线环境可以通过内部网络访问一个自建的容器镜像仓库(如 Harbor、Nexus 等),就在有网机器上把公网镜像"搬运"过去。

在联网机器上执行以下命令(以 Docker 方式运行,--entrypoint "" 是为了绕过镜像默认的 gpustack start 入口,直接执行子命令):

sudo docker run --rm -it --entrypoint "" gpustack/gpustack \
    gpustack copy-images \
    --destination <your_internal_registry> \
    --destination-username <your_username> \
    --destination-password <your_password>

默认从 docker.io(Docker Hub)拉取镜像。如果 Docker Hub 拉取失败或速度很慢,可以将源切换到 quay.io 镜像源,只需增加 --source quay.io 参数:

sudo docker run --rm -it --entrypoint "" gpustack/gpustack \
    gpustack copy-images \
    --source quay.io \
    --destination <your_internal_registry> \
    --destination-username <your_username> \
    --destination-password <your_password>

注意:上述命令默认使用 latest 版本镜像。如需针对特定版本,请使用完整镜像标签,例如 gpustack/gpustack:vx.y.z,使命令内置的镜像清单与该版本一致。

copy-images 支持丰富的过滤参数,可在同步时只搬运需要的子集(完整参数表见 copy-images CLI 参考):

参数 默认值 说明
--backend {cann,corex,cuda,dtk,hggc,maca,musa,neuware,rocm} 空 按推理后端名过滤 gpustack/runner 镜像
--backend-version / --backend-version-prefix / --backend-variant 空 按后端版本/版本前缀/变体过滤
--service {voxbox,vllm,mindie,sglang} 空 按服务名过滤 runner 镜像
--service-version / --service-version-prefix 空 按服务版本/版本前缀过滤
--repository 空 按仓库名过滤
--platform {linux/amd64,linux/arm64} 空 按平台过滤
--deprecated — 包含已弃用镜像
--max-workers 1 并发复制的工作线程数
--max-retries 1 单个镜像复制的最大重试次数
--source / --src docker.io 源仓库
--source-namespace / --src-namespace 空 源仓库命名空间
--source-username / --source-password 环境变量 SOURCE_USERNAME / SOURCE_PASSWORD 源仓库认证
--destination / --dest docker.io(环境变量 GPUSTACK_SYSTEM_DEFAULT_CONTAINER_REGISTRY) 目标仓库
--destination-namespace / --dest-namespace 环境变量 GPUSTACK_RUNTIME_DEPLOY_DEFAULT_CONTAINER_NAMESPACE 目标仓库命名空间
--destination-username / --destination-password 环境变量 DESTINATION_USERNAME / DESTINATION_PASSWORD 目标仓库认证

工作流二:打包下载 + 离线导入(save-images + load-images)

当离线环境完全无法访问内网仓库(例如物理隔离的网络)时,采用"联网机器打包 → 物理转运 → 离线导入"的方式。

第一步:在联网机器上下载并打包镜像

使用 save-images 命令,将按过滤条件筛选出的镜像下载为本地归档文件:

sudo docker run --rm -it --entrypoint "" \
 -v ./gpustack-air-gapped:/gpustack-air-gapped \
 --workdir /gpustack-air-gapped \
 gpustack/gpustack \
 gpustack save-images \
 --platform linux/amd64 \
 --backend cuda \
 --backend-version 12.9 \
 --service vllm \
 --service-version 0.15.1 \
 --max-workers 3 \
 --max-retries 3

该命令会依据指定的平台、后端与服务配置下载全部所需镜像,并以本地包的形式保存在 gpustack-air-gapped 目录下。示例中展示了如何通过过滤参数只下载部分镜像子集。

save-images 的过滤参数与 copy-images 基本一致,另有归档格式参数(完整参数表见 save-images CLI 参考):

参数 默认值 说明
--archive-format {oci,docker} oci 归档格式。oci 为 OCI Layout,docker 为 Docker Archive(docker save 兼容)
output 当前工作目录 镜像包输出目录

注意:同样默认使用 latest 版本镜像,指定版本请使用完整标签 gpustack/gpustack:vx.y.z。

下载完成后,用你方便的方式(如 U 盘或内部文件传输)把生成的 gpustack-air-gapped 目录整体拷贝到离线环境。

第二步:在离线机器上导入镜像

在目标机器上,将镜像包导入本地容器运行时:

sudo docker run --rm -it --entrypoint "" \
    --volume /var/run/docker.sock:/var/run/docker.sock \
    --volume ./gpustack-air-gapped:/gpustack-air-gapped \
    --workdir /gpustack-air-gapped \
    gpustack/gpustack \
    gpustack load-images \
    --platform linux/amd64 \
    --max-workers 3 \
    --max-retries 3 \
    /gpustack-air-gapped

命令把指定目录中的所有镜像包导入本地 Docker daemon,GPUStack 即可直接使用。这里必须挂载宿主机的 /var/run/docker.sock,因为 load-images 需要在宿主机 Docker 存储中写入镜像;同时通过挂载与 --workdir 让容器能访问镜像包目录。

load-images 除过滤与并发参数外,还支持以下配置(完整参数表见 load-images CLI 参考):

参数 默认值 说明
--destination / --dest docker.io(环境变量 GPUSTACK_SYSTEM_DEFAULT_CONTAINER_REGISTRY) 覆盖目标仓库(可配合 --archive-format 将镜像包重打到指定仓库)
--destination-namespace / --dest-namespace 环境变量 GPUSTACK_RUNTIME_DEPLOY_DEFAULT_CONTAINER_NAMESPACE 覆盖目标命名空间
--archive-format {oci,docker} oci 与保存时对应的归档格式
--storage {docker,podman} docker 导入到的容器镜像存储,支持 Docker 与 Podman
input 当前工作目录 镜像包所在目录

注意:导入命令同样默认使用 latest 版本,指定版本请使用完整标签。

补充:查看镜像清单(list-images)

如果无法直接访问内网仓库,可以先拉取 gpustack/gpustack 镜像,再用 list-images 查看当前版本需要哪些镜像:

sudo docker run --rm -it --entrypoint "" \
    gpustack/gpustack \
    gpustack list-images

输出清单涵盖所有受支持的加速器、推理后端、版本与架构。若只需要子集,可用与 copy-images 相同的过滤参数(--backend、--service、--platform、--repository 等)缩小范围;--format {text,json} 控制输出格式,json 便于脚本化处理(见 list-images CLI 参考)。

另外,Image Selector 提供了纯浏览器端的镜像选择工具,其数据随文档打包发布、完全离线可用,适合人工挑选要下载的镜像;但它的版本列表只覆盖随包发布时的版本,需要自动化同步或更新版本时仍应使用上述 CLI 命令。

离线安装 GPUStack

内网镜像仓库准备好之后,即可在离线环境安装 GPUStack。核心思路是用内部仓库地址替换默认的 gpustack/gpustack 镜像,并通过 --system-default-container-registry 指定 GPUStack 拉取系统镜像与推理镜像的默认仓库。

基本安装命令

 sudo docker run -d --name gpustack \
     --restart unless-stopped \
     -p 80:80 \
     --volume gpustack-data:/var/lib/gpustack \
-    gpustack/gpustack
+    <your_internal_registry>/gpustack/gpustack \
+    --system-default-container-registry <your_internal_registry>

关键点说明:

  • 镜像本身:使用 <your_internal_registry>/gpustack/gpustack,即内网仓库中的 GPUStack 镜像。
  • --system-default-container-registry:告诉 GPUStack 从哪个仓库拉取系统组件与推理后端(runner)镜像。该参数在 start CLI 参考 中的默认值为 docker.io,也对应配置键 system_default_container_registry 与环境变量 GPUSTACK_SYSTEM_DEFAULT_CONTAINER_REGISTRY(在 config.py 中定义)。
  • 命名空间约定:GPUStack 业务镜像约定存放在 gpustack 命名空间下。若内网仓库需要多级命名空间,应保持 gpustack 位于最后一级,例如 awesome.com/amazing-group/amazing-subgroup/gpustack,然后将 --system-default-container-registry 设为父路径 awesome.com/amazing-group/amazing-subgroup。若镜像无法放在 gpustack 命名空间下(例如 gpustack-ai),还需要同步调整 --image-repo 与 --benchmark-image-repo 参数(详见 start CLI 参考)。

从源码看,这一约定在 k8s/manifest_template.py 中也有体现:默认容器命名空间常量 _DEFAULT_CONTAINER_NAMESPACE = "gpustack",构建镜像引用时会按此命名空间拼接。若部署在内网仓库,需要保持该约定一致,才能让 system_default_container_registry 正确解析出镜像地址。

从需要认证的安全仓库拉取推理后端镜像

如果内网容器仓库要求认证,启动 GPUStack worker(或一体化 GPUStack 服务器)时需设置以下环境变量,使 worker 能够拉取 runner 镜像:

 sudo docker run -d --name gpustack \
     ...
+    --env GPUSTACK_RUNTIME_DEPLOY_DEFAULT_CONTAINER_REGISTRY_USERNAME=<your_internal_registry_username> \
+    --env GPUSTACK_RUNTIME_DEPLOY_DEFAULT_CONTAINER_REGISTRY_PASSWORD=<your_internal_registry_password> \
     <your_internal_registry>/gpustack/gpustack \
     --system-default-container-registry <your_internal_registry>

这两个环境变量的说明记录在 environment-variables.md 中:当 runner 镜像托管在需要认证的仓库时,需要在每个 GPUStack worker(或一体化服务器)启动时设置。实际生产中更推荐的做法是直接在容器运行时(Docker daemon 或 containerd)层面配置仓库认证,而不是依赖这两个环境变量。

从非默认命名空间拉取推理后端镜像

如果内网仓库使用的命名空间不是默认的 gpustack,需设置以下环境变量:

 sudo docker run -d --name gpustack \
     ...
+    --env GPUSTACK_RUNTIME_DEPLOY_DEFAULT_CONTAINER_NAMESPACE=<your_namespace> \
     <your_internal_registry>/gpustack/gpustack \
     --system-default-container-registry <your_internal_registry>

GPUSTACK_RUNTIME_DEPLOY_DEFAULT_CONTAINER_NAMESPACE 的默认值为 gpustack(见 environment-variables.md)。若镜像托管在 gpustack 之外的命名空间(如 gpustack-ai),将其设为 gpustack-ai 即可;对于多级命名空间(如 awesome.com/amazing-group/amazing-subgroup/gpustack-ai),则按前文所述,用 --system-default-container-registry=awesome.com/amazing-group/amazing-subgroup 声明仓库父路径。

如果通过 Helm 在 Kubernetes 中部署,图表(chart)会把 global.hub 作为 GPUSTACK_SYSTEM_DEFAULT_CONTAINER_REGISTRY 传给服务器,确保 vLLM、llama.cpp 等推理引擎镜像也从同一仓库拉取(见 charts/gpustack-chart/README.md 与 server-statefulset.yaml)。

离线环境中的自带文档

GPUStack 服务器内置了当前版本的官方文档,并在 /help/ 路径下直接提供访问:

http://<your_gpustack_server>/help/

这份文档与在线站点内容一致,版本与服务器镜像构建时所基于的版本相同,且内置搜索完全离线可用。因此,离线部署完成后,团队可以直接在内网浏览 GPUStack 的完整使用文档(模型部署、GPU 服务实例、监控观测、SSO 等),无需再访问互联网。

总结与常见注意事项

  1. 镜像清单要完整:离线环境必须包含 GPUStack 自身镜像、runner 推理镜像、Higress 网关镜像、benchmark-runner 以及 CSI 存储相关镜像。手工拷贝容易遗漏,建议始终使用 list-images / copy-images / save-images 官方命令生成与当前版本严格匹配的清单。
  2. 版本一致性:镜像管理命令默认按 latest 工作;正式离线部署务必使用与服务器镜像完全一致的版本标签(如 gpustack/gpustack:vx.y.z),避免版本漂移导致镜像缺失或 API 不兼容。
  3. 命名空间与仓库地址:遵守 gpustack 命名空间约定,正确配置 --system-default-container-registry;多级命名空间时保持 gpustack 为最后一级;非默认命名空间或私有认证仓库分别通过 GPUSTACK_RUNTIME_DEPLOY_DEFAULT_CONTAINER_NAMESPACE 与 GPUSTACK_RUNTIME_DEPLOY_DEFAULT_CONTAINER_REGISTRY_USERNAME/PASSWORD 处理。
  4. 容器运行时就绪:确保 Docker 与 GPU 容器工具包(NVIDIA / AMD / Ascend 等)配置完成,并预先验证驱动(nvidia-smi、npu-smi info 等),否则即使镜像就绪,推理服务也无法访问加速设备。
  5. 离线自助查阅:部署完成后通过 http://<your_gpustack_server>/help/ 访问随服务器携带的离线文档,便于运维与使用者随时查阅。

按上述流程操作,即可在完全隔离的网络中完成 GPUStack 从镜像搬运到服务上线的全过程。更详细的命令参数可继续查阅 copy-images、list-images、save-images、load-images 与 start 的 CLI 参考文档,以及 环境变量说明 和 安装要求。

登录后查看全文
gpustack