1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

社内のLLMリクエストを一か所に集約したAI Gateway構築記

1
Last updated at Posted at 2026-10-06

こんにちは、DevOpsエンジニアのPokaです。

Inflabでは、字幕翻訳、講座詳細ページの生成、学習エージェント、コミュニティの回答など、かなり多くの場所でLLM APIを使っています。
当初は各サービスが必要なプロバイダーでAPIキーを発行し、直接呼び出す方式でした。
しかし利用箇所が30を超えたあたりから、この方式では徐々に限界が見えてきました。

本記事では、社内LLMルーティングサービスであるAI Gatewayを作ることになった背景と、構築の過程を共有します。

背景

モデルの入れ替わりが速すぎる

GPT、Claude、Gemini、Qwenといったプロバイダーが、ほぼ毎週のように、より安くて性能の良いモデルを出しています。
同じプロバイダーの中でも、せいぜい3か月ほどの周期で新バージョンが出て、古いモデルは提供終了となり、呼び出せなくなります。

ここで2つの問題が同時に起きます。

  • 「今いちばんコスパの良いモデル」の寿命が非常に短い - 割引キャンペーンが絡むとさらに短くなります。
  • モデルの更新を見逃すとサービスが止まる - 提供終了日までに切り替えられなければ、そのまま障害になります。

モデルを切り替えるときは、既存モデルと新モデルの両方が満足のいく結果を出すかを検証する必要があります。
この検証を各サービスの担当者が短いサイクルで繰り返すと、相当な時間がかかります。
忙しければ切り替えはどんどん後回しになり、後回しが続くと上記の2つ目の問題につながります。

コストも無視できない水準まで膨らんでいました。
2026年6月時点で、InflabのLLM API費用はAWS費用の約23% に相当していました。
同じ性能をより安く使えるかどうかが、インフラ全体のコスト効率を左右するほど重要になっていたと言えます。

キーと使用量が散らばっている

各サービスがプロバイダーを直接呼び出すと、サービスの数だけキーが増えます。
キーが増えると失効やローテーションが難しくなり、漏洩したときの影響範囲の把握も難しくなります。

使用量の確認も面倒でした。
どの機能がどれだけトークンを使っているかを見るには、プロバイダーのダッシュボードを一つずつ開く必要があり、
それでも「どのサービスのどの機能が使ったのか」は区別できませんでした。

まとめると、モデル選択・キー管理・使用量の可観測性の3つを一か所に集約することが目標でした。

では、どのゲートウェイを使うべきか?

LiteLLM Proxy、Portkey AI Gateway、Envoy AI Gatewayを比較しました。
3つとも複数LLMへの統合ルーティングとフォールバックには対応しているので、決め手はそれ以外の項目になりました。

最初に比較したのは2025年11月で、本記事の執筆にあたり2026年9月時点の情報で再確認しています。
いずれもセルフホスティング + 無料プランで使えるかどうかを基準に記載しています。
3製品とも変化が速いので、導入を検討される場合は最新のドキュメントを改めて確認することをおすすめします。

機能 Envoy AI Gateway LiteLLM Proxy Portkey AI Gateway
予算/レートリミット(コスト/トークンベース) 可能(ポリシー設定) 有料のみ 有料のみ
可観測性(ログ/メトリクス/トレース) 可能(OpenTelemetry) ロギングのみ可能
メトリクスのエクスポートは有料
基本ダッシュボードのみ
コストトラッキング 可能(設定が必要) 基本集計のみ可能
キー/チーム別は有料
有料のみ
ガードレール 可能 有料のみ 可能
プロンプト管理 なし 可能 有料のみ

決め手はCNCFプロジェクトであることでした

表をもう一度見ていただくと、有料のみと書かれたセルが一つもないのは、Envoy AI Gatewayの列だけです。
プロンプト管理はそもそも存在しませんが、有料プランでなければ使えない機能は一つもありません。
Envoy AI GatewayはCNCFが管理するEnvoyプロジェクトの一部なので、機能が商用プラン限定になることがありません。

これは「今いくら払うか」という問題ではありませんでした。
ゲートウェイを置く目的そのものが、予算ポリシー、レートリミット、使用量の追跡、認証といった統制の仕組みを一か所に集めることです。
そして、まさにこの統制の仕組みこそが、たいてい商用プランのセールスポイントになっています。
利用箇所が増えてポリシーを強化すべきタイミングで、機能ごとにプランの交渉をやり直すような状況は避けたかったのです。

可観測性がまさにその例でした。
私たちはすでにメトリクスとトレースをPrometheusやOpenTelemetryベースのスタックに集約して見ていましたが、
LiteLLM Proxyは使用量を独自UIの中でしか見られず、既存のダッシュボードに統合する方法がありませんでした。
社内ダッシュボード一か所で使用量を見ることが今回の主な目標だったので、そのまま不採用の理由になりました。

受け入れたトレードオフ

もちろんタダで手に入ったわけではなく、付随するコストもありました。

  • Envoy Gatewayも一緒に導入する必要がある - Envoy AI GatewayはEnvoy Gatewayの上で動作します。当時はEnvoy Gatewayを使っていなかったので、AI Gatewayの導入に合わせて一緒に取り入れました。
  • プロンプト管理機能が弱い - プロンプトは各サービスのリポジトリで管理するほうが自然だと考え、許容しました。

その代わり、ルーティングと認証ポリシーをすべてKubernetesのカスタムリソースとして宣言できる点は、私たちによく合っていました。
社内のインフラ設定はすべてGitOpsで管理しているので、新しいプロバイダーを追加する作業が、コンソールのクリックではなく、コードレビュー付きのPull Request 1件で完結するようになりました。

構成

まず使う側の話をすると、知っておくべきことはほとんどありません。
ゲートウェイがOpenAI APIの仕様でリクエストを受け取り、各プロバイダーの仕様に変換してくれるので、
ほとんどの場合、OpenAIのライブラリ1つでClaudeもGeminiもQwenもすべて呼び出せます。

Inflabの構成では、1つのゲートウェイが3つのアクセス経路を受け持ち、その背後に5つのプロバイダーがつながっています。

3つのアクセス経路と接続されたプロバイダー

使ううえで必要なのはここまでです。
ここから先はこのゲートウェイがどう構成されているかの話なので、興味のある方だけ読んでいただければ大丈夫です。

Envoy AI Gatewayは、設定を管理するControl Planeと、実際のリクエストが流れるData Planeに分かれています。
Envoy Gatewayの上に載る拡張なので、ルーティングと認証をKubernetesリソースとして宣言すると、
コントローラーがそれをプロキシの設定に落とし込んでくれる仕組みです。

  • AIGatewayRoute - どのモデルへのリクエストをどのバックエンドに送るかを定義します
  • AIServiceBackend - プロバイダーのエンドポイントとAPI仕様を定義します
  • BackendSecurityPolicy - そのバックエンドで使う認証情報を定義します

これらのリソースを適用すると、次のような流れで反映されます。

AIGatewayRouteを適用
  -> AI Gateway ControllerがHTTPRouteと設定用Secretを生成
  -> Envoy Gateway ControllerがxDS設定を生成
  -> AI Gateway Extension ServerがxDSにLLM処理用フィルターを追加
  -> Envoy Proxy + ExtProc sidecarがリクエストを処理

モデル名を消して「ティア」だけを残す

モデルの切り替えを中央で処理するには、サービス側がモデル名を直接指定してはいけません。
サービスのコードに gemini-2.5-flash がハードコードされていると、そのモデルが提供終了になるときに結局サービスのコードを修正することになります。
それではゲートウェイを置いた意味がなくなってしまいます。

そこで、モデル名の代わりに low、medium、high の3つのティアだけを公開することにしました。

名前 入力100万トークンあたりの最大コスト 推奨用途
high $2 ハルシネーションの影響を非常に受けやすい場合や、複雑な推論が必要な場合に使用
medium $1 ユーザーがテキストを直接目にする場合や、後処理に使うデータの生成に使用
low $0.3 簡単なロジック、短い回答、分類、構造化データの生成に使用

各ティアに実際に紐づくモデルは、時間とともに変わります。
ただし、表に記載した最大コストは契約のように固定されます。
どのモデルが割り当てられるかは分からなくても上限は分かるので、
月間の想定入力トークン数 × 上限コスト で入力トークンの費用を事前に見積もることができます。

例えば、月に入力トークンを1億使うと見込まれる機能で low を選んだ場合、
100万トークン単位に換算すると100なので 100 × $0.3 = $30 です。出力トークンの費用はこれとは別にかかります。

実際に呼び出すときは、model にティア名を入れるだけです。

curl -s '<社内AI GatewayのURL>/v1/chat/completions' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer <サービス名>' \
  -H 'X-Service-Feature: onboarding-chat' \
  -d '{"model":"low","messages":[{"role":"user","content":"hi"}]}'

# -> レスポンスのmodelフィールドには、実際にルーティングされたモデル名が入って返ってきます

ルーティング構成

ゲートウェイの設定で、ティアを実際のモデルに置き換えます。
同じモデルを複数のプロバイダーから利用できる場合は、優先順位を付けてフォールバックを設定しています。

low、medium、highの各ティアがどのバックエンドにつながるか

# medium: 割引中のルートを先に叩き、レートリミットにかかったら定価ルートに切り替える
- matches:
    - headers:
        - type: Exact
          name: x-ai-eg-model
          value: medium
  backendRefs:
    - name: envoy-ai-gateway-openrouter
      modelNameOverride: openai/gpt-5.6-luna
      priority: 0
    - name: envoy-ai-gateway-openai
      modelNameOverride: gpt-5.6-luna
      priority: 1

これに加えて、429レスポンスと接続失敗に対するリトライポリシーを設定しました。
同じモデルをより安く提供するルートが出てきたらそちらを最優先にし、レートリミットにかかったときだけ定価ルートに切り替わります。
この判断がサービスのコードではなく、ゲートウェイの設定にあることがポイントです。

モデルを切り替えるときの手順

モデルが変わると、モデルの特性によってレスポンスの形が変わったり、これまでうまく動いていたパターンが動かなくなったりと、
副作用が出てサービスに影響を与える可能性があります。
これを中央で極力抑えることもゲートウェイの役割だと考え、次の手順を定めました。

  1. ティアごとに、最低限の品質基準を自動で検証できるテストセットを用意します。
  2. 上限コストを超えず、よりコスパが良さそうなモデルが出たら候補に挙げます。
  3. 既存モデルと候補モデルに対して同じテストセットを実行します。1つでも失敗したら不採用とします。
  4. 通過したら開発部門全体に切り替え予定日を告知し、関連機能のモニタリングをお願いします。
  5. 切り替え後、そのティアを使う機能が正常に動作しているかを重点的に確認し、新たに見つかった品質基準はテストセットに追加します。

でも、ちょっと窮屈じゃないですか?

はい、機能ごとにぴったりのモデルを選ぶ自由は減ります。

それでもこの方向を選んだのは、ある時点で完璧に最適化された選択をすることよりも、
変化に素早く追従できる能力のほうが長く利益をもたらすと考えたからです。
あるモデルが大幅に値下げされたとき、30のサービスがそれぞれ対応する構造と、
ゲートウェイが一度だけ対応する構造とでは、時間が経つほど差が開いていくと思います。

誰がどれだけ使ったかをどう把握するか?

ゲートウェイがキーを一元管理すると、プロバイダーのダッシュボード上ではすべてのリクエストがひとまとまりに見えます。
そのため、ゲートウェイ自身が「誰が呼び出したか」を記録する必要がありました。

最初は、サービスごとにゲートウェイ用のAPIキーを発行する案を検討しました。
しかし、なくそうとしていたキーがまた増えるのが引っかかり、発行ではなく命名規則と検証を使う方向に切り替えました。
APIキーの代わりに、デプロイしているアプリケーション名を入れてもらうと、
ゲートウェイが許可された形式かを確認したうえで、サービス識別用のヘッダーに移し替えます。

さらに、先ほどの例にあった X-Service-Feature ヘッダーで機能名をもう1つ受け取ります。
これにより、「どのサービスのどの機能が、どのモデルをどれだけ呼び出したか」を社内ダッシュボード一か所で確認できるようになりました。

成果

  • 社内の30を超えるサービスが、ゲートウェイを経由してLLMを呼び出しています。サービスのコードからプロバイダーのキーがなくなりました。
  • 新しいプロバイダーを追加する作業が、GitOpsのPull Request 1件に集約されました。
  • サービスと機能の2軸で、トークン使用量とコストを確認できるようになりました。
  • モデルの切り替えがゲートウェイの設定変更1回で完了します。大幅に値下げされたモデルが出たら、ティアの紐付けを変えるだけで全サービスに一度に反映されます。

では、コストはどれくらい下がったのか?

InflabのLLM費用が最も高かったのは6月でした。
ティアルーティングを本番環境に適用したのは8月初めなので、適用後初めて丸1か月運用した8月を、現在の状態として比較しました。

LLM費用全体が、ピーク時と比べて約78% 減少しました。

これには2つの要因が同時に作用しました。

1つ目はティアルーティングです。
medium ティアの実際のブレンド単価は100万トークンあたり$0.18でした。
ティア表に記載した medium の上限$1の5分の1程度です。
キャッシュヒット率が80%を超えたことも、単価を押し下げるのに一役買いました。

2つ目は、使用量が見えるようになったことです。
それまではプロバイダーのダッシュボードにリクエストがひとまとまりで記録され、どの機能がいくら使っているのか分かりませんでした。
サービスと機能の2軸に分けてみると、想定よりはるかに多く使っていた機能や、
わざわざ高いモデルを使う必要のなかった機能が浮かび上がってきました。
ルーティングを変えなくても、見えるようになっただけで改善される部分がありました。

おわりに

変化の速い領域では、最適な選択を維持し続けるよりも、選択を変えるコストを下げるほうが得策です。
モデル名をティアで隠すという決定によって、個々の機能の最適化を少しあきらめる代わりに、組織全体の反応速度を手に入れたと言えます。

管理対象を増やさずに解決する方法がないか、まず探してみるのがおすすめです。
サービスを識別するためにゲートウェイ用のキーを新たに発行しようとして、命名規則と検証に方向転換したのがその一例です。
そもそもキーを減らすために始めた作業だったので、キーを再び増やさない選択が正しかったと考えています。

今後は、ティアごとのテストセットをより細かく作り込み、モデル切り替えの判断を自動化することに注力していく予定です。
同じような悩みを抱えている方の参考になれば幸いです。最後まで読んでいただき、ありがとうございました!

参考資料

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?