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 の組み合わせを必ず最新の公式情報で再確認してください。