先日初めて知ったのですが、Kubernetes上で生成AIモデル(LLM)による推論システムを構築する際に便利なKubernetes Operatorがあるようです。
AI Inference Operator for Kubernetes. The easiest way to serve ML models in production. Supports VLMs, LLMs, embeddings, and speech-to-text.
比較的新しいプロダクトということもあって、まだ日本語記事がほぼ無いのと、AIに聞いてもプロダクト概要程度しかわからないようなので、自身で調査・構築してみることにしました。
(※ Kubernetes自体の知識についてはここでは前提として省略します)
2025年7月現在、KubeAIはCNCFのSandboxプロジェクトとして提案されており、まだ非常に開発が活発な段階にあるので公式ドキュメントやインストール方法は変更される可能性が高いかもしれません。
KubeAIとは
KubeAIは、高性能なLLM推論ライブラリ/サーバ実装であるvLLMをKubernetes上にデプロイ・運用するためのKubernetes Operatorです。vLLMの機能をKubernetesのオーケストレーション能力と組み合わせることで、LLMの推論サービスを大規模かつ効率的に提供することを目指して開発されています。vLLM対応をアピールしていますが、他にはOllamaサーバもサポートされているようです。個人でローカルLLM使う時にはOllammaを使うことはそこそこあるかもしれませんが、プロダクション用途だとvLLMの方が採用されるのではないでしょうか。
KubeAIはKubernetes Operatorとして提供されているので、モデルサーバーとしてのPod構成やライフサイクル(デプロイ、スケーリング、アップグレード、ヘルスチェックなど)をk8sのスケジューラと各種コントローラが全て管理してくれます。さらに、ロードバランシング機能はKubeAI固有の工夫が入っているようで、標準のKubernetes Serviceのロードバランシング機能は、vLLMのようにKVキャッシュの状態によってパフォーマンスが大きく左右されるステートフルなモデルには適していません。KubeAIでは推論パフォーマンスを向上させるために最適化されたロードバランシング機能を提供する独自のプロキシが組み込まれているそうです↓
また、NVIDIA GPUだけでなくAMDやIntelのGPU、AWS Trainiumなどマルチハードウェア環境で動作します。最近はAMDのMI300シリーズは有力視されているので期待できますね。もちろんCPU環境でも動くので、GPUサーバが手元に無くても開発環境や動作確認用途ではCPUモードを使うという選択ができます。
アプリケーション統合の文脈だと、KubeAIはOpenAI API互換性(/v1/chat/completions
や/v1/embeddings
等のエンドポイント)を提供しています。これによりOpenAI APIを使用するように構築された既存のアプリケーションを、Kubernetes上でホストされている独自のモデルに簡単に切り替えることができます。とはいってもvLLM本体にOpenAI API互換があるのでKubeAI固有のアピールポイントではないですが、OpenAI API互換があるかどうかはアプリケーション開発者にとっては重要かと思います。
vLLM
vLLMの紹介も軽くしておきます。LLM推論サーバとしてはONNX RuntimeやNVIDIAのTriton Inference Serverなども有名で実績がありますが、vLLMはPagedAttensionによる効率的なキャッシュ機構を備えており性能面において特に優秀で、それだけでなくOpenAI API互換やHuggingFace Modelsとの連携機能などのアプリケーション統合面でも扱いやすいので採用実績が増えてきているプロダクトです。
vLLMの素晴らしさはもっといろいろあるのでアピールしたいところではありますが、このエントリーはKubeAIについての紹介なのでここでは省略します。
KubeAIの導入
KubeAIはKubernetes Operatorとして提供されているので当然ながらk8sのCRD(Custom Resource Definition)操作権限が必要です。自分でk8sクラスタ管理していない場合はAdminに依頼するか、CRD操作のRoleを付与してもらう必要があります。ここではオンプレ上のk8sクラスタに構築してみますが、もちろんパブリッククラウドのマネージドKubernetesサービス(AKS/EKS/GKE)への導入も簡単です。
Kubernetes: Client Version: v1.33.3 Server Version: v1.33.1 Kustomize Version: v5.6.0 Helm Version: v3.18.4 GPU: NVIDIA A100-SXM4
Operatorのインストールは公式のhelmチャートがあるのでhelmでインストールするのが一番推奨されます。動作確認目的なので一時的なNamespaceを作ってそこで作業します。
# Namespaceの作成 $ kubectl create ns kubeai $ kubectl config set-context --current --namespace=kubeai # HelmでKubeAIのインストール $ helm repo add kubeai https://www.kubeai.org $ helm repo update $ helm install kubeai kubeai/kubeai NAME: kubeai LAST DEPLOYED: Fri Jul 25 07:08:54 2025 NAMESPACE: kubeai STATUS: deployed REVISION: 1 TEST SUITE: None
上記のhelm installで以下のリソースが作成されました。
$ kubectl get deploy NAME READY UP-TO-DATE AVAILABLE AGE kubeai 1/1 1 1 12m $ kubectl get po NAME READY STATUS RESTARTS AGE kubeai-7dc7f588c5-jdjjp 1/1 Running 0 12m open-webui-0 1/1 Running 0 12m $ kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubeai ClusterIP 10.110.209.73 80/TCP 12m open-webui ClusterIP 10.108.51.145 80/TCP 12m
どうやらOpen WebUIのPodもデフォルトで付いてくるようです。便利ですが必須ではない気はしますね。
LLMモデルのインストール
KubeAIはModel管理用のOperatorも提供しており、LLMモデルもHelm経由でインストールできます。KubeAIはHuggingFaceと直接連携できるのでトークンを設定しておくと便利です。
$ export HF_TOKEN=huggingface token here... $ helm upgrade --install kubeai kubeai/kubeai --set secrets.huggingface.token=$HF_TOKEN # Secret登録確認 $ kubectl get secret NAME TYPE DATA AGE kubeai-huggingface Opaque 1 11m
新しいCRDがインストールされているので内容を確認しておきます。
$ kubectl get crd models.kubeai.org NAME CREATED AT models.kubeai.org 2025-07-25T07:08:55Z $ kubectl explain models.kubeai.org GROUP: kubeai.org KIND: Model VERSION: v1 DESCRIPTION: Model resources define the ML models that will be served by KubeAI. FIELDS: apiVersion string APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources kind string Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds metadata objectmeta Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata spec object ModelSpec defines the desired state of Model. status object ModelStatus defines the observed state of Model.
Modelというリソースが追加されており、モデル定義用のマニフェストファイルを作って登録することになります。ここではELYZAの8Bモデルを使います。HuggingFaceのアクセストークンは前述で作ったSecretを指定しておきます。
apiVersion: kubeai.org/v1 kind: Model metadata: name: llama-3-elyza-jp-8b namespace: kubeai spec: features: [TextGeneration] url: hf://elyza/Llama-3-ELYZA-JP-8B engine: VLLM args: - --trust-remote-code - --enable-chunked-prefill - --max-model-len=8192 - --dtype=auto - --max_num_batched_tokens=1024 - --gpu-memory-utilization=0.9 - --tensor-parallel-size=1 - --disable-log-requests envFrom: - secretRef: name: kubeai-huggingface scaleDownDelaySeconds: 300 targetRequests: 10 minReplicas: 1 resourceProfile: nvidia-gpu-a100-80gb:1
Modelリソースの仕様は以下公式の仕様書を参考に作りましょう。
https://www.kubeai.org/reference/kubernetes-api/#model
作成したリソースを登録・確認します。
$ kubectl apply -f elyza-model.yaml model.kubeai.org/llama-3-elyza-jp-8b created $ kubectl get model NAME AGE llama-3-elyza-jp-8b 6m13s # 推論サーバ(vLLM)のPodを確認 $ kubectl get po NAME READY STATUS RESTARTS AGE kubeai-7dc7f588c5-cpr27 1/1 Running 0 6h12m model-llama-3-elyza-jp-8b-f664d47f9-bsgkq 1/1 Running 0 4m56s open-webui-0 1/1 Running 0 6h12
ちなみに、モデルはHuggingFaceからダウンロード取得していますが、k8sのPersistentVolume(PV)上に置いてあるモデルも読み込むことができます。
動作確認
ここまでの手順でKubernetesにvLLMの推論サーバが稼働してLlama-3-ELYZA-JP-8Bのモデルが読み込まれたことになるので、次はクライアントとして動作確認しておきます。前述の通り、KubeAIにはOpen WebUIがおまけで付属しているので簡単に動作確認できます。Open WebUIのServiceはClusterIPで作成されるので外部から接続するためにポートフォワードします。Service定義を編集してNodePortに変えても良いかと思います。
$ kubectl port-forward svc/open-webui 8000:80
ブラウザからlocalhost:8000にアクセスして動作確認します。
問題なく動きました。同様にkubeai Serviceに対してプログラムから動作確認します(ポートフォワード設定は割愛)。適当なHTTPクライアントでも確認できますが、OpenAI API互換があるのでopenaiライブラリを使うのが楽かと思います。
from openai import OpenAI # OpenAIクライアントを初期化 # vLLMサーバーのURLをbase_urlに指定 # vLLMは認証を必要としないためapi_keyはダミーの文字列でOK BASE_URL="http://localhost:8000/openai/v1" client = OpenAI(base_url=BASE_URL, api_key="vllm") def request_chat_completion_streaming(): """ KubeAIのChat Completions APIをストリーミングモードで呼び出す """ print("\n--- Chat Completions ストリーミングリクエスト ---") # OpenAIクライアントを初期化 # vLLMサーバーのURLをbase_urlに指定, 認証を必要としないためapi_keyはダミーの文字列でOK BASE_URL="http://localhost:8000/openai/v1" client = OpenAI(base_url=BASE_URL, api_key="vllm") try: content = "仕事の熱意を取り戻すためのアイデアを5つ挙げてください" stream = client.chat.completions.create( model="llama-3-elyza-jp-8b", # 注意: HuggingFace上のモデル名ではなく、KubeAIのModelリソースで定義した名前を指定すること messages=[ {"role": "user", "content": content } ], max_tokens=500, temperature=0.8, stream=True ) print("生成されたテキスト:") for chunk in stream: # completions APIの .text ではなく、chat completions APIの .delta.content を使用 content = chunk.choices[0].delta.content if content: print(content, end='', flush=True) print() except Exception as e: print(f"error: {e}") if __name__ == "__main__": request_chat_completion_streaming()
* 出力結果
--- Chat Completions ストリーミングリクエスト --- 生成されたテキスト: 仕事の熱意を取り戻すためのアイデアを5つ挙げます。 1. 「なぜこの仕事をしているのか」という原点に戻る: 仕事の目的や意味を再認識することで、モチベーションが高まります。自身の成し遂げたいことや、仕事を通じて実現したいビジョンを思い出してみま ょう。 2. 目標を再設定する: 現在の目標や、達成すべき数字などを再確認します。目標が曖昧な場合、モチベーションが下がる要因になるため、明確な目標を設定することで、熱意 戻る可能性があります。 3. 新しいスキルや知識を習得する: 新しいことを学ぶと、脳が活性化し、仕事に対する熱意が高まります。研修やセミナーに参加、書籍やオンラインコースで学ぶなど、自己投資をしてみ しょう。 4. 職場の環境を整える: 職場の環境が整っていないと、仕事の熱意が下がる要因になることがあります。整理整頓、作業スペースの改善、コミュニケーションの改善など、環境 整えることで、仕事のパフォーマンスが向上する可能性があります。 5. 「小さな成功体験」を積み重ねる: 小さな成功体験を積み重ねることで、自信がつき、仕事の熱意が高まります。具体的には、日々の小さな目標を達成する、タスクを完了する、など小さ 成功体験を積み重ねることで、モチベーションが高まる可能性があります。 以上のアイデアを試し、仕事の熱意を取り戻すことができます。
こちらも問題ありません。
おわりに
今回はKubeAIの使い方を紹介しました。k8s上にLLM推論システムを構築するプロダクション需要は大きいかと思いますが、vLLMサーバをk8s上に構築することで推論サービスを大規模かつ効率的に展開することが可能になります。さらにKubeAIのModelカスタムリソースによってOllamaのような簡易的なモデル管理機能を備えていたり、Open WebUIがデフォルトで付属するのでプロンプトの検証など動作確認も簡単です。
手作業でマニフェストファイルを全部揃えることで似たような環境を実現することはできますが、KVキャッシュ効率を考慮したKubeAI Proxyと同等のものを作るのは大変ですし、構築時間がかかるだけでなく保守運用コストもかさんでしまいます。
KubeAIはまだ機能は少ないですが、対応フレームワークも今後は増えていくでしょうし、Kubernetes + LLMの構成を作るときの第一候補になるポテンシャルはあると思っています。個人的にはモデル管理機能がもっと洗練されると嬉しい気はしますね。KubeAIがCNCFに無事採択されることを期待しています。