「複数のGPU Nodeに分散させて安定運用したいが、Kubernetesへの移行手順がわからない」
そんな悩みを抱えるLinuxインフラエンジニアは多いはずです。この記事では、OllamaをKubernetesクラスターへHelmでデプロイし、NVIDIA GPU Operatorによるリソース認識・PersistentVolumeによるモデル永続化・Ingressを使った外部公開まで、本番スケールのローカルLLM環境を一連の手順で構築します。Ubuntu ServerでのOllama単体構築が完了している前提で、コンテナオーケストレーション環境への移行ステップを実例ベースで解説します。
この記事のポイント
・NVIDIA GPU OperatorでKubernetesにGPUリソースを認識させてからHelm install ollamaを実行する
・persistentVolume.enabled: trueでモデルデータを永続化し、Pod再起動後の再ダウンロードを防ぐ
・tolerations+nodeSelectorでGPU NodeだけにOllamaがスケジュールされる設定が必須
・IngressのProxy-Read-Timeoutを3600秒以上に設定しないとLLM応答中にタイムアウトが発生する
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
OllamaをKubernetesで動かす利点と前提条件
Docker単体でOllamaを運用する場合、チームの人数が増えると1台のサーバーでリクエストを捌きながらモデルをロードし続けるのが難しくなります。現場で聞いた話では、10名規模でDockerを使い始めたチームが、利用者が20名を超えたあたりからレイテンシの増加が目立ちはじめ、Kubernetes移行でPodを3つに水平展開して解消したケースがあります。Kubernetesを使う主な利点は3つあります。宣言的な設定による再現性の確保、GPU Nodeへの自動スケジューリング、そしてPodのセルフヒーリング(異常終了時の自動再起動)です。一度Helm Chartで設定ファイルを整備すれば、開発・ステージング・本番の環境差を最小化できます。
1. 前提条件を確認する
この記事で想定する環境は以下の通りです。・Kubernetes 1.28以上(kubeadmまたはマネージドK8s)
・NVIDIA GPU搭載Node(CUDA 12.x対応ドライバ)
・kubectl・Helm 3.x がインストール済み
・動的PV(StorageClass)が使えるストレージ環境
Kubernetesクラスター自体の構築はこの記事のスコープ外とし、既存クラスターへのOllamaデプロイに絞って解説します。GPUドライバの確認は `nvidia-smi` コマンドで行ってください。
NVIDIA GPU OperatorをKubernetesクラスターに導入する
GPUを使うPodをKubernetesで動かすには、NVIDIA GPU Operatorが必要です。これはNVIDIAが提供するOperatorで、ドライバ・CUDA toolkit・コンテナランタイムのプラグインをNode上に自動設定してくれます。手作業でNodeごとにcuda-toolkit をインストールする旧来の方法に比べて、はるかに管理が楽になります。1. HelmリポジトリにNVIDIAを追加してOperatorをインストールする
# NVIDIA GPU Operatorのリポジトリを追加 $ helm repo add nvidia https://helm.ngc.nvidia.com/nvidia $ helm repo update # ネームスペースを作成してインストール $ kubectl create namespace gpu-operator $ helm install gpu-operator nvidia/gpu-operator \ --namespace gpu-operator \ --set driver.enabled=true \ --set toolkit.enabled=true \ --wait
2. GPUリソースが認識されているか確認する
$ kubectl get nodes -o=custom-columns=\ NAME:.metadata.name,\ GPU:.status.allocatable."nvidia\.com/gpu" # 出力例 NAME GPU k8s-node-01 1 k8s-node-02 2
Helm ChartでOllamaをデプロイする基本設定
OllamaにはコミュニティメンテナンスのHelm Chartが公開されています。`otwld/ollama-helm` がよく使われており、Deployment・Service・PVCを一括で生成できます。自前でマニフェストを書くよりも設定の見通しがよく、アップグレードも `helm upgrade` 一発です。1. リポジトリを追加してvalues.yamlを取り出す
$ helm repo add ollama-helm https://otwld.github.io/ollama-helm/ $ helm repo update # デフォルト値をローカルに書き出す $ helm show values ollama-helm/ollama > ollama-values.yaml
2. values.yamlにGPUとモデルの設定を記述する
取り出した `ollama-values.yaml` を編集します。最低限設定すべき箇所は GPU・モデル・ストレージの3点です。# ollama-values.yaml(主要設定抜粋) ollama: gpu: enabled: true type: nvidia number: 1 models: - llama3.3:8b-instruct-q4_K_M persistentVolume: enabled: true size: 50Gi storageClass: "standard" # kubectl get storageclass で確認した名前に変更 resources: requests: nvidia.com/gpu: 1 limits: nvidia.com/gpu: 1 tolerations: - key: "nvidia.com/gpu" operator: "Exists" effect: "NoSchedule" nodeSelector: accelerator: nvidia-gpu
3. OllamaをKubernetesにデプロイして起動を確認する
$ kubectl create namespace ollama $ helm install ollama ollama-helm/ollama \ --namespace ollama \ --values ollama-values.yaml \ --wait # Podの状態を確認 $ kubectl get pods -n ollama # 出力例 NAME READY STATUS RESTARTS AGE ollama-6d8c7f9b4-xkqzm 1/1 Running 0 2m30s
PersistentVolumeでモデルデータを永続化する
Podは再起動のたびにコンテナ内のデータが消えます。OllamaのモデルデータはGB単位になるため、毎回ダウンロードし直すのは現実的ではありません。PersistentVolumeClaim(PVC)で永続化しておくことで、Pod再作成後も即座に利用を再開できます。1. PVCの状態を確認する
$ kubectl get pvc -n ollama # 出力例 NAME STATUS VOLUME CAPACITY ACCESS MODES ollama Bound pvc-4e2a3c1b-9a12-4f8d-b2e1-3a4c5d6e7f89 50Gi RWO
2. Pod再起動後もモデルが残っているか検証する
# Podを手動削除(Deploymentが自動で再作成する) $ kubectl delete pod -n ollama -l app.kubernetes.io/name=ollama # 新しいPodの起動を待つ $ kubectl get pods -n ollama -w # Pod内でモデル一覧を確認 $ kubectl exec -n ollama deploy/ollama -- ollama list # 出力例(再起動後もモデルが残っている) NAME ID SIZE MODIFIED llama3.3:8b-instruct-q4_K_M a1b2c3d4e5f6 4.9 GB 2 minutes ago
ServiceとIngressで外部からアクセスできるようにする
チームメンバーがOllamaのAPIを利用できるようにするには、ServiceとIngressの設定が必要です。Helm Chartのデフォルトでは `ClusterIP` のServiceが作成されるため、クラスター外からアクセスするにはIngressが別途必要になります。1. Serviceの現在の設定を確認する
$ kubectl get svc -n ollama # 出力例 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE ollama ClusterIP 10.96.123.45
11434/TCP 5m
2. IngressでHTTP外部アクセスを設定する
以下の内容を `ollama-ingress.yaml` として保存します。# ollama-ingress.yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: ollama-ingress namespace: ollama annotations: nginx.ingress.kubernetes.io/proxy-read-timeout: "3600" nginx.ingress.kubernetes.io/proxy-send-timeout: "3600" nginx.ingress.kubernetes.io/client-body-buffer-size: "10m" spec: ingressClassName: nginx rules: - host: ollama.internal.example.com http: paths: - path: / pathType: Prefix backend: service: name: ollama port: number: 11434
$ kubectl apply -f ollama-ingress.yaml # Ingressを確認 $ kubectl get ingress -n ollama # 外部からAPIにアクセスして動作確認 $ curl http://ollama.internal.example.com/api/tags {"models":[{"name":"llama3.3:8b-instruct-q4_K_M",...}]}
GPU Nodeへのスケジューリングを確実にする設定
GPU搭載NodeとCPUのみのNodeが混在するクラスターでは、OllamaのPodが誤ってCPU NodeにスケジュールされるとGPUが使えないまま起動します。`tolerations` と `nodeSelector` で必ずGPU Nodeを指定してください。1. GPU NodeにTaintとLabelを付与する
# GPU NodeにLabelを付与 $ kubectl label node k8s-node-01 accelerator=nvidia-gpu # GPU NodeにTaintを付与(GPU Tolerationがないと乗れなくなる) $ kubectl taint node k8s-node-01 nvidia.com/gpu=true:NoSchedule # 設定を確認 $ kubectl describe node k8s-node-01 | grep -A5 "Taints\|Labels"
2. OllamaのPodがGPU Nodeに乗っているか確認する
$ kubectl get pod -n ollama -o wide # 出力例(k8s-node-01=GPU搭載Node) NAME READY STATUS NODE AGE ollama-6d8c7f9b4-xkqzm 1/1 Running k8s-node-01 8m # Pod内からGPU使用状況を確認 $ kubectl exec -n ollama deploy/ollama \ -- nvidia-smi --query-gpu=name,memory.used,memory.total --format=csv,noheader # 出力例 NVIDIA A100-SXM4-40GB, 5320 MiB, 40536 MiB
よくあるエラーとトラブルシューティング
Kubernetes環境でのOllamaデプロイでは、以下のエラーが頻出します。事前に把握しておくことで、原因特定の時間を短縮できます。1. PodがPendingのまま動かない
`kubectl describe pod -n ollama・`Insufficient nvidia.com/gpu` → GPU Nodeが不足しているかGPU Operatorが未導入
・`didn't match node selector` → `nodeSelector` のラベルがNodeに付いていない
・`had untolerated taint` → Podの `tolerations` とNodeのTaintが一致していない
2. PVCがPendingのままBoundにならない
$ kubectl describe pvc -n ollama ollama # Eventsに表示される典型的なエラー no persistent volumes available for this claim and no storage class is set # 利用可能なStorageClassを確認 $ kubectl get storageclass # 出力例 NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE standard (default) rancher.io/local-path Delete WaitForFirstConsumer
3. IngressでAPIタイムアウトが発生する
LLMの応答生成は長い回答で数十秒かかります。Ingressの `proxy-read-timeout` がデフォルト(60秒)のままだと生成途中でタイムアウトします。前述のIngress設定で3600秒に延ばすか、ストリーミングAPIに切り替えてください。4. helm upgradeでモデルデータが消えた
`helm upgrade` 時に `--reset-values` を使うか `values.yaml` から `persistentVolume.enabled` の行を削除すると、PVCが削除されてモデルが消えます。アップグレードは必ず `--values ollama-values.yaml` を明示して実行し、`persistentVolume.enabled: true` が維持されているか事前に確認してください。まとめ
OllamaをKubernetesにデプロイするための主要な手順と設定ポイントを整理します。| 手順 | コマンド・設定 | ポイント |
|---|---|---|
| GPU認識 | helm install gpu-operator nvidia/gpu-operator | driver.enabled=trueでOperator管理にする |
| GPU確認 | kubectl get nodes -o=custom-columns=NAME:.metadata.name,GPU:.status.allocatable."nvidia\.com/gpu" | 数値が表示されればOK、noneならOperator確認 |
| デプロイ | helm install ollama ollama-helm/ollama --values ollama-values.yaml | models:でモデルを事前指定して自動pull |
| 永続化確認 | kubectl get pvc -n ollama | STATUS: Boundが必須 |
| 外部公開 | kubectl apply -f ollama-ingress.yaml | proxy-read-timeout: "3600"を必ず設定 |
| スケジューリング | nodeSelector: accelerator: nvidia-gpu + tolerations | CPU Nodeへの誤スケジュール防止 |
| 動作確認 | kubectl exec -n ollama deploy/ollama -- ollama list | モデル一覧とGPUメモリ使用量を確認 |
DockerによるOllama単体運用から、Kubernetesによるチームスケール対応への移行は、利用者が20名を超えてレイテンシが気になり始めた段階で検討する価値があります。Helm Chartを使った宣言的な設定は環境の再現性を高め、本番運用の安定性につながります。
社内でChatGPTが使えないときにローカルLLMを選ぶ判断をした後、チームへの安定提供を実現するインフラとしてKubernetesは有力な選択肢です。Ollamaの可用性を高め、情シス担当者がSLA要件を説明しやすくなる構成でもあります。
ローカルLLMのKubernetes運用を2日間のハンズオンで体験する
Helmデプロイ・GPU Operator設定・PersistentVolume構成を実機のGPU環境で手を動かしながら習得したい方向けに、「ローカルAIマスターセミナー」を開催しています。
少人数(最大8名)ZOOMハンズオン形式で実施しています。
・Ubuntu ServerでローカルLLMを構築する方法|Ollamaで機密データを外に出さず業務AIを動かす完全ガイド
・社内でChatGPTが使えないときの代替手段|機密データを守るローカルLLMという選択肢
・ローカルLLMのモデルを比較する方法|Llama3.3・Mistral・Gemma・Phi-4をUbuntuで使い分けるポイント
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:OllamaとJupyterLabを連携させる方法|ノートブック上でローカルLLMをPythonから対話利用してAI実験環境を構築する手順
- この記事の属するカテゴリ:ローカルLLMへ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます