1. 服务端搭建与配置
在搭建GPUStack服务端时,我们使用以下Docker命令启动容器:
./docker -H unix://$(pwd)/docker.sock run \
--shm-size=128g \
-idt \
--ipc=host \
--network=host \
--security-opt seccomp:unconfined \
--name gpustack \
-v /data/labs/gpustack-data:/var/lib/gpustack \
docker.1ms.run/gpustack/gpustack:main-cpu \
--port 8090 \
--debug
关键配置说明:
--network=host:使用宿主机网络模式,这对后续通过SSH隧道连接多个VLAN至关重要
-v数据卷挂载:确保配置和状态数据持久化存储
组网结构挑战:
在实际部署中,我们面临多个VLAN间网络策略限制的问题。通过利用各VLAN信任的堡垒机建立SSH隧道(包括本地端口转发LPF和远程端口转发RPF),实现跨VLAN通信。这种设计既保证了安全性,又满足了GPUStack服务端访问各计算节点的需求。
2. worker端搭建
以NPU Worker为例,部署流程如下:
2.1 获取服务端Token
首先从服务端获取认证Token:
./docker -H unix://$(pwd)/docker.sock exec -it gpustack cat /var/lib/gpustack/token
2.2 启动NPU Worker容器
docker run -it -d --net=host --shm-size=128g \
--ipc=host \
--privileged=true \
--name gpustack \
--restart=unless-stopped \
-e ASCEND_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 \
--device=/dev/davinci_manager \
--device=/dev/hisi_hdc \
--device=/dev/devmm_svm \
--device=/dev/davinci0 \
--device=/dev/davinci1 \
--device=/dev/davinci2 \
--device=/dev/davinci3 \
--device=/dev/davinci4 \
--device=/dev/davinci5 \
--device=/dev/davinci6 \
--device=/dev/davinci7 \
-v /usr/local/Ascend/driver:/usr/local/Ascend/driver:ro \
-v /usr/local/sbin:/usr/local/sbin:ro \
-v /data/labs/weights:/data/labs/weights:rw \
-v /data/labs/updates:/data/labs/updates:ro \
-v /etc/ascend_install.info:/etc/ascend_install.info:ro \
-v /data/labs/gpustack-data:/var/lib/gpustack \
docker.1ms.run/gpustack/gpustack:main-npu \
--server-url http://127.0.0.1:8090 \
--worker-ip 127.0.0.1 \
--worker-port 10150 \
--worker-name "npu-198-97" \
--token c8e291d8045736ab3aa5ddb6de619291
2.3 网络隧道配置技巧
2.3.1 服务端访问隧道
指定GPUStack服务端URL地址:--server-url http://127.0.0.1:8090,前提条件是将GPUStack服务端的端口映射到NPU服务器上,便于worker访问。
# 以下隧道创建命令均需在堡垒机上执行!
# 在堡垒机上创建GPUStack服务端口的LPF隧道
ssh -o ServerAliveInterval=60 -o ServerAliveCountMax=3 -o SetEnv=Notes=GPUStack -CfNg -L 8090:<GPUStack服务端IP>:8090 root@<GPUStack服务端IP>
# 在上述隧道基础上在NPU服务器上建立RPF隧道
ssh -o ServerAliveInterval=60 -o ServerAliveCountMax=3 -o ExitOnForwardFailure=yes -o SetEnv=Notes=GPUStack -CfNg -R 8090:127.0.0.1:8090 user@<NPU服务器IP>
上述采用了LPF+RPF隧道叠加方式建立了NPU与GPUStack服务端的通信。
2.3.2 健康检查隧道
指定当前GPUStack worker的IP为127.0.0.1,这样做的目的是告知GPUStack服务端使用隧道对worker进行健康检查,即http://127.0.0.1:10150;而不能使用NPU服务器的真实地址,因为VLAN之间网络策略不通。
# 在堡垒机上创建GPUStack worker的健康检查端口的LPF隧道
ssh -o ServerAliveInterval=60 -o ServerAliveCountMax=3 -o SetEnv=Notes=GPUStack -CfNg -L 10150:<NPU服务器IP>:10150 user@<NPU服务器IP>
# 在上述隧道的基础上在GPUStack服务端宿主机上建立RPF隧道
ssh -o ServerAliveInterval=60 -o ServerAliveCountMax=3 -o ExitOnForwardFailure=yes -o SetEnv=Notes=GPUStack -CfNg -R 10150:127.0.0.1:10150 root@<GPUStack服务端IP>
注意事项:
1、使用127.0.0.1作为worker IP是为了通过隧道进行健康检查
2、规范命名worker节点(--worker-name)便于管理界面识别
3 问题诊断与处理
worker注册成功后,状态偶尔会出现Not Ready的状态:
图1、worker状态为Not Ready(HeartBeat lost)
分析:从代码可知,心跳时间戳检查与前主机时间戳有关,因此该问题可能与宿主机时间不同步有关!
def compute_state(self, worker_offline_timeout=60):
now = int(datetime.now(timezone.utc).timestamp())
heartbeat_timestamp = (
self.heartbeat_time.timestamp() if self.heartbeat_time else None
)
if (
heartbeat_timestamp is None
or now - heartbeat_timestamp > worker_offline_timeout
):
self.state = WorkerStateEnum.NOT_READY
self.state_message = "Heartbeat lost"
return
配置chronyd时间服务后重启worker恢复正常!
ntpSrvAddr=192.168.0.1
sed -i '/server.*burst/d' /etc/chrony.conf
echo 'server '$ntpSrvAddr' iburst' >> /etc/chrony.conf
systemctl daemon-reload; systemctl restart chronyd
chronyc sources
4 总结
本文主要介绍了以下技术方案:
1、跨多个VLAN统一纳管GPU/NPU资源
2、通过SSH隧道安全地建立网络连接
3、解决时间同步导致的状态异常问题
建议:
1、提前规划好网络隧道策略
2、确保所有节点时间同步
3、规范命名worker节点便于管理
4、定期检查隧道连接状态
这种方案特别适合需要跨多个安全域统一管理异构计算资源的场景,既满足了安全要求,又提供了灵活的资源调度能力。