BESTNET-CLOUD
GPU-VPS
GPUStack
10G Private Network
NFS Shared Cache
Tech Blog / Infrastructure Build Guide
Bestnet Cloud × GPU-VPS を 10G プライベートネットワークで接続し、
GPUStack クラスタを実装する手順 #
ベストネットクラウドをコントロールプレーン、GPU-VPS を推論ワーカーとして分離し、
共有 NFS キャッシュでモデルファイルを一元化する構成です。
クライアントポータル側の準備から
Ubuntu 上の実装、運用確認までをハウツー記事として整理しました。
Private Link
モデルダウンロード
GPU Worker
共有モデル保管先
この記事で扱う範囲 #
本稿は、Bestnet Cloud 上に AI-SRV を立てて GPUStack Server + NFS を集約し、
GPU-VPS 側に複数の GPU ワーカーを配置する初期構築パターンを扱います。
役割分離と共有キャッシュ設計が主題なので、公開向けに実 IP や内部命名規則は例示値へ置き換えています。
設計の核心は、GPU を必要としないコントロールプレーンとモデル保管先を汎用クラウド側へ寄せ、
GPU-VPS はあくまで推論実行用のノードとして割り切ることです。
こうしておくと、ワーカーを増やしてもストレージの重複投資を避けやすく、
モデルの実体は Bestnet Cloud 側の共有領域だけで管理できます。
モデル登録は GUI からのみ
AI-SRV に GPUStack Server + NFS を統合
全 worker はNFSマウントポイント /models を共有
ここでは 0.6.x 系の構築パターンを分かりやすく整理しています。
Bestnet Cloud ナレッジを、実際の構築順に読み替える #
Bestnet Cloud のナレッジでは、クライアントポータルの運用タスクが細かく分かれています。
そのため、GPU クラスタ構築では「どのタイミングでどのナレッジを使うか」を先に決めておくと手戻りが減ります。
本稿では、ポータル側の準備を次の順番に落とし込みました。
ポータル保護
MFA・許可 IP の考え方を先に固める
SSH 鍵登録
OS 展開前に管理鍵を整備
テンプレート作成
AI-SRV と GPU-VPS を Ubuntu 24 で用意
Private Network
10G セグメントへ全ノードを接続
Firewall / NAT
公開範囲と通信方向を絞る
Snapshot
初期状態を戻せる地点を残す
アーキテクチャの考え方 #
役割はシンプルです。Bestnet Cloud 側の AI-SRV が Web UI / API / NFS 共有を担い、
GPU-VPS 側のノードは GPUStack Worker と推論実行だけに集中します。
10G プライベートネットワークを使って内部通信を閉じることで、
モデル配布・NFS・クラスタ接続をすべて private side に寄せられます。
BESTNET-CLOUD
control-01 #
GPUStack Server + NFS を統合した AI-SRV
- Web UI / API を提供
/srv/gpustack_modelsを NFS export- ローカルでは
/modelsに bind mount - モデル実体を 1 箇所へ集約
NFS / UI / Worker Join / 内部通信
GPU-VPS
gpu-worker-01 / 02 #
/models を共有マウントし、推論だけを担当する worker 群
- GPUStack Worker を起動
--cache-dir /modelsを統一- 各 worker に大容量モデル保管領域を持たせない
- 横展開時は同じパターンで台数追加
→
最初の worker がモデルを 1 回だけ取得
→
他 worker は同じ
/models から読み込むだけ
事前に決めておく項目 #
| 役割 | 配置先 | ホスト名(例) | Private IP(例) | 主な責務 |
|---|---|---|---|---|
| Server + NFS | Bestnet Cloud | control-01 | 10.10.0.10 | GPUStack UI / API、NFS、モデル保管先 |
| GPU Worker #1 | GPU-VPS | gpu-worker-01 | 10.10.0.21 | 推論実行、共有 /models 利用 |
| GPU Worker #2 | GPU-VPS | gpu-worker-02 | 10.10.0.22 | 推論実行、共有 /models 利用 |
公開向けの例示です。実環境では自社の naming rule と private subnet に合わせてください。
クライアントポータル側の準備を先に固める #
クライアントポータル自体の防御を整える #
サーバー作成より先に、管理面の防御方針を決めます。特にチーム運用では、
MFA と許可 IP の扱いを先に整理しておくと、後から「誰がどこから管理面へ入れるか」で迷いません。
SSH 鍵を登録してからサーバーを作る #
AI-SRV と GPU ワーカーを作成した後に個別で鍵を差し込むより、クライアントポータルの SSH 鍵管理で
先に鍵を整備しておくほうが、テンプレート展開後すぐに管理へ入れます。
- 運用チーム用の公開鍵を整理する
- 緊急時の共有鍵と個人鍵を混在させない
- 記事公開時は鍵 fingerprint も載せない
Bestnet Cloud 上に AI-SRV をテンプレートから作成する #
AI-SRV には Ubuntu 24 系テンプレートを使い、GPUStack Server と NFS の両方を載せます。
このノードはモデル保管先も兼ねるため、OS ディスクとは別に十分な保存領域を確保する設計が向いています。
- 役割は GPUStack Server + NFS
- private network に接続する
- UI 公開が必要な場合のみ public 側を検討する
- モデル格納先の容量は worker よりも AI-SRV 側を厚くする
GPU-VPS 側に worker を必要台数ぶん作成する #
worker は推論用なので、GPU 種別・VRAM・将来のモデルサイズを基準に GPU-VPS のプランを選びます。
一方、モデル本体は NFS 側に寄せるので、worker のストレージは OS と実行に必要な最低限へ絞りやすくなります。
- Ubuntu 24 系で統一する
- GPU driver / CUDA が使える前提で作成する
- private network へ接続する
- 必要なければ public IP を持たせない構成も検討する
10G プライベートネットワークに全ノードを乗せる #
NFS と GPUStack の内部通信は、Bestnet Cloud と GPU-VPS を結ぶ 10G private link 上で流します。
これにより、モデル読み出しや worker join を public 側へ出さずに済みます。
- AI-SRV と全 worker を同一 private segment に収容する
- 固定 IP を割り当て、後続の NFS export と systemd 設定を安定化する
- worker に外向き通信が必要なら、NAT ルーター方式か一時 public egress を選ぶ
worker を private-only に寄せたい場合は、Bestnet Cloud の仮想ルーター / NAT パターンを使って
OS 更新や外部取得だけを外へ出す設計が扱いやすいです。
ファイアウォールの初期ルールを決める #
ルールは「AI-SRV に必要な inbound を最小限だけ許可し、worker は SSH 以外の inbound をほぼ持たせない」方針で十分です。
ポータルのファイアウォール画面で、まず既存ルールを確認し、その後に必要ポートだけ追加します。
| 対象 | ポート / プロトコル | 送信元の考え方 | 用途 |
|---|---|---|---|
| AI-SRV | 22/tcp | 管理元 IP のみに制限 | SSH |
| AI-SRV | 80/tcp | 管理ネットワーク or private side | GPUStack Web UI / API |
| AI-SRV | 2049/tcp | private subnet のみ | NFS v4 |
| AI-SRV | 111/tcp,111/udp | 必要時のみ private subnet | rpcbind を使う構成向け |
| GPU Worker | 22/tcp | 管理元 IP のみに制限 | SSH |
NFS v4 前提なら 2049/tcp に寄せやすい一方、環境によっては rpcbind を使うことがあります。公開範囲は必ず private subnet に限定します。
最初のスナップショットを取得する #
OS の初期作成、鍵投入、private network 接続、ファイアウォールの整備が終わったら、
いったん AI-SRV と GPU worker のスナップショットを取得しておくと、その後のミドルウェア導入で失敗しても戻しやすくなります。
OS 側のベースラインを作る #
サーバーと worker の両方で、まずは時刻同期と NFS のベースを揃えます。GPU ワーカーはこの後に GPU driver / CUDA を入れるため、
先に OS 更新と再起動ポイントを済ませておくと安定します。
# 全ノード
sudo apt update
sudo apt install -y nfs-common
# NFS サーバー用(AI-SRV のみ)
sudo apt install -y nfs-kernel-server
AI-SRV に GPUStack Server + NFS を構築する #
GPUStack Server をインストールする #
初期構築例では、AI-SRV に GPUStack Server を導入し、管理 UI へログインできる状態を作ります。
初期管理者パスワードは控えたら安全な vault へ移し、記事には掲載しません。
curl -sfL https://get.gpustack.ai | sh -s -
cat /var/lib/gpustack/initial_admin_password
# Web UI(例)
# http://10.10.0.10/NFS 共有ディレクトリを作る #
モデルファイルの実体は /srv/gpustack_models に置きます。
これを private subnet のみへ export し、AI-SRV 自身でも /models として bind mount します。
こうしておくと、サーバーから見えるパスと worker から見えるパスが統一されます。
sudo mkdir -p /srv/gpustack_models
echo "/srv/gpustack_models 10.10.0.0/24(rw,sync,no_subtree_check,no_root_squash)" | sudo tee -a /etc/exports
sudo exportfs -ra
# Server 自身も bind mount
sudo mkdir -p /models
sudo mount --bind /srv/gpustack_models /models
echo "/srv/gpustack_models /models none bind 0 0" | sudo tee -a /etc/fstabworker 参加トークンを発行する #
GPUStack の GUI から worker join token を作成します。公開記事では <WORKER_JOIN_TOKEN> として表記し、
実値は掲載しません。併せて、GUI へログインできる管理元も private network 側に寄せる運用だとより安全です。
GPU-VPS 側に共有 cache をマウントして worker を参加させる #
まずは /models を NFS マウントする #
各 worker は、AI-SRV が export している共有領域を同じパス /models でマウントします。
この時点で全 worker の cache path が揃うため、モデルの重複保存を防げます。
sudo mkdir -p /models
echo "10.10.0.10:/srv/gpustack_models /models nfs defaults 0 0" | sudo tee -a /etc/fstab
sudo mount -aマウント後は mount | grep /models で、意図した共有先が見えているか確認します。
GPUStack Worker をインストールする #
AI-SRV 側で発行した token を使い、各 GPU-VPS を worker としてクラスタへ参加させます。
curl -sfL https://get.gpustack.ai | sh -s - --server-url http://10.10.0.10 --token <WORKER_JOIN_TOKEN>worker サービスで --cache-dir /models を固定する #
共有 cache 構成では、この指定がもっとも重要です。GPUStack Worker の systemd 定義に--cache-dir /models を入れ、併せて data-dir も固定しておきます。
[Service]
ExecStart=/root/.local/bin/gpustack start --server-url http://10.10.0.10 --token <WORKER_JOIN_TOKEN> --cache-dir /models --data-dir /var/lib/gpustack-datasudo systemctl daemon-reload
sudo systemctl enable --now gpustack
# Using cache dir: /models が出れば OK
journalctl -u gpustack -fGPUStack GUI で worker が Ready になることを確認する #
GUI の Workers 画面で、全 GPU-VPS が Ready になることを確認します。
ここで Not Ready のままなら、GPU driver / CUDA、NFS マウント、worker ログの順に切り分けると早いです。
モデルデプロイと動作確認 #
構築完了の判断は、単に worker が Ready になることではありません。
実際に GUI からモデルを 2 replicas 以上で deploy し、最初の 1 台だけがダウンロードし、
2 台目以降が同じ共有ファイルを再利用するところまで確認して完了とします。
この構成で効くコスト最適化 #
GPU-VPS ごとにモデルを丸ごと持たないため、GPU ノードのストレージを薄く設計しやすくなります。
大きなモデルほど、共有 NFS キャッシュ方式の効果が分かりやすく出ます。
運用時の勘所 #
監視とトラブルシューティング #
Q. replicas を増やすと再ダウンロードしますか?
基本的にはしません。共有 /models にファイルが存在すれば、worker はそれを再利用します。
Q. worker は public IP が必須ですか?
必須ではありません。外向き通信の取り方を NAT 方式に寄せるなら、private-only で運用する選択もあります。
Q. どこを厚くするとコスト効率がよくなりますか?
各 GPU worker のストレージではなく、共有モデル置き場を持つ AI-SRV 側です。モデルを 1 箇所で管理できるからです。
Bestnet Cloud を制御系、GPU-VPS を実行系として切り分けると、GPU クラスタは扱いやすくなる #
AI-SRV に GPUStack Server と NFS を統合し、GPU-VPS 群は worker として private network でぶら下げる。
そのうえで /models を共有キャッシュにすると、ストレージの重複を避けながら GPU クラスタを素直に拡張できます。
ポータル側では、SSH 鍵、テンプレート展開、private network、ファイアウォール、スナップショットの順で整え、
OS 側では NFS と GPUStack のパスを統一する。これだけで、かなり実運用しやすい構成になります。
BESTNET-CLOUD × GPU-VPS
NFS Shared Cache
モデルは 1 回だけ取得