クラスター管理
GPUStack は、クラスター単位のワーカー管理と複数のクラスタータイプをサポートしています。DigitalOcean などの Cloud Provider でクラスターを作成するほか、セルフホストのクラスターを作成して Docker の実行コマンドでワーカーを追加できます。また、セルフホストの Kubernetes クラスターにあるすべてのノードを GPUStack ワーカーとして登録することもできます。
クラスターの作成
Clustersページに移動します。Add Clusterボタンをクリックします。- クラスタープロバイダーを選択します。
Self-HostプロバイダーではDockerとKubernetes、Cloud ProviderではDigitalOceanとSHUIHUA FUTUREを選択できます。 - プロバイダーに応じて、
Base ConfigurationとAdd Workerの各ステップで異なるオプションを設定します。 - 基本設定の
Advancedクラスター設定では、Worker Configuration YAMLを使ってワーカーのオプションを事前設定できます。
Docker クラスターの作成
Basic Configurationステップでは、Nameは必須、Descriptionは任意です。Saveをクリックします。Add Workerステップでは、docker runコマンドでワーカーを追加する前に、いくつかのオプション設定と検証が必要です。Select the GPU vendorで GPU ベンダーを選択します。検証済みのベンダーはNvidia、AMD、Ascendです。実験的な対応ベンダーはHygon、Moore Threads、Iluvatar、Cambricon、Metaxです。選択後にNextをクリックします。Check Environmentで環境を確認します。ワーカーを追加する準備が整っているかを検証するシェルコマンドが表示されます。スクリプトをコピーして対象環境で実行し、OK が返されたらNextをクリックします。-
Specify argumentsで追加するワーカーの引数を指定します。次の引数を設定し、Nextをクリックします。 -Specify the worker IPでワーカー IP を指定するか、Auto-detect the Worker IPで自動検出させます。ワーカー IP にサーバーからアクセスできることを確認してください。 - ワーカーコンテナーのAdditional Volume Mountを指定します。マウント先のパスは、既存のモデルファイルの再利用に使用できます。 -
Run commandでワーカーコンテナーを作成し、起動します。bash スクリプトをコピーして対象環境で実行します。
クラスター作成後にワーカーを追加することもできます。
Clustersページに移動します。- ワーカーを追加するクラスターを探します。
- 操作列の省略記号ボタンをクリックし、
Add Workerを選択します。 - ワーカーを追加するためのオプションを選択します。上記の
Select the GPU vendorからRun commandまでと同じ手順に従います。
Kubernetes クラスターの登録
Basic Configurationステップでは、Nameは必須、Descriptionは任意です。Saveをクリックします。Select the GPU vendorで GPU ベンダーを選択します。検証済みのベンダーはNvidia、AMD、Ascendです。実験的な対応ベンダーはHygon、Moore Threads、Iluvatar、Cambricon、Metaxです。Kubernetesクラスターでは複数の GPU ベンダーを選択できます。CPU 専用クラスターでは何も選択しません。選択したベンダーごとに 1 つのワーカー DaemonSet が生成され、各 DaemonSet のnodeSelectorはマニフェスト生成時にそのベンダーの PCI 存在ラベルから導出されます。選択後にNextをクリックします。Check environmentで環境を確認します。ワーカーを追加する準備が整っているかを検証するシェルコマンドが表示されます。スクリプトをコピーして対象環境で実行し、OK が返されたらNextをクリックします。Run commandでワーカーのマニフェストを適用します。bash スクリプトをコピーし、kubectlがインストールされ、kubeconfigが設定された環境で実行します。
クラスター作成後に Kubernetes を登録することもできます。
Clustersページに移動します。- Kubernetes クラスターを登録する対象のクラスターを探します。
- 操作列の省略記号ボタンをクリックし、
Register Clusterを選択します。 - クラスターを登録するためのオプションを選択します。上記の
Select the GPU vendorからRun commandまでと同じ手順に従います。
Kubernetes クラスターのオプション
Kubernetes クラスターの作成時または編集時には、Basic Configuration ステップで、Name と Description に加えて次のオプションを設定できます。
Cluster Type(必須)— クラスターの用途を選択します。Model Service— モデル API やトークンベースのサービスの公開など、LLM 推論と API サービングに使用します。GPU Service— 対話型の開発、学習ジョブ、カスタム環境など、オンデマンドの GPU 計算に使用します。
Advanced 設定では、次の Kubernetes デプロイオプションを設定できます。
Namespace— クラスターのマニフェストの生成先となる Kubernetes 名前空間です。空の場合はgpustack-systemを使用します。Volume Mounts— すべてのワーカーポッドにマウントする追加ボリュームです。各マウントにVolume Name、Container Path、Read Onlyフラグを指定し、Source Typeを選択します。Host Path— ノード上のパスです。Path Type(例:Directory、Directory (create if not exists)、File、Socket、Character Device、Block Device)を指定します。Persistent Volume Claim (PVC)— 既存のPVC Nameです。読み取り専用に設定することもできます。ConfigMap—ConfigMap Nameです。存在を任意とする設定もできます。
Image Credentials— プライベートレジストリーから GPUStack イメージを取得する際に使うイメージプルシークレットです。エントリーごとにRegistry、Username、Passwordを指定します。Node Selector— このクラスターの GPUStack ワークロードを、ラベルが一致するノードに限定します。チャートのglobal.nodeSelectorとして渡され、各コンポーネントがフォールバック先として参照するため、ワーカー DaemonSet とオペレーターに適用されます。また、この設定に対応するオペレーターリリースでは、オペレーターがデプロイするコンポーネント(Kueue、Node Feature Discovery のコントロールプレーン、CSI コントローラー)にも適用されます。意図的に対象外となるワークロードが 2 種類あります。1 つは、対象ノード全体をカバーする必要がある Node Feature Discovery のラベラーと CSI ノードプラグインです。これらを限定すると、ほかのすべてのノードにラベルが付かなくなり、ワーカー自身が選択条件に使うラベルも失われます。もう 1 つはチャートのインストールフックです。リリースが存在する前に実行されるため、リリース自身が付けるラベルを待つことはできません。ワーカー DaemonSet は、これらのラベルに加えて GPU ベンダーラベルも保持します。ノードは両方に一致する必要があります。Default Container Registry— このクラスターの GPUStack イメージを解決する際に使うデフォルトのレジストリーです。未設定の場合はサーバーのデフォルトにフォールバックします(プレースホルダーはdocker.io)。Operator Image— GPUStack Operator のコンテナーイメージを上書きします。空の場合はサーバーのデフォルトを使用します。GPU Service Static Access Address—Cluster TypeがGPU Serviceの場合のみ表示されます。このクラスターの GPU インスタンスにアクセスするためにオペレーターが使用する静的アドレス(例: LoadBalancer の VIP)です。省略できます。Worker Configuration YAML— 以下のワーカー設定 YAML を参照してください。
名前空間と Pod Security Admission
GPUStack は、自身が管理する名前空間として gpustack-system(または Namespace の設定値)と、クラスターを使用する組織ごとの gpustack-<org> を作成し、それぞれに Pod Security Admission の privileged レベルのラベルを付けます。
必要な理由。 Pod Security Admission は Kubernetes に組み込まれており、Pod の作成時に適用されます。レベルに適合しない Pod は Pending のまま残るのではなく、即座に拒否されます。モデル、キャッシュサービス、ベンチマークの Pod には、baseline と restricted レベルで禁止されている次の機能が必要です。
| 要件 | 必要となる理由 |
|---|---|
| ホストネットワーク | RDMA が GID を NIC アドレスにバインドするため |
| hostPort | 分離されたペアが相手に渡すサイドチャネルのため |
| ホスト IPC | KV キャッシュバッファーを CUDA-IPC で共有するため |
| デバイスのマウント | アクセラレーターそのものを利用するため |
プリフィル/デコードのデプロイには 4 つすべてが同時に必要なため、このラベルがないと最も早く、深刻に失敗する構成です。
3 つのキーをすべて設定する理由。 warn と audit をクラスターのデフォルトのままにすると、Pod を作成するたびに警告が返され、監査アノテーションが記録されます。例外を適用することが想定された名前空間ではノイズとなり、ほかの場所で重要な警告が埋もれてしまいます。
影響範囲。 privileged は、その名前空間内のすべての Pod が Pod Security Admission の適用を免除されることを意味します。このため、ユーザー自身のワークロードと共有する名前空間ではなく、GPUStack が作成して管理する名前空間を使用しています。これらの名前空間には、ほかのワークロードをスケジュールしないでください。また、これらのラベルは Kyverno、Gatekeeper、OPA には影響しません。これらは別の Admission Webhook であり、ホストネットワークやデバイスマウントを禁止するポリシーがあれば、引き続き Pod は拒否されます。クラスターでこれらを使用している場合は、そちらでも GPUStack の名前空間を許可してください。
より厳しいレベルで拒否される内容の確認。 実行中のワークロードに対して、何も変更せずに確認できます。
API サーバーは、名前空間内の既存の Pod を指定したレベルで評価し、拒否される各 Pod と、違反する制御項目を警告します。
チャートの値
Kubernetes クラスターを登録すると、GPUStack Helm チャートがインストールされ、上記のオプションはそのチャートの値に変換されます。これらのオプションで扱えない設定には、同じチャートに直接渡せる helmValues を使用します。キーはチャート固有のものをそのまま使用するため、チャートやサブチャートが提供する設定は、この画面に専用のオプションが追加されるのを待たずに設定できます。
UI にはまだ入力欄がないため、API を通じて設定します。PUT はクラスター全体を置き換えるので、まずクラスターを読み取り、k8sOptions の下に helmValues を追加して返送してください。
値は、クラスターから導出された値に対して、キーごとに深さ優先でマージされます。リストは Helm 自体と同様に、追加ではなく置き換えとなります。キーの説明は各チャートにあります。GPUStack チャートの values.yaml、および gpustack-operator 配下の設定については GPUStack Operator チャートを参照してください。
一部のパスはマージされず、拒否されます。これらは、このクラスターの登録情報からサーバーが導出する設定で、リリースが発行先のクラスターと一致することを保証します。具体的には、ワーカーの報告先、実行するイメージ、そのイメージの取得元レジストリー、トークンを保持する Secret などです。API は拒否したパスを返し、helmValues フィールドの説明には現在の一覧が記載されています。このページで重複して記載しないことで、情報の不一致を防いでいます。
注記
クラスターを保存するだけでは、Kubernetes 側は変更されません。Register Cluster を再実行して、生成されたマニフェストを適用してください。クラスター内の Job が、マニフェストの要求とリリースのインストール元設定を比較し、異なる場合にのみアップグレードします。
注記
リリースがデプロイする構成を変えるアップグレードでは、生成対象から外れたワーカー DaemonSet が自動的に削除されます。たとえば、CPU 専用ノードがコントロールプレーンを担うクラスターで CPU ワーカー DaemonSet を無効にする場合(helmValues で worker.cpuEnabled=false を指定)、またはクラスターが選択しなくなった GPU ベンダーを削除する場合です。kubectl apply はマニフェストから除外されたオブジェクトを削除しないため、アップグレード Job が、リリースで生成されなくなったすべての <release>-worker[-<vendor>] DaemonSet を削除します。過去の Helm リビジョンがそれを管理していたかどうかは問いません。
このクリーンアップ機能が導入される前から残っているものも、同じ方法で削除されます。現在のマニフェストを一度適用すると、前回から設定が変わっていなくても Job が削除します。Job を実行できないクラスターに限り、次の手動操作が必要です。
バージョンだけをアップグレードする場合は、Register Cluster のパラメーター(GPU ベンダー、オプション)を、最後に適用したマニフェストと同じにしてください。それ以外の変更は、バージョンアップグレードではなく構成変更です。
警告
Kueue と Node Feature Discovery は必須です。オペレーターはこれらに基づいてスケジューリングの仕組みを構成し、起動時に CRD を待つため、クラスターに既存のものがない状態で無効にすると、オペレーターが起動できなくなります。このリリースがインストールしたものを無効にすると、それ自体が削除されます。Kueue の CRD はそのチャートに含まれ、すべての Workload と ClusterQueue も一緒に削除されます。
Kubernetes クラスターのアンインストール
アンインストールでは、登録時にインストールされたリリースの helm uninstall に加えて、Helm が管理していないオブジェクトを削除します。正常に完了するかは、事前準備によって決まります。オペレーターの配下(Kueue、Node Feature Discovery、CSI ドライバー、デバイスマネージャー)には、カスタムリソースにファイナライザーを付けるコントローラーがあります。アンインストールするとそのコントローラーが削除されるため、先にリソースを削除しなければ、リソースがある名前空間(gpustack-system、gpustack-default)が Terminating のままになります。次の順に実行してください。
- まず、このクラスターで実行するものをサーバーから削除します。デプロイ済みのモデルを削除(または移行)してから、クラスターのレコードを削除し、消失するワーカーへのスケジューリングをサーバーが停止するようにします。
-
コントローラーがまだ動作している間にカスタムリソースを削除し、削除の完了を待ちます。推測せず、このクラスターのリリースが管理するものを調べてください。
表示されたすべての CRD について、すべてのオブジェクトを削除し、残りがなくなるまで待ちます。
-
リリースをアンインストールします。メインのリリースは
gpustackです。5 つのgpustack-*アプリケーションリリースは、チャートがそれらのオブジェクトを引き継ぐ前に登録されたクラスターに存在します。存在しないリリースにhelm uninstallを実行するとエラーになるため、先に確認します。ここでは
--waitを渡さないでください。--waitを指定すると、アンインストールは Node Feature Discovery の post-delete prune フックまで進み、フックのnode-feature-discovery-pruneServiceAccount と ClusterRole を作成した後、削除待ちで停止します。この待機は--timeoutを超えて継続します(helm --debugで確認すると、タイムアウト後も数分間waiting for resources to be deleted count=1に留まり、作成された ServiceAccount が残っています)。抜け出すために Helm を終了すると prune RBAC が管理者のいない状態で残るため、ステップ 4 でこれらを手動削除する必要があります。--waitを指定しなければアンインストールは速やかに戻り、フックのリソースもほかと一緒にクリーンアップされ、オブジェクトは同様に削除されます。ステップ 4 では、Helm が管理していなかった残存物を削除します。 -
helm uninstallで削除されないものを削除します。Helm は CRD を削除しません。また、オペレーターは、どのリリースにも管理されない 3 種類のクラスター単位のオブジェクトを登録します。- オペレーター自身の CRD —
worker.gpustack.ai配下のdevices、instances、instancetypesです。チャートではなくオペレーターが起動時に作成するため、meta.helm.sh/release-nameアノテーションがなく、ステップ 2 の検出クエリーにも表示されません。instancetypeオブジェクトにはgpustack.ai/controlledファイナライザーが残ります。CRD の削除前または削除中にこれを除去しないと(下記参照)、CRD が削除中のままになり、グループの API が消えません。 - オペレーターの Admission Webhook —
gpustack-worker-mutation(Mutating)とgpustack-worker-validation(Validating)です。オペレーターの Service に転送し、失敗時には拒否するため、削除するまでworker.gpustack.aiオブジェクトへのすべての書き込み(下記のファイナライザー除去も含む)がservice "gpustack-operator-worker" not foundで拒否されます。 - オペレーターの APIServices —
v1.gpustack.aiとv1.worker.gpustack.aiです。これらもオペレーターの Service を参照します。削除するまで、削除中の名前空間はこれらのグループについてstale GroupVersion discoveryを報告し、完了しません。
Node Feature Discovery の prune RBAC も、
helm uninstallの後に残ることがあります。ClusterRole/node-feature-discovery-pruneとそのバインディングは post-delete prune フックのリソースで(上記の--waitに関する注意を参照)、フック実行中に Helm を終了すると管理者のいない状態で残ります。その後の登録では引き継がれず、インストールが拒否されるため、ほかと一緒に削除してください。次にクラスター単位のブートストラップ RBAC、その後に名前空間を削除します。
gpustack-systemにはブートストラップの ConfigMap、ServiceAccount、登録トークンの Secret も含まれ、名前空間の削除とともに削除されます。 - オペレーター自身の CRD —
-
(任意) 各ノードに残るデータを削除します。ワーカーポッドはホストの
/var/lib/gpustackをマウントしており、上記の手順ではこのディレクトリーを変更しません。ここにはダウンロード済みのモデルの重みやキャッシュが保存されています。再インストール時に問題になることはありません。同じノードにクラスターを再登録すると、このディレクトリーが再利用され、既存のファイルの再ダウンロードを省略できます。ストレージをほかの用途に必要とする場合にのみ削除してください。
kubectl get all -n gpustack-system(NotFound になること)、kubectl get clusterrolebinding | grep gpustack、kubectl get ds -A | grep -E 'gpustack|csi' で確認します。ステップ 4 でのみ削除するオブジェクトについては、kubectl get apiservice,mutatingwebhookconfiguration,validatingwebhookconfiguration 2>/dev/null | grep gpustack と kubectl get crd | grep -E 'gpustack|worker\.gpustack' でも確認します(どちらも何も表示されないこと)。
名前空間がすでに Terminating のままの場合は、コントローラーが消えたオブジェクトにファイナライザーが残っています。対象を特定してから、ファイナライザーを手動で除去してください。この操作が安全なのは、削除するクラスターだけです。先に Admission Webhook を削除してください(ステップ 4)。そうしないと、Service が存在しなくなった Webhook がパッチ自体を捕捉します。
クラスター単位の残存物も同じように除去します。gpustack.ai/controlled ファイナライザーを保持する instancetype.worker.gpustack.ai オブジェクトは、その CRD(および worker.gpustack.ai グループ全体)を削除中の状態に留めます。kubectl patch instancetypes.worker.gpustack.ai <name> -p '{"metadata":{"finalizers":null}}' --type=merge を実行してください。
DigitalOcean クラスターの作成
Basic Configurationステップでは、Nameは必須、Descriptionは任意です。DigitalOcean API との通信に使用するクラウド認証情報を作成または選択します。GPU Droplet をサポートするリージョンを選択します。新しく作成する DigitalOcean Droplet からアクセス可能なGPUStack Server URLも設定する必要があります。Nextをクリックします。- 1 つ以上の
Worker Poolsを追加します。プールごとにName、Instance Type、OS Image、Replicas、Batch Size、Labels、Volumesを指定できます。 - ワーカープールの設定後に
Saveをクリックします。
クラスター作成後にワーカープールを追加することもできます。
Clustersページに移動します。- ワーカープールを追加する
DigitalOceanクラスターを探します。 - 操作列の省略記号ボタンをクリックし、
Add Worker Poolを選択します。 - 上記のステップ 3 のオプションを設定して、新しいワーカープールを追加します。
SHUIHUA FUTURE クラスターの作成
Basic Configurationステップでは、Nameは必須、Descriptionは任意です。Shuihua API との通信に使用するクラウド認証情報を作成または選択します。Shuihua にはリージョンがないため、選択は不要です。新しく作成するインスタンスからアクセス可能なGPUStack Server URLも設定する必要があります。- このプロバイダーでは
Default Container Registryが必須です。Shuihua インスタンスは Docker Hub にアクセスできないため、Docker Hub に解決されるレジストリーは拒否されます。入力欄にはquay.ioとswr.cn-south-1.myhuaweicloud.comが候補として表示されます。独自の Harbor やミラーなど、アクセス可能なほかのレジストリーも指定できます。 Nextをクリックします。- 1 つ以上の
Worker Poolsを追加します。プールごとにName、Instance Type、OS Image、Replicas、Batch Size、Labelsを指定できます。Instance Typeは Shuihua の仕様テンプレートで、GPU モデル、時間単価、残り在庫とともに表示されます。売り切れのテンプレートは選択できません。Shuihua にはブロックストレージ API がないため、ボリュームは提供されません。 - ワーカープールの設定後に
Saveをクリックします。
クラスター作成後も、DigitalOcean クラスターと同じ方法でワーカープールを追加できます。
Shuihua インスタンスは NAT 配下にあり、ポート 22 と 80 だけがマッピングされています。そのため、クラスターはデフォルトで tunnel プロキシモードを使用し、ワーカーはサーバーの WebSocket トンネルを通じて推論を提供します。表示される IP はインスタンスのプライベートアドレスです。実際にアクセスできる接続先は、ワーカーの View SSH Access で確認してください。手順全体は Shuihua を使用した GPU クラスターの追加を参照してください。
ワーカープールの操作
クラウドプロバイダーのクラスターでは、Clusters ページでワーカープールを管理できます。
Clustersページに移動します。- 管理するクラウドプロバイダーのクラスターを探し、展開してワーカープールを表示します。
- ワーカーのレプリカ数を変更するには、ワーカー列で直接編集します。
- ワーカープールを編集するには、
Editボタンをクリックし、必要に応じてName、Replica、Batch Size、Labelsを更新します。 - ワーカープールを削除するには、そのワーカープールの操作列にある省略記号ボタンをクリックし、
Deleteを選択します。
クラスターの更新
Clustersページに移動します。- 編集するクラスターを探します。
Editボタンをクリックします。- 必要に応じて
Name、Description、Worker Configuration YAMLを更新します。 Saveボタンをクリックします。
クラスターの削除
Clustersページに移動します。- 削除するクラスターを探します。
- 操作列の省略記号ボタンをクリックし、
Deleteを選択します。 - 削除を確認します。
- モデルまたはワーカーが残っているクラスターは削除できません。
ワーカー設定 YAML
クラスターの作成時または更新時には、次の YAML の例を使ってワーカー設定を事前定義できます。
上記の YAML は、Worker Configuration YAML で現在サポートしているすべてのオプションを示しています。各オプションの意味は、GPUStack の設定ファイルのドキュメントを参照してください。proxy_mode オプションは、サーバーからワーカーへの接続方法を制御します。ワーカー接続モードを参照してください。
Docker クラスターと Kubernetes クラスターのどちらも、デフォルトのコンテナーレジストリーをここで設定しなくなりました。代わりに、Advanced 設定にあるクラスター単位の Default Container Registry オプションで設定してください。Kubernetes クラスターの名前空間も同様に、Namespace オプションで設定します(Kubernetes クラスターのオプションを参照)。
ワーカー接続モード
ワーカー上のモデルインスタンスに推論リクエストを転送するには、サーバーと API ゲートウェイからそのワーカーへのネットワーク経路が必要です。ワーカーの proxy_mode オプションを、ワーカー設定 YAML または --proxy-mode フラグで設定すると、次の経路を選択できます。
direct— サーバーとゲートウェイが、ワーカーの通知したアドレスとポートに直接接続します。オーバーヘッドが最も少ない方式ですが、サーバーからワーカーに直接到達できる必要があります。worker— リクエストは、ワーカー内蔵の HTTP リバースプロキシを経由し、ローカルの推論プロセスに転送されます。引き続きサーバーからワーカーに到達できる必要がありますが、公開するのはワーカーポートだけで済みます。tunnel— ワーカーはサーバーへの 1 本のアウトバウンド WebSocket 接続を維持し、サーバーはこのトンネルだけを通じてワーカーにアクセスします。ワーカーがサーバーからのインバウンド接続を受け付けられない場合に使用します。
デフォルトは、サーバー内の組み込みワーカーでは direct、スタンドアロンワーカーでは worker です。
トンネルモード(ファイアウォールまたは NAT 配下のワーカー)
direct と worker モードではサーバーが接続を開始するため、サーバーからワーカーに到達できる必要があります。しかし、ワーカーがファイアウォールや NAT の背後にある場合、別のネットワークにある場合、アウトバウンド通信のみ許可するプライベートサブネットにある場合など、到達できないことがあります。
tunnel モードでは向きが逆になり、ワーカーからサーバーへの一方向に接続を確立します。
- ワーカーが、登録にも使う同じ
--server-urlエンドポイントに対して、永続的なアウトバウンド WebSocket 接続を開きます。トークンで認証し、切断された場合は自動的に再接続します。 - サーバーは、プロキシポート(デフォルトは
30079、--proxy-portで設定)で HTTP/HTTPS プロキシを実行します。 - ゲートウェイがトンネルモードのワーカー上のモデルインスタンスにアクセスする際は、リクエストをサーバーのプロキシポートに送り、既存のトンネルを通じてワーカーに中継します。
ワーカーは外向きの接続だけを行うため、ワーカー側でインバウンドポートを開く必要はありません。サーバーの API ポートに到達できればよく、サーバーのプロキシポートにはゲートウェイから到達できる必要があります。
有効にするには、ワーカーの proxy_mode を tunnel に設定します。