El Reg による LLM を本番環境に導入するための必須ガイド

Table of Contents

El Reg による LLM を本番環境に導入するための必須ガイド

ハンズオンLlama.cpp または Ollama を使用すると、数分でチャットボットを立ち上げることができますが、複数のユーザー、稼働時間の保証、GPU 予算の超過がないことを前提とした実際のワークロードを処理できるように大規模な言語モデルを拡張するのは、まったく別の話です。

モデルは4GB未満のメモリを搭載したPCでも効率的に動作するかもしれませんが、大規模なモデルを提供するために必要なリソースは大きく異なります。多数の同時リクエストを処理する本番環境にデプロイするには、40GB以上のGPUメモリが必要になる場合があります。

この実践ガイドでは、ローカルの概念実証から本番環境対応のデプロイメントまで AI ワークロードをスケーリングする方法を詳しく見ていき、Gemma 3 や Llama 3.1 などのモデルを大規模にデプロイするプロセスについて説明します。

APIを使った構築

LLM をコード ベースに統合する方法は多数ありますが、本番環境に展開する場合は、OpenAI 互換 API を使用することを強くお勧めします。

これにより、急速に変化するモデル環境に対応できる柔軟性が得られます。わずか6か月前に最先端と考えられていたモデルは、すでに過去のものとなっています。また、ChatGPTが2022年にAIブームの火付け役となって以来、OpenAIのAPIインターフェースは、アプリとLLMを接続するための事実上の標準となっています。

このアプローチは、利用可能なあらゆるLLMを活用してアプリケーションを構築できることも意味します。例えば、ノートブックのLlama.cppでMistral 7Bを使ってビルドを開始し、本番環境にデプロイする準備ができたら、Mistral AIのAPIサーバーに切り替えることができます。特定のモデル、推論エンジン、またはAPIプロバイダーに縛られることはありません。

クラウドベースの推論サービスといえば、AI導入をスケールアップする上で、これは通常、設備投資を最小限に抑えた最も効率的な方法です。管理するハードウェアも、設定するモデルも不要で、アプリをアクセスするためのAPIだけが必要です。

主要なモデルビルダーの API 提供に加えて、オープンウェイト モデル向けの推論サービスをサービスとして提供する AI インフラ スタートアップ企業が増えています。

しかし、これらのプロバイダーはすべて同じではありません。SambaNova、Cerebras、Groqなど、推論を高速化するために高級ハードウェアや投機的デコードなどの技術を使用しているプロバイダーもありますが、提供モデルの数は少ないです。

Fireworks AIのような他のAIツールは、Low Rank Adaptation(LoRA)アダプターを用いたカスタム微調整モデルのデプロイをサポートしています。このコンセプトについては、以前に詳しく解説しました。過去2年間でAIエコシステムがいかに多様化してきたかを考えると、どれか1つを選ぶ前に、しっかりと調査することをお勧めします。

自分でやりたい(またはやらなければならない)

プライバシーや規制上の理由、あるいは既に多数のGPUサーバーを発注済みなど、クラウドベースのアプローチが検討できない場合は、オンプレミスでの導入を検討する必要があります。その場合、状況はすぐに複雑になる可能性があります。まずは、よくある疑問点をいくつかご紹介します。

どのモデルを使用すべきでしょうか?これはユースケースによって異なります。主にカスタマーサービスチャットボットに使用されるモデルは、検索拡張生成やコードアシスタントに使用されるモデルとは要件が異なります。

まだモデルを決定していない場合は、ニーズを満たすモデルが見つかるまで、API プロバイダーと時間をかけて話し合う価値があります。

実際にどれくらいのハードウェアが必要なのでしょうか?これは大きな問題です。GPUは高価で、供給がまだ不足しています。ありがたいことに、モデルを使えば、GPUの実行に必要なハードウェアについて多くの情報を得ることができます。

より大きなモデルには、当然のことながらより多くのハードウェアが必要になります。しかし、どれくらい増えるのでしょうか?パラメータ数(10億単位)に2GBを掛けることで、必要な最小GPUメモリの大まかな見積もりが得られます。

例えば、Llama 4 Maverickのようなモデルを実行したい場合、重みを保持するためだけでも最低800GBのGPUメモリが必要になります。そのため、最初からNvidia HGX H200、B200、またはAMD MI300Xのマシンを検討することになるでしょう。しかし、Phi 4 14Bのようなマシンで既に良好な結果が得られている場合は、Nvidia L40を2つ搭載するだけで十分かもしれません。

これは16ビット精度で学習されたモデルにのみ適用されることに注意してください。DeepSeek-V3やR1などの8ビットモデルでは、10億パラメータあたりわずか1GBのメモリで済みます。また、量子化などのモデル圧縮技術(品質とサイズを犠牲にする)を活用すれば、10億パラメータあたり512MBまで削減できます。

ただし、これはあくまで下限値に過ぎません。多くの場合、モデルを複数の人に同時に提供する予定であれば、さらに多くのメモリが必要になります。これは、モデルの重みに加えて、キーバリューキャッシュも考慮する必要があるためです。これはモデルの短期記憶のようなもので、追跡する必要があるユーザーや詳細情報が増えるほど、HBMまたはGDDRの予算を増やす必要があります。

Nvidia のサポート マトリックスは、多くの一般的なオープン モデルを実行するために必要な GPU の種類と数に関する一般的なガイダンスを提供しているため、開始するには最適な場所です。

モデルに合わせてハードウェアのサイズを決定したら、冗長性についても検討する必要があります。ビジネス向けのLLMを実行するために単一のGPUノードを構成することは確かに可能ですが、もしそのノードに障害が発生した場合はどうなるでしょうか?そのため、デプロイメントのサイズを決定する際には、フェイルオーバーと負荷分散のためにさらに2つのシステムを検討することになるでしょう。

モデルをどのようにデプロイすればよいでしょうか? LLMを本番環境にデプロイして提供するには、いくつかの方法があります。ベアメタル上で実行し、従来型のロードバランサーで負荷を分散させることもできます。仮想マシンにデプロイすることも、DockerやKubernetesでコンテナを起動してすべてを管理することもできます。

このガイドでは、Kubernetes を使用して LLM を展開する方法について説明します。Kubernetes は、コンテナの作成、ネットワーク、負荷分散を自動化することで、大規模な展開に伴う複雑さの多くをうまく抽象化します。

推論ワークロードを 3 つの GPU ノードに分散して負荷を分散し、クラスター全体の停止やダウンタイムを軽減する方法の例を次に示します。

推論ワークロードを3つのGPUノードに分散し、負荷を分散してクラスター全体の停止やダウンタイムを軽減する方法...画像をクリックすると拡大します

Kubernetesが簡単だと言っているわけではありません。Kubernetes自体に複雑な点がありますが、多くの企業が既に導入し、十分に理解しています。

これが、NVIDIA、Hugging Face、そしてその他の企業が、それぞれのNVIDIA推論マイクロサービス(NIM)と、愛らしい名前のHUGS(Hugging Face Generative AI Services)を備えたコンテナ化環境へと傾倒している理由の一つです。これらのサービスは、一般的なワークロードとデプロイメント向けに事前構成されています。この記事の後半で、これらのサービスの使い方について少し解説します。

どの推論エンジンを使うべきでしょうか?モデル実行用の推論エンジンは豊富にあります。私たちの記事では、Raspberry Piを含むほぼすべてのプラットフォームで動作するOllamaとLlama.cppを頻繁に使用しています。

ただし、大規模なモデルを提供することが目的である場合は、vLLM、TensorRT LLM、SGLang、さらには PyTorch などのライブラリがより頻繁に使用される傾向があります。

このチュートリアルでは、vLLMを使用したモデルのデプロイについて見ていきます。vLLMは幅広い人気モデルをサポートし、Nvidia、AMD、その他のハードウェア間で幅広いサポートと互換性を提供しているためです。ただし、SGLangやTensorRT LLMなどのツールを使用する場合でも、ここで説明する原則の大部分は適用されます。

Kubernetes環境の準備

一般的なKubernetes環境と比較すると、ポッドをGPUと通信させるには、追加のドライバーと依存関係が必要です。AMDハードウェアの場合、設定プロセスはNvidiaの場合とは異なります。

シンプルにするため、K3S をシングルノード構成でデプロイします。基本的な手順はマルチノード環境とほぼ同じですが、各 GPU ワーカーノードで依存関係が満たされていることを確認する必要があり、ストレージ構成に若干の調整が必要になる場合があります。

このガイドでは、簡素化された単一ノードKubernetesクラスタにvLLMをデプロイします。

このガイドでは、簡素化された単一ノードKubernetesクラスタにvLLMをデプロイします。

注:これはコンテナオーケストレーションに関する包括的なガイドではなく、Kubernetesの概念についてある程度の知識があることを前提としています。私たちの目標は、本番環境で運用しやすい方法で推論ワークロードをデプロイするための強固な基盤を提供することです。そのため、GPUアクセラレーション対応のKubernetesノードを構成する手順を順を追って説明しますが、実際の環境とは多少異なる可能性があります。

前提条件

このガイドに必要なものは以下です。

  • サポートされている AMD または Nvidia GPU ボードが少なくとも 1 つ搭載されたサーバーまたはワークステーション。
  • 依存関係を管理しやすいように、Ubuntu 24.04 LTS を新規インストールします。

Nvidiaの依存関係

Nvidia アクセラレーション K3S 環境のセットアップは比較的簡単ですが、いくつかの依存関係が伴います。

まず、CUDAドライバー、ファブリックマネージャー、ヘッドレスサーバードライバーをインストールします。今回の場合、LTSリポジトリで利用可能な最新リリースは570なので、これを使用します。また、ドライバーの問題が発生した場合のデバッグに役立つため、Nvidiaのサーバーユーティリティもインストールします。

sudo apt install -y cuda-drivers-fabricmanager-570 nvidia-headless-570-server nvidia-utils-570-server

次に、Nvidia のコンテナ ランタイム リポジトリを追加し、次のコマンドを実行して最新バージョンをプルダウンし、再起動します。

curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \ && curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \ sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \ sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
sudo apt-get アップデート
sudo apt-get install -y nvidia-container-runtime
sudo 再起動

K3Sの起動

依存関係の大部分が設定されたので、K3Sのデプロイに進むことができます。単一ノードのデプロイの場合は、次のコマンドを実行します。

curl -sfL https://get.k3s.io | sh -

プロセスが完了したら、次のコマンドでノードがマシン上で実行する準備ができているかどうかを確認できます。

k3s kubectl ノードの取得

すべてが正しく動作していれば、次のような画面が表示されます。

名前 ステータス 役割 年齢 バージョン
kube-nv-prod コントロールプレーン、マスターが 3 時間 45 分で準備完了 v1.32.3+k3s1

AMD Instinct ボックスを実行している場合は次のセクションに進むことができますが、Nvidia を使用している場合は、さらにいくつかの調整を行う必要があります。

デフォルトでは、K3S は Nvidia コンテナランタイムがインストールされていることを検出し、それに応じて設定を行います。ただし、 を実行して再度確認することをお勧めしますgrep。すべてが正常に動作していれば、以下のリストが表示されますnvidia-container-runtime

sudo grep nvidia /var/lib/rancher/k3s/agent/etc/containerd/config.toml
sudo systemctl で k3s を再起動します。

GPUデバイスドライバーの展開

K3S をセットアップしたら、Kubernetes にポッドに GPU リソースを割り当てる権限を与えるだけです。そのためには、AMD または Nvidia のデバイスドライバーデーモンをクラスターにデプロイする必要があります。

Nvidia の場合、これは次のコマンドを実行することで実現できます。

kubectl create -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/v0.17.1/deployments/static/nvidia-device-plugin.yml

一方、AMD ユーザーは、次の 2 つのコマンドを実行してドライバーをインストールできます。

kubectl create -f https://raw.githubusercontent.com/ROCm/k8s-device-plugin/master/k8s-ds-amdgpu-dp.yaml
kubectl create -f https://raw.githubusercontent.com/ROCm/k8s-device-plugin/master/k8s-ds-amdgpu-labeller.yaml

注:ここで紹介するコマンドはすべてサーバー上で直接実行できますが、 経由でクラスターにリモートアクセスしたい場合はkubectl、K3S config.yaml ファイルを以下から参照できます。/etc/rancher/k3s/k3s.conf

約 1 分後、次のコマンドを実行して GPU が検出されたかどうかを確認できます。

kubectl ノードの説明

すべてが正しく機能していれば、ヘッダーの下にamd.com/gpu: 1または が表示されます。nvidia.com/gpu: 1Allocatable

これで、GPU ノードのデプロイメントの準備が整い、「vLLM での Gemma 3 4B のデプロイメント(Nvidia または AMD)」または「NIM の使用開始(Nvidia)」に進むことができます。

vLLMでGemma 3 4Bをデプロイする

まず最初に、Nvidia L40S または AMD MI210 クラスのパーツで vLLM を使用して Gemma 3 4B を展開する方法と、展開を調整してより大きな 8 GPU で実行する方法を説明します。

まず、マニフェスト ファイルを見てみましょう。

vllm-openai-gemma.yaml (Nvidia)

apiバージョン: apps/v1
種類: デプロイメント
メタデータ: 名前: vllm-openai ラベル: アプリ: vllm-openai
仕様: レプリカ: 1 セレクタ: matchLabels: アプリ: vllm-openai テンプレート: メタデータ: ラベル: アプリ: vllm-openai 仕様: ランタイムクラス名: nvidia ホストIPC: true コンテナ: - 名前: vllm-openai イメージ: vllm/vllm-openai:latest 引数: - "--model" - "google/gemma-3-4b-it" - "--served-model-name" - "Gemma 3 4B" - "--disable-log-requests" - "-tp" - "1" - "--max-num-seqs" - "8" #- "--max_num_batched_tokens" #- "16000" - "--max_model_len" - "16000" - "--api-key" - "$(API_KEY)" ポート: - コンテナポート: 8000 環境: - 名前: API_KEY valueFrom: secretKeyRef: name: vllm-api-key key: API_KEY - name: HUGGING_FACE_HUB_TOKEN valueFrom: secretKeyRef: name: hf-token key: HUGGING_FACE_HUB_TOKEN volumeMounts: - name: huggingface-cache mountPath: /root/.cache/huggingface - name: shm mountPath: /dev/shm volumes: - name: huggingface-cache hostPath: path: /root/.cache/huggingface type: Directory - name: shm emptyDir: medium: Memory sizeLimit: "10Gi" resources: limits: nvidia.com/gpu: 1 cpu: "12" memory: 20G requests: nvidia.com/gpu: 1 cpu: "8" memory: 10G

マニフェストとしては、これはかなり標準的なものです。単一のNvidia GPU上でvLLMでGemma3 4Bモデルを実行する単一のポッドを起動します。以下にAMD固有のマニフェストを記載していますが、基本的な概念はどちらにも当てはまります。

そうは言っても、後ほど説明する vLLM の引数以外にも、強調する価値のある要素がいくつかあります。

レプリカ数:この数によって、replicasデプロイするモデルのインスタンス数が決まります。十分なGPUがあれば、vLLMの複数のインスタンスを単一のサーバーに負荷分散することも可能です。Gemma 3 4Bのような小規模なモデルの場合、AMDは実際にこれを推奨しています。

リソース:各ポッドに割り当てるCPU、GPU、システムメモリの量を定義します。モデルのサイズに応じて調整する必要があります。

LLMが単一のGPUに収まらない場合は、要求するGPUの数を増やす必要があります。例えば、8つのGPUを搭載したH200またはMI300XマシンでDeepSeek R1を実行したい場合は、GPUlimitとGPUのrequest両方を8に設定します。

vLLM 構成

さて、vLLMの設定に移りましょう。マニフェストからわかるように、モデルの実行方法を指定する引数をvLLMにいくつか渡しています。モデルの場所(この場合はHugging Faceから取得)の設定、アドバタイズされたモデル名、ログリクエストを無効にするフラグ、そして後ほどKubernetesシークレット経由で渡すAPIキーなど、いくつかは必須です。

残りは、お使いのハードウェアとユースケースに大きく依存します。それぞれ詳しく見ていきましょう。

tensor-parallel-size:テンソル並列処理により、モデルの重みと計算負荷の両方を複数の GPU に分散できます。

この数値は、通常、上記のセクションで説明したGPUの数と一致する必要がありますresources。今回の場合、シングルGPUノードでデモを行っているため、この1数値は に設定され、実質的に無効になります。

max-num-seqs: vLLM が 1 回のバッチで処理するプロンプトまたはリクエスト数の上限を設定します。つまり、これを 8 に設定すると、vLLM は最大 8 つの同時リクエストを一度に処理します。

これを高い数値に設定すると計算効率は上がりますが、メモリ消費量が増え、応答のストリーミングが開始されるまでの待機時間が長くなるというトレードオフが伴います。

したがって、LLM が特定の瞬間に少数のリクエストを処理することがわかっている場合は、レイテンシとメモリ消費を減らすために、この値を低く設定する方が実際にはよい場合があります。

max_num_batched_tokens:と同様に動作します--max-num-seqsが、同時リクエストではなく、vLLM が一度に処理するトークンの最大数を制限します。

ここでの適切な設定は、レイテンシを最適化するのか、スループットを最適化するのかによって異なります。

バッチサイズが小さいほどシステムへの計算負荷は大きくなりますが、メモリ消費量とレイテンシは減少します。一方、バッチサイズが大きいほど一度に処理できるトークンの数が増え、より多くのユーザーにサービスを提供できるようになりますが、待機時間が長くなる可能性があります。

これを設定する方法がわからない場合は、実際に構成から省略することができ、vLLM は利用可能なリソースに基づいてバッチ サイズを自動的に調整します。

max_model_len:これは、各シーケンスが追跡する必要があるトークンの最大数を定義し、前に設定したものと連動します--max_num_seqs

これはワークベンチのようなものだと考えてください。--max_model_lenは各ワークベンチの大きさ(というか、ワークベンチにできるサイズ)を表し、 は--max_num_seqs特定の時点でユーザーが使用できるワークベンチの数を表します。与えられたスペース(メモリ)に対して、大きなワークベンチを少数用意することも、小さなワークベンチを大量に用意することもできます。

vLLMはデフォルトで、この値をモデルがサポートする最大のコンテキストウィンドウに設定します。古いモデルではこの値は通常は小さかったのですが、最近ではコンテキストウィンドウが128,000トークンを超えることが日常的にあり、中には100万トークンを超えるものもあります。これらのトークンは大量のメモリを消費する可能性があるため、この--max_model_len値をより小さい値に設定することが必要になる場合や、場合によってはより望ましい場合もあります。

以下の図は、これらのパラメータがメモリ要件にどのように影響するかを示しています。

以下は、max_num_batch_tokens、max_model_len、max_num_seqsがGPUメモリにどのような影響を与えるかを示した図です。

max_num_batch_tokens、max_model_len、max_num_seqs が GPU メモリに与える影響

vllm-openai-gemma.yaml (AMD)

前述したように、AMD Instinct アクセラレータにワークロードを展開する場合、マニフェスト ファイルは多少異なります。

apiバージョン: apps/v1
種類: デプロイメント
メタデータ: 名前: vllm-openai
仕様: レプリカ: 1 セレクタ: matchLabels: アプリ: vllm-openai テンプレート: メタデータ: ラベル: アプリ: vllm-openai 仕様: hostIPC: true コンテナ: - 名前: vllm-openai イメージ: rocm/vllm:instinct_main セキュリティコンテキスト: seccompProfile: タイプ: 制限なし 機能: 追加: - SYS_PTRACE コマンド: ["/bin/sh", "-c"] 引数: - > vllm serve google/gemma-3-4b-it \ --served-model-name 'Gemma 3 4B' \ --disable-log-requests \ -tp 1 \ --max-num-seqs 8 \ --max_model_len 16000 \ --api-key $(API_KEY) ポート: - コンテナポート: 8000 環境: - 名前: VLLM_USE_TRITON_FLASH_ATTN 値: "0" - 名前: API_KEY valueFrom: secretKeyRef: 名前: vllm-api-key キー: API_KEY - 名前: HUGGING_FACE_HUB_TOKEN valueFrom: secretKeyRef: 名前: hf-token キー: HUGGING_FACE_HUB_TOKEN volumeMounts: - 名前: huggingface-cache mountPath: /root/.cache/huggingface - 名前: shm mountPath: /dev/shm resources: limits: amd.com/gpu: "1" cpu: "12" memory: "20Gi" requests: amd.com/gpu: "1" cpu: "8" memory: "10Gi" volumes: - 名前: huggingface-cache hostPath: path: /home/tobiasmann/.cache/huggingface type: Directory - 名前: shm emptyDir: medium: Memory sizeLimit: "10Gi"

注:このマニフェストは、Instinct アクセラレータ上での vLLM 実行に特化しています。W7900 などの AMD ワークステーションカードでテストしたい場合は、こちらのガイドに従ってソースから互換性のある vLLM コンテナを構築し、任意のコンテナレジストリにプッシュする必要があります。

vLLMのチューニング

Gemma 3 4B は非常に小さなモデルであり、モデルの重みをネイティブ BF16 解像度に適合させるには 8GB 強の vRAM が必要ですが、先ほど見たマニフェストを 24GB Nvidia L4 で使用しようとすると、メモリ不足 (OOM) エラーが発生する可能性があります。

これに該当する場合は、、、、またはこれら 3 つの組み合わせのいずれかを下げる必要が--max_num_seqあり--max_model_lenます--max_num_batch_tokens

これらのパラメータはパフォーマンスとユーザー エクスペリエンスに大きな影響を与える可能性があるため、2 つの異なるシナリオを見て、パラメータをどのように調整するかを確認してみましょう。

シナリオ1:企業概要作成アシスタント

要約アシスタントの設定方法の図解はこちらです

要約アシスタントの設定方法

12 人のチーム向けに、大規模なドキュメントの検索と要約を支援する genAI アプリケーションを構築しているとします。2 人以上が同時に要約タスクを実行する可能性は非常に低いため、--max_num_seqs2 程度に設定できます。

ただし、これらのドキュメントは非常に大きいため、ドキュメントがコンテキストウィンドウ内に収まり、途中で切れてしまうことのないように、--max_model_lenと を十分に大きく設定する必要があります。最大のドキュメントが約15,000語の場合、余裕を持たせるために を32,000語に設定するとよいでしょう。トークンは単語だけでなく句読点も表すことに注意してください。--max_num_batch_tokens--max_model_len

直感的には、32,000トークンのシーケンスが2つある場合、64,000に設定したいと考えるかもしれません--max_num_batch_tokens。しかし、すべてのドキュメントが15,000語以上になるわけではないため、これは最悪のシナリオです。例えば、一方のユーザーが10,000語のドキュメントを要約し、もう一方のユーザーが3,000語のドキュメントを要約した場合、上限に近づくことはまずないでしょう。ありがたいことに、vLLMはこのパラメータ設定における推測作業を大幅に--max_num_batch_tokens軽減します。未設定のままにしておくと、利用可能なメモリに基づいて自動的に適切なサイズに調整されます。

シナリオ2: カスタマーサービスチャットボット

カスタマーサービスチャットボットの場合、同時ユーザー数を最大化するために、より多くの小さなシーケンスを優先する場合があります。

カスタマーサービスチャットボットの場合、同時ユーザー数を最大化するために、より多くの小さなシーケンスを優先します。

さて、ユーザーが製品について理解を深めたり、よくある課題を克服したりするためのカスタマーサービスチャットボットを構築するとしましょう。パラメータは、要約シナリオとはかなり異なります。

まず、プロンプトと応答ははるかに短くなりますが、同時に多くのユーザーにサービスを提供する可能性が高くなります。この場合、--max_num_seqs16、32、あるいはそれ以上の大きな数値を設定する一方で、--max_model_len1,024や2,048といった小さな数値を設定するのが合理的かもしれません。

ここでも、vLLM--max_num_batch_tokensに設定方法を判断させることができます。

ベンチマーク

具体的なユースケースに応じて、全体的なスループット、最初のトークンまでの時間 (チャットボットが応答を開始するまでユーザーが待機する時間)、または 2 番目のトークンのレイテンシ (回答が生成される速さ) の望ましい組み合わせを実現する構成が見つかるまで、いくつかの異なる構成をベンチマークすることが賢明です。

最終準備: vLLMマニフェストを好みに合わせて調整したら、vLLMを起動する作業に移ります。まずは2つのシークレットを生成する必要があります。1つはHugging Faceトークン用です。Gemma 3はゲート式モデルなので、リポジトリページへのアクセスを事前にリクエストすることを忘れないでください。もう1つは、後でvLLM APIサーバーにアクセスするために使用します。

これは、トークンとキーを入れ替えHUGGING_FACE_TOKEN_HEREて次の 2 つのコマンドを実行することで実現できます。TOP_SECRET_KEY_HERE

kubectl でシークレット汎用 hf-token を作成します --from-literal=HUGGING_FACE_HUB_TOKEN=HUGGING_FACE_TOKEN_HERE
kubectl でシークレット汎用 vllm-api-key を作成します --from-literal=API_KEY=TOP_SECRET_KEY_HERE

最後に、Hugging Face のキャッシュ ディレクトリが存在することを確認します。

mkdir -p /root/.cache/huggingface

注:ここではシンプルにするためにバインドマウントを使用していますが、NFS、永続ボリュームストア、またはその他のストレージインターフェースを使用して、Hugging Face のキャッシュされた Safetensor ファイルを維持することも可能です。また、このバインドマウントを完全に削除することも可能です。ただし、その場合、vLLM は新しいポッドが起動されるたびにファイルを再ダウンロードする必要があることに注意してください。

vLLMの起動

これで準備が整いました。次のコマンドを実行して、vLLM で Gemma 3 4B を起動できます。

kubectl apply -f vllm-openai-gemma.yaml

get pods次に、 でコマンドを実行してデプロイメントを確認しますkubectl

kubectl ポッドを取得する

「containerCreating」が表示されるはずですvllm-openai-...。「running」と表示されたら、vLLM ログをチェックして問題がないか確認できます。

kubectl ログ -l app=vllm-openai -f

数分後、次のように表示されます。

情報: アプリケーションの起動が完了しました。

イングレスとロードバランシング

サーバーが起動したら、他のコンテナデプロイメントと同様に、Kubernetes Ingressとロードバランサーを設定できます。設定方法は、Kubernetes環境、使用するIngressコントローラーとロードバランサー、そしてセキュリティポリシーによって異なります。

ここでの基本的な考え方は、Kubernetes が API アドレスを公開し、Kubernetes が利用可能なすべての GPU ノード間で負荷を自動的に分散するというものです。

ここまでの手順を踏んでいて、vLLM サーバーが意図したとおりに動作していることを確認したいだけなら、以下のコマンドを実行して、手軽な Ingress サービスを立ち上げることができます。ただし、これを再現する場合は、フロントエンドアプリケーションが標準 HTTP 経由で提供されるため、ネットワークの DMZ の背後にある同じサブネット上で実行されている必要があることに注意してください。これらの注意事項を踏まえて、早速始めましょう。

まず、vllm-openai-svc.yaml次の内容を含む という別の YAML ファイルを作成して、新しい ClusterIP サービスを作成します。

apiバージョン: v1
種類: サービス
メタデータ: 名前: vllm-openai-svc 名前空間: デフォルト
仕様: タイプ: ClusterIP セレクタ: アプリ: vllm-openai ポート: - ポート: 8000 ターゲットポート: 8000

次に、サービスを作成するには、次のコマンドを実行します。

kubectl apply -f vllm-openai-svc.yaml

次に、Ingress 構成を読み込み、vllm-openai-ingressroute.yaml次の内容を含む という別の YAML ファイルを作成し、YOUR_DOMAIN_NAME_HERE使用する予定のドメインに置き換えます。

apiバージョン: traefik.io/v1alpha1
種類: IngressRoute
メタデータ: 名前: vllm-openai 名前空間: デフォルト
spec: entryPoints: - web routes: - match: Host(YOUR_DOMAIN_NAME_HERE) kind: Rule services: - name: vllm-openai-svc port: 8000 sticky: cookie: name: VLLMSESSION secure: true httpOnly: true

次に、次のコマンドを実行してこれを適用します。

kubectl apply -f vllm-openai-ingressroute.yaml

ローカルDNSサーバーを更新して、先ほど設定したドメインを指すようにすることができます。/etc/hostsの変更

ローカル DNS サーバーにアクセスできない場合 (通常はルーター設定の一部として、またはスタンドアロン サーバーとして処理されます)、/etc/hostsLinux でローカル マシンのファイルを変更して、ドメインを Kuberentes ノードの IP にポイントすることができます。

sudo ナノ /etc/hosts

以下を追加して保存し、終了します。

NODE_IP YOUR_DOMAIN_NAME_HERE YOUR_DOMAIN_NAME_HERE

テストしてみる:

すべての設定が完了したら、次のコマンドを実行してサーバーが実行中であることをテストできます。

エクスポート VLLM_API_KEY="TOP_SECRET_KEY_HERE"
curl -i http://api.local.rambler.ink/v1/models \ -H "認証: Bearer $VLLM_API_KEY"

すべてがうまくいけば、次のようなものが表示されるはずです:

HTTP/1.1 200 OK
コンテンツの長さ: 481
コンテンツタイプ: application/json
日付: 2025年4月16日(水) 20:06:56 GMT
サーバー: uvicorn
Set-Cookie: VLLMSESSION=48de0c44ee42ce61; パス=/; HttpOnly;セキュア {"object":"list","data":[{"id":"Gemma 3 4B","object":"model","created":1744834016,"owned_by":"vllm","root":"google/gemma-3-4b-it","parent":null,"max_model_len":16000,"permission":[{"id":"modelperm-e17493c83c8047c1b8ce3b082e4c4a61","object":"model_permission","created":1744834016,"allow_create_engine":false,"allow_sampling":true,"allow_logprobs":true,"allow_search_indices":false,"allow_view":true,"allow_fine_tuning":false,"organization":"*","group":null,"is_blocking":false}]}]}

NIM を使い始める

最適なスループットやレイテンシを実現するために、操作しなければならないレバーやノブの数が膨大であることは、Nvidia、Hugging Face などが、起動して実行するためにほとんどまたはまったく構成を必要としない、あらかじめ準備されたモデル コンテナーに惹かれた理由の 1 つです。

Nvidiaはこれらを略して「推論マイクロサービス(NIM)」と呼んでおり、Hugging Faceはこれらのコンテナの自社バージョンを「Hugs」と呼んでいます。これらのマイクロサービスは無料ではありません。開発環境ではNIMを試すことができますが、本番環境に導入するにはAI Enterpriseライセンスが必要で、GPU1台あたり年間4,500ドル、またはクラウドではGPU1台あたり1時間あたり1ドルかかります。

ただし、すでにライセンス料を支払っている場合は、考える必要はありません。

ここでは NIM の導入の基本について説明しますが、Kubernetes 環境に最適な構成を調整する方法の詳細については、Nvidia のドキュメントを必ず確認してください。

依存関係を取得する

KubernetesクラスターにNIMをデプロイするには、HelmとNvidia GPU Operatorという追加の依存関係が必要です。Helmをインストールするには、次のコマンドを実行します。

curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 \ && chmod 700 get_helm.sh \ && ./get_helm.sh

次に、GPU Operator の Helm リポジトリを追加してインストールします。

helm リポジトリに nvidia を追加 https://helm.ngc.nvidia.com/nvidia \ && helm リポジトリを更新
helm install --wait --generate-name \ -n gpu-operator --create-namespace \ nvidia/gpu-operator \ --version=v25.3.0

NGCリポジトリとAPIキーの追加

NIM をダウンロードする前に、ここの手順に従って NGC API キーを生成し、それを.bashrcまたは.zshファイルに追加する必要があります。

NGC_API_KEY=NGC_API_KEY_HERE をエクスポートします
echo "NGC_API_KEY=VALUE" >> ~/.bashrc

または

echo "NGC_API_KEY=VALUE" をエクスポート >> ~/.zsh

Helmチャートを入手してカスタマイズを追加する

次に、NIM LLM Helmチャートをダウンロードします。バージョン1.7.0を使用していますが、最新バージョンはこちらから入手できます。

helm で https://helm.ngc.nvidia.com/nim/charts/nim-llm-1.7.0.tgz を取得します --username='$oauthtoken' --password=$NGC_API_KEY

次に、Kubernetes クラスターに NGC リポジトリと API キーをシークレットとして追加します。

kubectl でシークレット docker-registry ngc-secret を作成します --docker-server=nvcr.io --docker-username='$oauthtoken' --docker-password=$NGC_API_KEY
kubectl は、シークレット ジェネリック ngc-api --from-literal=NGC_API_KEY=$NGC_API_KEY を作成します。

最後に、デプロイメント用の構成ファイル (この場合は Llama 3.1 8B) を作成し、 として保存しますcustom-values.yaml

イメージ: リポジトリ: "nvcr.io/nim/meta/llama3-8b-instruct" タグ: 1.0.3
モデル: ngcAPIシークレット: ngc-api
永続性: 有効: false
imagePullSecrets: - 名前: ngc-secret

NIMをスピンアップ

helm インストール my-nim nim-llm-1.7.0.tgz -f カスタム値.yaml

数分後、NIM の実行中に表示されるはずです。その後、コンテナ ポートをマシンに転送してテストします。

kubectl ポート転送サービス/my-nim-nim-llm 8000:http-openai

次に、別のシェルで次のコマンドを実行してテストします。

curl -i http://localhost:8000/v1/models

すべてがうまくいけば、次のようなものが表示されます。

HTTP/1.1 200 OK
日付: 2025 年 4 月 17 日木曜日 21:40:52 GMT
サーバー: uvicorn
コンテンツの長さ: 477
コンテンツタイプ: application/json {"object":"list","data":[{"id":"meta/llama3-8b-instruct","object":"model","created":1744926052,"owned_by":"system","root":"meta/llama3-8b-instruct","parent":null,"permission":[{"id":"modelperm-47170d15fee9430eb42deda48f0f17b0","object":"model_permission","created":1744926052,"allow_create_engine":false,"allow_sampling":true,"allow_logprobs":true,"allow_search_indices":false,"allow_view":true,"allow_fine_tuning":false,"organization":"*","group":null,"is_blocking":false}]}]}%

もちろん、以前 vLLM で行ったように適切な Ingress サービスを構成する必要がありますが、これにより、少なくとも NIM を本番環境に展開する方法についての理解が深まるはずです。

まとめ

運用環境で AI ワークロードを拡張するためにどの方法を採用するかに関係なく、回復力とセキュリティを損なうことなく柔軟性を優先することが重要です。

また、推論は AI パズルの重要な要素ではあるものの、数ある要素の 1 つであり、LLM だけではそれほど役に立たないことも注目に値します。

以前に説明したように、効果的な AI ツールを構築するには、微調整、検索拡張生成、そして通常は大量のデータ準備など、複数のテクノロジーとアプローチが必要になる場合があります。

The Registerは、 LLMやその他のAIテクノロジーの活用について、誇大広告ではなく、より深く掘り下げた情報を近日中にお届けする予定です。これらのテクノロジーがどのように連携するのかを、その真髄までお見せしたいと考えています。AIインフラ、ソフトウェア、モデルについて、何か気になる点がありましたら、ぜひ下のコメント欄にお寄せください。®

編集者注: The Registerは、このような記事の裏付けとして、NVIDIAのRTX 6000 Ada世代グラフィックカード、IntelのArc A770 GPU、AMDのRadeon Pro W7900 DSを提供されました。これらのベンダーは、本記事およびその他の記事の内容に一切関与していません。

Discover More