GPUStack
Docker Migration
NFS Shared Cache
GPU 클러스터 운영 메모
GPUStack을 v0.7.1에서 v2.1.1로 마이그레이션한 이야기
공유 NFS 모델 캐시 구성을 손상시키지 않고 업그레이드하기 #
기존 installation script 기반으로 운영하던 GPUStack 환경을 Docker 기반 v2 시리즈로 마이그레이션한 기록입니다.
관리 노드와 NFS를 겸하는 구성은 유지하면서 GPU 워커 노드 2대를 단계적으로 마이그레이션하고,
모델 캐시 공유·워커 재연결·배포 시 backend/CUDA 정합성 확인까지 정리했습니다.
Ubuntu / Docker / NVIDIA GPU / NFS
대상: GPUStack v0.7.1 → v2.1.1
이 글의 전제 #
실제 환경에서는 관리 노드 1대와 GPU 워커 2대로 구성하고, 모델 캐시를/models에 집약하여 NFS 공유하고 있습니다. 이 글에서는 실제 호스트명,
프라이빗 IP, 워커 토큰 등의 민감한 정보는 모두 숨기고 공개 가능한 수준까지 추상화했습니다.
원래 구성은 “관리 노드에 GPUStack Server와 NFS를 집약하고, GPU 워커 노드 그룹이
공통의 /models를 참조하는” 단순한 방식입니다. 모델 파일 다운로드를
1회로 끝낼 수 있어서 워커 추가 시 디스크 사용량과 네트워크 전송량을 줄일 수 있는 것이 장점이었습니다.
이 철학은 v2 시리즈로 마이그레이션하면서도 바꾸지 않고, 운영만 현행 방식에 맞춰 정리하기로 했습니다.
업그레이드 전후의 접근 방식 #
v2 시리즈로 올리기 전에 파악해야 할 포인트 #
1. 마이그레이션은 Docker 전제 #
기존 버전에서 installation script나 pip 기반으로 설치한 환경은,
v2 시리즈로 마이그레이션할 때 Docker 기반으로 통합하는 것이 공식 migration 경로입니다.
2. 관리 DB도 변경됨 #
v0.7 시리즈 이전에서 기본이었던 SQLite에서 v2.0 이후는 embedded PostgreSQL로 마이그레이션됩니다.
즉, “바이너리만 교체하는 업데이트”가 아니라 데이터 마이그레이션을 고려한 작업이 됩니다.
3. embedded worker 정리 #
기존 구성에서는 관리 노드가 worker로도 보였습니다. 이번에 이를 계기로
관리 노드는 Server 전담, GPU 워커만 Workers 목록에 남기는 방침으로 전환했습니다.
먼저 해두길 잘한 일 #
Server를 건드리기 전에 기존 데이터 디렉토리의 백업을 받았습니다.
v2 시리즈에서는 새로운 컴포넌트가 legacy data dir를 읽기 때문에 권한 조정과 백업이 매우 중요합니다.
실시한 업그레이드 절차 #
legacy data dir를 특정하고 먼저 백업 받기 #
기존 구성의 systemd 정의를 확인하고, Server / Worker가 각각 어떤 data dir를 사용하는지 명확히 했습니다.
그 위에서 서비스 중지 → tar 백업 → 권한 조정 순으로 작업했습니다.
sudo systemctl cat gpustack | sed -n '/ExecStart/p'
sudo systemctl stop gpustack
sudo systemctl disable gpustack
sudo tar -C / -cpf /root/backup/gpustack-server.tar var/lib/gpustack관리 노드를 먼저 v2.1.1로 마이그레이션하기 #
관리 노드는 GPU를 사용하지 않는다는 전제였기 때문에 Server 시작 시 --runtime nvidia는 제거했습니다.
이를 그대로 두면 Docker 측에 NVIDIA runtime이 등록되지 않은 서버에서는unknown or invalid runtime name: nvidia 오류로 시작에 실패합니다.
sudo docker run -d --name gpustack \
--restart=unless-stopped \
--privileged \
--network=host \
--env GPUSTACK_DATA_MIGRATION=true \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume /var/lib/gpustack:/var/lib/gpustack \
--volume /models:/models \
gpustack/gpustack:v2.1.1 \
--disable-worker \
--cache-dir /models여기서 --disable-worker를 명시한 이유는 관리 노드상의 old embedded worker를
깔끔하게 역할 분리하고 싶었기 때문입니다. 이번 마이그레이션에서는 “관리 노드는 관리에만 전념”이 테마였습니다.
GPU 워커를 Docker 버전 worker로 순차적으로 전환하기 #
워커는 기존 data dir을 계승하면서 Docker 버전 worker로 재연결했습니다.
공유 캐시 경로를 맞추기 위해 컨테이너에도 /models:/models를 bind하고,
시작 인수에 --cache-dir /models를 추가했습니다.
sudo docker run -d --name gpustack-worker \
--restart=unless-stopped \
--privileged \
--network=host \
--volume /var/lib/gpustack-data:/var/lib/gpustack \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume /models:/models \
--runtime nvidia \
gpustack/gpustack:v2.1.1 \
--server-url http://<SERVER_IP> \
--token <JOIN_TOKEN> \
--worker-name <WORKER_NAME> \
--worker-ip <WORKER_IP> \
--cache-dir /models핵심은 GUI의 “워커 추가”를 그대로 “등록 작업”으로 생각하지 않는 것이었습니다.
실제로 GUI는 token이나 실행 명령을 얻기 위한 입구이며, Ready 상태가 되는 것은 워커 노드 측에서
실제 명령을 실행한 이후입니다.
NVIDIA Container Toolkit 확인하기 #
GPU 워커 측에서는 --runtime nvidia가 필수입니다. 만약 Docker가 runtime을 인식하지 못하는 경우,
NVIDIA Container Toolkit 설정이 반영되지 않았을 수 있습니다. 공식 절차대로nvidia-ctk로 Docker runtime을 구성하고 Docker를 재시작합니다.
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart dockerWorkers 목록을 “실제로 추론하는 노드만”으로 정리하기 #
기존 환경에서는 관리 노드가 worker로 남아 있어 목록상으로는 Not Ready로 보여 혼란의 원인이 되었습니다.
GPU 워커 2대가 Ready가 된 시점에 관리 노드 유래의 stale worker는 정리 대상으로 삼았습니다.
이렇게 해두면 운영 팀이 봐도 역할이 직관적입니다.
이번에 겪은 문제점 #
관리 노드에서 unknown or invalid runtime name: nvidia #
Server 노드에 GPU를 탑재하지 않았거나 NVIDIA runtime을 설치하지 않았는데--runtime nvidia를 붙인 채로 기동했습니다. 관리 노드를 Server 전용으로 한다면
여기는 간단히 제거하는 것이 좋았습니다.
Worker는 Ready인데 모델이 Pending #
워커의 상태와 모델 배포 가능 여부는 별개의 문제였습니다. 특히 v2 이행 직후에는
backend version의 승계나 CUDA 세대와의 정합으로 Pending이 되는 경우가 있습니다.
“worker가 Ready가 되면 끝”이 아니라, 실제로 1건 배포해서 확인하는 곳까지가 이행입니다.
배포 시의 교훈 #
이번에는 worker 측의 OS 업데이트도 포함되어 있어, 결과적으로 CUDA 계열 패키지가 12.9 세대로 정렬되었습니다.
그 상태에서 GPUStack 측의 built-in backend version과 deployment 설정을 재검토할 필요가 있었습니다.
이행 후에는 Inference Backends와 Deployment의 backend/version 지정을
세트로 확인하는 것이 안전합니다.
체크리스트 #
- 기존 환경의 data dir과 systemd 정의를 먼저 파악한다
- Server 백업을 받은 후 이행을 시작한다
- 관리 노드는 먼저, GPU 워커는 나중 순서로 올린다
- NFS 공유 캐시를 사용한다면
/models를 host / container / worker에서 통일한다 - Server 전용 노드라면 embedded worker를 끄고 Workers 목록을 심플하게 한다
- 워커 연결 후에는 반드시 1건 배포해서 backend/CUDA의 정합까지 확인한다
정리 #
이번 업그레이드에서 가장 효과가 있었던 것은 버전을 올리는 것 자체보다
“노드의 역할을 정리해서 화면상의 보이는 방식을 알기 쉽게 한 것”이었습니다.
관리 노드는 Server + NFS, 추론은 GPU 워커만으로 역할이 명확해진 덕분에
이후의 운영 판단이 훨씬 수월해졌습니다.
만약 동일하게 v0.7 계열 이전부터 사용하고 있으며, shared cache 구성을 유지하면서 v2 계열로 올리고 싶은 경우에는
Server 선행·Worker 후속·deployment까지 실검증의 3가지를 강력히 권장합니다.
“기동할 수 있다”로 끝내지 않고 실제로 모델이 구동되는 곳까지 확인하면 이행의 품질이 상당히 안정됩니다.
참고한 공식 정보 #
- GPUStack Migration Guide
- GPUStack CLI Reference: gpustack start
- GPUStack Release Notes
- NVIDIA Container Toolkit Install Guide
본 기사는 특정 사내 환경을 소재로 한 실천 메모입니다. 실운영에 적용할 때는 사용 중인 GPU, 드라이버,
CUDA 세대, backend version의 조합을 반드시 최신 공식 정보로 재확인하시기 바랍니다.