跳至主要内容

⬇️⬇️⬇️ 欢迎关注我的 telegram 频道和 twitter ⬇️⬇️⬇️


联系方式: Twitter Github Email Telegram

在Kubernetes中部署LiteLLM

September 2, 2026 本文有 2331 个字 需要花费 5 分钟阅读

简介

我手里有多个渠道的大模型接口。平时用 Hermes 跑各种任务,换模型的时候不想每次去改 Hermes 的配置。所以搭了个 LiteLLM,把不同渠道的模型收进同一个 OpenAI 兼容接口。Hermes 只需要配置一次,之后想切换底层模型,在 LiteLLM 的管理页面把模型映射改一下就行。

先在本机跑通,确认模型真能调用,再搬到 Kubernetes。最终接了 PostgreSQL、Redis、Traefik 和 ArgoCD。这篇记录一下完整配置,还有中间碰到的几个坑。

为什么用 LiteLLM

LiteLLM 可以把不同厂商的模型包装成同一套 OpenAI 兼容 API。客户端只需要改 base_url、API Key 和模型名,不用管后面接的到底是什么渠道。

Hermes 平时通过模型名调模型。我用 LiteLLM 之后,Hermes 的模型名就固定指向 LiteLLM 里的一个入口,比如 main-fast。哪天想换更合适的模型,在 LiteLLM 后台把 main-fast 指到别的模型就行,Hermes 那边什么都不用动。

我现在配了 3 个模型入口,主要是给 Hermes 不同用途准备的:

  • main-fast:日常高频,快和省
  • main-pro:复杂推理,能力最强
  • main-vision:带视觉理解

入口名是我自己在 LiteLLM 里起的,指向不同渠道的真实模型。换模型只改映射,不动 Hermes。

数据库用 PostgreSQL,保存虚拟 Key、用量、模型配置和调用日志。Redis 用来做响应缓存,也给路由器共享状态。入口还是我常用的 Traefik,部署交给 ArgoCD。

目录结构

配置放在 aws-k8s/litellm

litellm/
├── argocd.yaml
├── config.yaml
├── deploy.yaml
├── ingressroute.yaml
├── kustomization.yaml
└── svc.yaml

argocd.yaml 是 ArgoCD Application,不放进当前目录的 resources。剩下的资源由 Kustomize 渲染。

LiteLLM 配置

下面是精简后的 config.yaml。为了避免把真实凭据发到文章里,示例中的 Key 和密码都做了脱敏。当前仓库里的配置是直接写值,部署起来省事,但仓库必须保持私有。

model_list:
- model_name: main-fast
  litellm_params:
    model: openai/main-fast
    api_base: https://llm.example.com/v1
    api_key: os.environ/FAST_API_KEY

- model_name: main-pro
  litellm_params:
    model: openai/main-pro
    api_base: https://llm.example.com/v1
    api_key: os.environ/PRO_API_KEY

- model_name: main-vision
  litellm_params:
    model: openai/main-vision
    api_base: https://llm.example.com/v1
    api_key: os.environ/VISION_API_KEY

litellm_settings:
  drop_params: true
  cache: true
  json_logs: true
  default_fallbacks:
  - main-fast
  cache_params:
    type: redis
    host: redis
    port: 6379
    password: os.environ/REDIS_PASSWORD
    ttl: 3600

router_settings:
  redis_host: redis
  redis_port: 6379
  redis_password: os.environ/REDIS_PASSWORD

general_settings:
  master_key: os.environ/LITELLM_MASTER_KEY
  database_url: os.environ/DATABASE_URL
  store_model_in_db: true
  store_prompts_in_spend_logs: true
  background_health_checks: true
  health_check_interval: 3600

这里有几个配置我觉得挺实用。

drop_params: true 会丢掉上游模型不支持的参数。不同厂商兼容 OpenAI API 的程度不一样,开着能少碰到一些参数报错。

default_fallbacks 配了兜底模型。默认调用失败时,LiteLLM 可以继续尝试备用模型。不过模型能力和返回风格可能不一样,别把 fallback 当成完全无感的切换。

store_model_in_db: true 允许从管理页面或 API 添加模型,配置会保存到 PostgreSQL。文件里写的模型不会消失,会和数据库里的模型一起加载。

store_prompts_in_spend_logs: true 会把请求和响应写进 Spend Logs。排查调用挺方便,但这东西会保存真实对话。多人使用或者有敏感数据时,最好关掉,或者至少设置日志保留时间。

用 Redis 做缓存

一开始我用的是本地缓存。放到 Kubernetes 后就换成 Redis:

litellm_settings:
  cache: true
  cache_params:
    type: redis
    host: redis
    port: 6379
    password: os.environ/REDIS_PASSWORD
    ttl: 3600

router_settings:
  redis_host: redis
  redis_port: 6379
  redis_password: os.environ/REDIS_PASSWORD

这两块不是一回事。

cache_params 缓存模型响应。相同请求再次进来时,可以直接返回 Redis 里的结果,省时间也省 token。

router_settings 里的 Redis 用来共享路由状态,比如限流计数和模型冷却。以后把 LiteLLM 扩成多个副本,这块状态不会散落在每个 Pod 里。

坑1. 缓存开了不等于一定能命中。

精确缓存很看请求内容。system prompt 里带时间、随机 ID,或者多轮聊天每次都多一段历史,缓存键都会变。FAQ、翻译、固定文本摘要这类请求更容易命中。

坑2. TTL 不要一上来设太长。

我先设成 3600 秒。实时性强的内容不应该长时间缓存。稳定的知识问答可以按业务改到 6 小时,甚至一天。

用 configMapGenerator 管配置

我没有手写 ConfigMap,而是让 Kustomize 根据文件生成:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deploy.yaml
- svc.yaml
- ingressroute.yaml

configMapGenerator:
- name: litellm-config
  namespace: app
  files:
  - config.yaml

渲染后会得到类似这样的名字:

litellm-config-bkgbcc6hgc

Deployment 里的引用也会自动改成带 Hash 的名字。config.yaml 一变,Hash 跟着变,Deployment 的 Pod 模板也会变化,配置更新时就能触发滚动发布。不用自己维护 ConfigMap 名字。

Deployment 中这样挂载:

volumeMounts:
- name: config
  mountPath: /app/config.yaml
  subPath: config.yaml
  readOnly: true

volumes:
- name: config
  configMap:
    name: litellm-config

源码里只写 litellm-config。最后的 Hash 由 Kustomize 处理。

Deployment

镜像用了固定版本,没有用 latest

apiVersion: apps/v1
kind: Deployment
metadata:
  name: litellm
  namespace: app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: litellm
  template:
    metadata:
      labels:
        app: litellm
    spec:
      imagePullSecrets:
      - name: docker-registry-secret
      containers:
      - name: litellm
        image: litellm/litellm:v1.99.1
        args:
        - --config
        - /app/config.yaml
        - --port
        - "4000"
        ports:
        - name: http
          containerPort: 4000
        env:
        - name: TZ
          value: Asia/Shanghai
        volumeMounts:
        - name: config
          mountPath: /app/config.yaml
          subPath: config.yaml
          readOnly: true
      volumes:
      - name: config
        configMap:
          name: litellm-config

当前的 Deployment 只设置了 TZ,敏感配置仍然跟着 config.yaml 一起挂载。更推荐的做法是用 Secret 注入这些环境变量:

FAST_API_KEY
PRO_API_KEY
VISION_API_KEY
LITELLM_MASTER_KEY
LITELLM_SALT_KEY
DATABASE_URL
REDIS_PASSWORD

我当前实际用的是 ConfigMap 整体挂载 + TZ 环境变量(见上面的真实片段),Secret 注入是更推荐的方向,后续会把敏感项都挪过去。

LITELLM_SALT_KEY 要固定下来。数据库中的模型凭据靠它加解密。模型写入数据库后再换 Salt Key,旧凭据就解不开了。

我现在只有一个副本。以后扩容时,PostgreSQL 和 Redis 已经在了,状态共享这块不用推倒重来。

Service 和 Traefik

Service 很简单,把 80 转到容器的 4000:

apiVersion: v1
kind: Service
metadata:
  name: litellm
  namespace: app
spec:
  ports:
  - name: http
    port: 80
    targetPort: http
  selector:
    app: litellm
  type: ClusterIP

入口用 Traefik IngressRoute。HTTPS 由 letsencrypt 签证书,HTTP 统一跳 HTTPS:

apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
  name: litellm
  namespace: app
spec:
  entryPoints:
  - websecure
  routes:
  - kind: Rule
    match: Host(`litellm.example.com`)
    services:
    - name: litellm
      namespace: app
      port: 80
  tls:
    certResolver: letsencrypt

交给 ArgoCD

argocd.yaml 指向这个目录:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: litellm
spec:
  destination:
    server: https://kubernetes.default.svc
  source:
    path: aws-k8s/litellm
    repoURL: https://git.example.com/example/kubernetes-yaml
    targetRevision: HEAD
  project: default
  syncPolicy:
    automated: null

我没有打开自动同步,先手动确认 diff,再点同步。AI 网关里放着模型密钥和调用日志,稳一点没坏处。

部署前检查

先渲染一遍:

kubectl kustomize aws-k8s/litellm > /tmp/litellm.yaml

确认生成了这些资源:

ConfigMap/litellm-config-xxxxx
Service/litellm
Deployment/litellm
IngressRoute/litellm
IngressRoute/litellm-http

同步完成后检查:

kubectl -n app get pod,svc
kubectl -n app logs deploy/litellm -f
curl https://litellm.example.com/health/readiness

最后用 OpenAI 兼容接口跑一遍:

curl https://litellm.example.com/v1/chat/completions \
  -H "Authorization: Bearer $LITELLM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "main-fast",
    "messages": [
      {"role": "user", "content": "只回复 ok"}
    ]
  }'

能正常返回,再去看 PostgreSQL 的表、Redis 里的缓存,以及 LiteLLM 管理页面里的 Spend Logs。

最后

这套配置不复杂。LiteLLM 负责统一模型接口,PostgreSQL 管持久数据,Redis 管缓存和共享状态,Kustomize 负责配置变更,ArgoCD 负责部署。

后面准备再补健康检查、资源限制、日志自动清理和虚拟 Key 的预算限制。先让它稳定跑起来,再慢慢加。

欢迎关注我的博客 www.bboy.app

Have Fun