目录

科研与小团队 GPU 共享容器落地方案:Agent 模式纳管内网节点与内网穿透全流程

背景

科研团队或小型技术团队中,GPU 资源往往集中在少数物理机上。这些机器通常部署在机房、实验室内网或家庭宽带环境中,没有固定的独立公网 IPv4 地址,无法通过传统 SSH 方式直接被管理平台纳管。与此同时,多人共享同一台 GPU 机器的需求也越来越普遍——既要隔离各自的运行环境,又要能从外部访问各自的容器。

本文介绍一套完整的解决方案:使用 oneclickvirt 项目的 Agent 模式,将无独立公网 IPv4 的 GPU 节点纳入统一管理平台,配合内网穿透实现外部访问,再通过 LXD/Incus 开设共享 GPU 的隔离容器,供多位用户分别使用。


整体架构

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
外部用户
    |
    | HTTPS/WSS
    v
主控服务器(有独立公网 IPv4)
    |
    | WebSocket 隧道(WS/WSS)
    v
Agent 节点(无独立公网 IPv4,如机房内网机、实验室工作站、家宽机器)
    |
    | LXD/Incus 容器
    v
各用户独立的 GPU 容器(通过内网穿透暴露端口供外部 SSH 或其他访问)

主控服务器承担两个角色:一是虚拟化管理平台的控制端,二是内网穿透的中继节点,将无公网 IP 节点上的容器端口转发到自身可达的端口上。


主控部署要求

内网穿透功能要求主控对宿主机网络与防火墙具有直接控制能力,因此主控的部署方式有明确限制。

主控必须满足以下全部条件:

  • 部署方式为脚本部署裸机编译部署,不支持 Docker 或 Docker Compose 部署
  • 运行在拥有独立公网 IPv4 地址的 Linux 服务器上
  • 具备 Root 权限

不满足上述条件(包括通过 Docker 部署主控,或主控所在机器无独立公网 IPv4,或非 Linux 系统)将无法正常使用内网穿透功能。


Agent 模式纳管节点

适用场景

以下类型的节点无法通过标准的 SSH 直连方式纳管,需使用 Agent 模式:

  • 本地工作站 / 实验室内网机
  • 家庭宽带接入的设备(动态 IP 或 NAT 后)
  • NAT 网络环境中的云主机

对于有固定独立 IPv4 的普通云服务器,也可以选择 Agent 模式,配置方式基本一致。

新增节点并选择 Agent 模式

在管理后台的节点列表页面,点击新增节点,进入节点类型选择界面。

新增节点选择 Agent 模式

点击 Agent 模式后,进入基础信息配置页面。

Agent 模式基础信息配置页面

配置节点信息

与标准模式不同,Agent 模式下 IP 地址和端口均为可选项,无需强制填写。

  • 本地节点 / 家宽节点 / NAT 网络节点:IP 地址和端口保持留空
  • 有固定独立 IPv4 的服务器:可按实际情况填写 IP 和端口

需要特别注意:若 IP 地址与端口留空,后续选择网络模式时仅支持无端口映射模式;若填写了 IP 与端口,则网络模式与标准模式一致,可选全部类型。

Agent 节点配置及网络模式说明

保存并获取安装命令

配置完成后点击保存,页面会在连接配置区域出现生成安装命令的按钮。

重要说明:节点保存后,系统会为该节点生成并固化一个唯一的 Token,该 Token 一经生成无法单独刷新或修改。若 Token 泄露,只能删除该节点记录、重新创建节点并重新配置。请妥善保管 Token。

连接配置区域,点击生成安装命令

点击生成后,会得到一条完整的安装命令。将该命令复制后,在目标节点服务器上以 Root 身份执行,即可完成 Agent 的安装与接入。

验证连接状态

Agent 安装完成后,返回管理后台,在该节点的连接配置页面下方点击检测按钮,验证节点是否已成功连接主控。

点击检测按钮验证连接

检测成功界面

检测成功后,该节点后续的大部分配置与标准模式一致。


内网穿透端口映射

功能说明

内网穿透端口映射(即后台中的内穿端口功能)仅对 Agent 模式纳管的节点有效,原理是通过 WS/WSS WebSocket 隧道将节点内部端口转发到主控服务器上。

因此若主控前置了 Nginx 等反向代理,务必确保已在反向代理中配置了 WebSocket 协议转发(Upgrade: websocket 头部处理),否则内网穿透将无法正常工作。

配置网络模式

对于本地节点(IP 和端口留空的情况),在后续开设容器时,网络模式必须选择无端口映射

网络模式选择无端口映射

选择无端口映射后,外部对容器的访问需通过管理员后台的端口管理页面手动添加端口穿透规则来实现。

添加端口穿透规则

进入管理员后台的端口管理页面,点击添加端口。在端口类型处选择控制端转发(内网穿透)。非必填的外部端口字段可以留空,系统将自动从主控服务器的可用端口中分配。

端口管理页面,添加内网穿透端口

添加成功后,主控服务器上对应的端口会将流量通过 WebSocket 隧道转发到指定节点内部的目标端口,外部用户即可通过 主控IP:分配端口 访问容器内的服务(SSH、Jupyter、Web 应用等)。

安全建议

若被纳管的节点有防探测、防封禁或隧道保密需求,强烈建议:

  1. 为主控服务器绑定域名
  2. 配置 HTTPS
  3. 纳管节点时使用 WSS 协议而非 WS 协议

WSS 协议通过 TLS 加密隧道流量,可有效降低隧道被识别、探测或封禁的风险。


GPU 共享容器全流程

以下流程以 NVIDIA GPU 为例,适用于 LXD 或 Incus 环境。

前置条件

宿主机(即被纳管的 Agent 节点)必须满足

  1. 已通过 oneclickvirt 的 LXD/Incus 教程完成本地虚拟化环境的安装和初始化
  2. 已在宿主机上安装好对应版本的 NVIDIA 驱动
  3. 宿主机上执行 nvidia-smi 有正常输出,类似如下格式:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
root@a12-ThinkStation-P620:/root# nvidia-smi
Sat May 16 20:23:07 2026
+---------------------------------------------------------------------------------------+
| NVIDIA-SMI 535.171.04             Driver Version: 535.171.04   CUDA Version: 12.2     |
|-----------------------------------------+----------------------+----------------------+
| GPU  Name                 Persistence-M | Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp   Perf          Pwr:Usage/Cap |         Memory-Usage | GPU-Util  Compute M. |
|                                         |                      |               MIG M. |
|=========================================+======================+======================|
|   0  NVIDIA RTX A6000               Off | 00000000:61:00.0 Off |                  Off |
| 30%   42C    P0              83W / 300W |      0MiB / 49140MiB |      1%      Default |
|                                         |                      |                  N/A |
+-----------------------------------------+----------------------+----------------------+
  1. 已通过 Agent 模式将该宿主机成功纳管,且健康检测通过

创建 GPU 容器

推荐开启节点的仅兑换码兑换模式,通过管理员后台的兑换码页面,在创建容器时选择 GPU 设备类型,生成对应的兑换码。

管理员先以普通用户视图兑换该兑换码,完成容器创建,再切回管理员视图进行后续操作。

兑换码页面选择 GPU 设备创建容器

通过内穿端口访问新建容器

容器创建完成后,在管理员后台的端口管理页面,为该容器的 SSH 端口(通常为 22)添加一条控制端转发规则(即内网穿透),以便通过 Web 终端或外部 SSH 直接进入容器。

为容器添加内穿端口,使用 Web SSH 连接

端口添加成功后,可直接通过管理后台的 Web SSH 功能进入该容器进行配置。

容器内安装 GPU 驱动

容器和宿主机共享同一套 GPU 硬件,因此容器内必须安装与宿主机版本完全一致的 NVIDIA 驱动,但安装时不能加载内核模块

具体步骤如下:

1. 确认宿主机驱动版本

在宿主机上执行:

1
nvidia-smi

记录 Driver Version 字段的版本号,例如 535.171.04

2. 进入容器

1
lxc exec <容器名> -- /bin/bash

3. 下载对应版本的驱动

访问 NVIDIA 官方驱动搜索页面(https://www.nvidia.cn/Download/Find.aspx?lang=cn),按照实际显卡型号和驱动版本进行查询,右键复制下载链接,然后在容器内用 wget 下载:

1
wget https://cn.download.nvidia.com/XFree86/Linux-x86_64/535.171.04/NVIDIA-Linux-x86_64-535.171.04.run

4. 安装驱动,加入 --no-kernel-module 参数

1
bash NVIDIA-Linux-x86_64-535.171.04.run --no-kernel-module

安装过程中出现的交互选项全部选择 no 即可。安装完成后在容器内执行:

1
nvidia-smi

若输出与宿主机版本一致,说明 GPU 已成功共享至该容器。

容器内 nvidia-smi 输出正常,GPU 共享成功

注意:由于驱动未加载到内核,若容器重启后 nvidia-smi 输出异常,重新执行上述安装命令后再重启容器即可恢复。保留下载好的 .run 文件备用。

5. 禁止驱动自动更新

为防止系统自动更新破坏已固定的驱动版本,在宿主机和容器内均执行以下操作:

1
2
3
4
5
6
cat > /etc/apt/apt.conf.d/10periodic << 'EOF'
APT::Periodic::Update-Package-Lists "0";
APT::Periodic::Download-Upgradeable-Packages "0";
APT::Periodic::AutocleanInterval "0";
APT::Periodic::Unattended-Upgrade "0";
EOF

在宿主机上还可以通过 apt-mark hold 锁定 NVIDIA 相关软件包版本:

1
apt-mark hold nvidia-*

制作母本容器并批量复制

完成驱动验证后,停止该容器,将其作为母本。通过管理后台的兑换码批量开设功能,选择复制模式,以该母本容器为源,批量创建新容器,分配给各位研究人员或团队成员使用。

每个复制出来的容器均具备 GPU 访问能力,各自环境完全隔离,互不干扰。每个容器根据需要单独添加内网穿透端口规则,对外暴露各自的服务端口。


版本更新说明

当主控平台版本升级后,需同步更新各 Agent 节点上的 Agent 程序。

更新时,将安装参数中的 source 设置为 controller,Agent 程序会直接从主控服务器的特定路径下载最新的脚本和所需文件,而不依赖外部网络,适合在内网环境中使用。


小结

整个方案的核心是:主控与 Agent 节点之间通过 WebSocket 隧道保持长连接,主控借助隧道将内网节点的端口转发到公网可达的地址上。GPU 共享则依赖 LXD/Incus 的设备透传机制,多个容器可共享同一张显卡,彼此隔离。

适合以下场景:

  • 科研团队的 GPU 工作站集中管理,各成员独享容器环境
  • 实验室内网机器无法从外部直接 SSH,但需要统一纳管和分配资源
  • 家宽或 NAT 网络后的 GPU 机器,不具备独立公网 IP 但仍需对外提供服务
  • 小团队希望通过兑换码机制控制 GPU 容器的分配和使用权限