OllamaをKubernetesにデプロイする方法|GPU NodeとHelm ChartでローカルLLMクラスターを本番スケール対応にする手順

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOMELinux技術 リナックスマスター.JP(Linuxマスター.JP)ローカルLLM > OllamaをKubernetesにデプロイする方法|GPU NodeとHelm ChartでローカルLLMクラスターを本番スケール対応にする手順
「DockerでOllamaを動かすのに成功したが、利用者が増えて単一コンテナでは負荷を捌けなくなってきた」
「複数の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にデプロイする方法|GPU NodeとHelm ChartでローカルLLMクラスターを本番スケール対応にする手順

「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

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

`--set driver.enabled=true` はNVIDIAドライバをOperatorが管理する設定です。すでにホストにドライバが手動でインストールされている場合は `false` に切り替えてください。`--wait` フラグで全Podが起動するまでコマンドがブロックします。

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

`nvidia.com/gpu` の数値が表示されればKubernetesがGPUリソースを認識できています。`` のままの場合は、`kubectl logs -n gpu-operator -l app=nvidia-device-plugin-daemonset` でエラーを確認してください。

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

`models:` に指定したモデルはPodの起動時に自動でpullされます。`llama3.3:8b-instruct-q4_K_M` はVRAM 8GB以上のNodeで動作します。モデルの選び方とVRAM目安はローカルLLMモデル比較ガイドで詳しく解説しています。

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

`STATUS: Running` かつ `READY: 1/1` が確認できれば、OllamaのPodが正常に起動しています。Podが `Pending` のままの場合はトラブルシューティング章を参照してください。

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

`STATUS: Bound` であればPVCが正常にバインドされています。`Pending` のままの場合は、指定した `storageClass` が存在するか確認してください。

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

PVCが機能していれば、Pod再作成後もモデルの再ダウンロードは不要です。一方、`helm upgrade` 時に誤って `persistentVolume.enabled: false` にするとPVCが削除されるため注意してください。

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",...}]}

`proxy-read-timeout` と `proxy-send-timeout` を3600秒に設定しているのは、LLMの応答生成が数十秒かかる場合にIngressがタイムアウトするのを防ぐためです。デフォルトの60秒のままでは長い回答でエラーになります。社内ネットワーク外への公開は避け、必要であればBasic認証またはOIDCをIngressに追加してください。

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

`nvidia-smi` の出力でGPUメモリが使用されていれば、OllamaがGPU推論を行っています。`values.yaml` の `tolerations` と `nodeSelector` が正しく設定されていれば、CPU Nodeへの誤スケジュールは防げます。

よくあるエラーとトラブルシューティング

Kubernetes環境でのOllamaデプロイでは、以下のエラーが頻出します。事前に把握しておくことで、原因特定の時間を短縮できます。

1. PodがPendingのまま動かない

`kubectl describe pod -n ollama ` のEvents欄を確認します。典型的な原因は以下の3パターンです。

・`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

`storageClass` が `standard` 以外の環境では、`kubectl get storageclass` で確認した名前を `values.yaml` の `persistentVolume.storageClass` に反映してください。

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-operatordriver.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.yamlmodels:でモデルを事前指定して自動pull
永続化確認kubectl get pvc -n ollamaSTATUS: Boundが必須
外部公開kubectl apply -f ollama-ingress.yamlproxy-read-timeout: "3600"を必ず設定
スケジューリングnodeSelector: accelerator: nvidia-gpu + tolerationsCPU 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ハンズオン形式で実施しています。

>> ローカルAIマスターセミナーの詳細を確認する
ローカルLLMの構築・運用に関する関連記事もあわせて参考にしてください。

Ubuntu ServerでローカルLLMを構築する方法|Ollamaで機密データを外に出さず業務AIを動かす完全ガイド
社内でChatGPTが使えないときの代替手段|機密データを守るローカルLLMという選択肢
ローカルLLMのモデルを比較する方法|Llama3.3・Mistral・Gemma・Phi-4をUbuntuで使い分けるポイント

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録
宮崎 智広

この記事を書いた人

宮崎 智広(みやざき ともひろ)

株式会社イーネットマーキュリー代表。現役のLinuxサーバー管理者として20年以上の実務経験を持ち、これまでに累計3,100名以上のエンジニアを指導してきたLinux教育のプロフェッショナル。「現場で本当に使える技術」を体系的に伝えることをモットーに、実践型のLinuxセミナーの開催や無料マニュアルの配布を通じてLinux人材の育成に取り組んでいる。

趣味は、キャンプにカメラ、トラウト釣り。好きな食べ物は、ラーメンにお酒。休肝日が作れない、酒量を減らせないのが悩み。最近、ドラマ「フライトエンジェル」を観て涙腺が崩壊しました。