1. 为什么要在 K8s 里跑 LiteLLM 网关
LiteLLM 是一个把多家大模型 API 统一成 OpenAI 兼容格式的网关,你可以把它理解成集群里的「模型路由中枢」:上游是各家模型服务,下游是业务 Pod,中间由它负责鉴权、路由、限流和日志。放到 Kubernetes 里跑,好处是副本可扩、配置可版本化、密钥可集中管理,团队里谁要用模型,只认一个集群内地址就行。
真正让人头疼的不是 LiteLLM 本身,而是 Key 的散落。业务 A 用一家、业务 B 用另一家,每个 Pod 里塞一份密钥,轮换一次要改十几个 Deployment。我试过把 endpoint 和 Key 统一收敛到 TaoToken 这一层,LiteLLM 只保留一份上游凭据,模型名到实际后端的映射写在 ConfigMap 里,改配置不用动业务代码。这篇就按这个思路,把「Kubernetes 部署 LiteLLM 统一多模型 Key」的完整路径走一遍,包含可直接复制的 Deployment、Service、ConfigMap YAML,以及用 curl 验证模型列表和一次对话请求的检查动作。
适合谁看:手里有 K8s 集群、需要给多个团队或服务统一发模型能力的平台同学;已经在用 LiteLLM 但 Key 管理混乱、想收敛入口的运维同学;以及准备把本地 LiteLLM 迁到集群、想要一份能跑通的清单的人。读完你应该能拿到一个一次部署、稳定路由多模型调用的最小可用形态。
需要提前说明的是,LiteLLM 的镜像、端口、环境变量在不同版本间偶有差异,本文以ghcr.io/berriai/litellm:main-latest和 8000 端口为基准,你落地时按自己锁定的 tag 微调即可。下面从集群前置检查开始。
2. 部署前的集群检查与 TaoToken 凭据准备
先把地基打牢,再谈部署。集群侧要确认三件事:kubectl 能连上、节点资源够、命名空间隔离好。LiteLLM 本体不重,单副本 1 核 1Gi 起步足够,但它要维护到上游的连接池,副本数建议至少 2 个做滚动更新时的可用性兜底。
kubectl version --short kubectl get nodes -o wide kubectl top nodes如果kubectl top报 metrics 不可用,说明 metrics-server 没装,不影响部署,但后面排查资源问题会少一个手段,建议顺手补上。接着建独立命名空间,别和业务混在一起:
kubectl create namespace litellm kubectl config set-context --current --namespace=litellm然后是凭据这一层。TaoToken 的定位是统一入口,你需要在控制台生成一个 API Key,后面 LiteLLM 就用这个 Key 去访问上游。地址方面,官网入口是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 基址是 https://taotoken.net/api ,注意 API 地址不带查询参数,配置里填的就是这个纯基址。
生成 Key 的入口在控制台的 API Keys 页面,对应 deep link 是 https://taotoken.net/console/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api_keys&utm_campaign=rewrite 。拿到形如sk-开头的字符串后,不要写进 YAML 明文,用 Secret 存。这里有个细节:LiteLLM 读取上游凭据既支持环境变量,也支持配置文件里的api_key字段,两种方式我都给出来,你按团队习惯选。
先把 Secret 建好,键名统一用upstream_api_key,避免和 LiteLLM 自身的 master key 混淆:
kubectl create secret generic litellm-upstream \ --namespace=litellm \ --from-literal=upstream_api_key='sk-你的TaoToken密钥'再建一个给 LiteLLM 网关自身用的 master key,业务侧调用集群内网关时校验用:
kubectl create secret generic litellm-master \ --namespace=litellm \ --from-literal=master_key='sk-litellm-local-2024'两个 Secret 分开是有原因的:上游 Key 泄露影响的是你的额度,网关 master key 泄露影响的是集群内调用权限,轮换节奏和范围都不一样。到这里前置就绪,下一节进入可复制的配置。
3. 可复制的 ConfigMap 与 Deployment 配置
这一节是全文的核心,配置写对了,后面基本一次过。LiteLLM 的配置分两块:一块是config.yaml,描述模型列表和上游地址;一块是 Deployment 的环境变量,告诉它去哪读配置、用哪个 master key。
先写 ConfigMap。注意api_base指向 TaoToken 的 API 基址,model字段写你要路由的模型名,model_name是暴露给业务侧的别名,业务只认别名,换后端时改这里就行:
apiVersion: v1 kind: ConfigMap metadata: name: litellm-config namespace: litellm data: config.yaml: | model_list: - model_name: gpt-4o-mini litellm_params: model: openai/gpt-4o-mini api_base: https://taotoken.net/api api_key: os.environ/UPSTREAM_API_KEY - model_name: claude-sonnet litellm_params: model: anthropic/claude-3-5-sonnet-20241022 api_base: https://taotoken.net/api api_key: os.environ/UPSTREAM_API_KEY general_settings: master_key: os.environ/LITELLM_MASTER_KEY database_url: "" litellm_settings: drop_params: true request_timeout: 600os.environ/UPSTREAM_API_KEY是 LiteLLM 的语法,表示从环境变量取值,这样密钥不进 ConfigMap。drop_params: true建议开着,不同上游对参数支持不一致,多余参数直接丢弃比报错友好。
接着是 Deployment。镜像用官方镜像,端口 8000,把 ConfigMap 挂到/app/config.yaml,环境变量从两个 Secret 注入:
apiVersion: apps/v1 kind: Deployment metadata: name: litellm namespace: litellm labels: app: litellm spec: replicas: 2 selector: matchLabels: app: litellm template: metadata: labels: app: litellm spec: containers: - name: litellm image: ghcr.io/berriai/litellm:main-latest args: - "--config" - "/app/config.yaml" - "--port" - "8000" ports: - containerPort: 8000 env: - name: UPSTREAM_API_KEY valueFrom: secretKeyRef: name: litellm-upstream key: upstream_api_key - name: LITELLM_MASTER_KEY valueFrom: secretKeyRef: name: litellm-master key: master_key volumeMounts: - name: config mountPath: /app/config.yaml subPath: config.yaml readinessProbe: httpGet: path: /health/readiness port: 8000 initialDelaySeconds: 15 periodSeconds: 10 livenessProbe: httpGet: path: /health/liveness port: 8000 initialDelaySeconds: 30 periodSeconds: 20 resources: requests: cpu: "250m" memory: "512Mi" limits: cpu: "1" memory: "1Gi" volumes: - name: config configMap: name: litellm-configService 用 ClusterIP 就够,集群内业务通过litellm-service.litellm.svc.cluster.local:8000访问;要对外再叠 Ingress:
apiVersion: v1 kind: Service metadata: name: litellm-service namespace: litellm spec: selector: app: litellm ports: - protocol: TCP port: 8000 targetPort: 8000 type: ClusterIP一次性 apply:
kubectl apply -f litellm-configmap.yaml kubectl apply -f litellm-deployment.yaml kubectl apply -f litellm-service.yaml kubectl get pods -n litellm -w看到两个 Pod 都Running且READY 1/1就说明探针过了。如果卡在CrashLoopBackOff,先看日志,多半是 config.yaml 缩进或环境变量名对不上,下一节验证时会顺带覆盖。
4. 用 curl 验证模型列表与一次对话请求
部署完不验证等于没部署。验证分两步:先确认网关活着并能列出模型,再打一次真实对话请求,确认上游链路通。
第一步,端口转发到本地,避免依赖 Ingress:
kubectl port-forward -n litellm svc/litellm-service 8000:8000另开一个终端,带上 master key 请求模型列表:
curl -s http://127.0.0.1:8000/v1/models \ -H "Authorization: Bearer sk-litellm-local-2024" | jq .返回里应该能看到gpt-4o-mini和claude-sonnet两个别名。如果返回 401,说明 master key 没对上,检查 Secret 里的值和请求头是否一致。
第二步,打一次对话请求,验证上游真的通:
curl -s http://127.0.0.1:8000/v1/chat/completions \ -H "Authorization: Bearer sk-litellm-local-2024" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-4o-mini", "messages": [{"role": "user", "content": "用一句话说明什么是网关"}], "max_tokens": 64 }' | jq '.choices[0].message.content'能打印出一句话回答,就说明 LiteLLM 用 TaoToken 的 Key 成功路由到了上游。再换claude-sonnet打一次,确认多模型路由都通。这一步很关键:模型列表能列出不代表上游可达,只有真实 completion 返回才算打通。
如果你更想先在网页里确认模型可用性,可以走模型对话入口 https://taotoken.net/model-chat?utm_source=taotoken_aicg_blog_end&utm_content=model_chat&utm_campaign=rewrite ,用同一个 Key 手动发一条,和集群内结果对照,能快速区分是网关问题还是上游问题。
验证通过后,业务侧接入就简单了:把 OpenAI SDK 的base_url指向http://litellm-service.litellm.svc.cluster.local:8000/v1,api_key填 master key,model填别名。业务代码零改动,换模型只改 ConfigMap。
5. 常见报错排查:401、local proxy failed 与 reading choices
部署阶段最容易撞的几类报错,我按真实日志对照给你排一遍。
401 Unauthorized。两种来源要分清:一种是请求网关时 master key 不对,日志里是Authentication Error,检查请求头Authorization: Bearer和 Secret 是否一致;另一种是网关访问上游时被拒,日志里会出现upstream字样,说明 TaoToken 的 Key 无效或额度问题,去控制台核对 Key 状态。区分方法看报错里有没有litellm前缀。
local proxy failed / connection refused。这通常是 Pod 没起来或端口不对。先kubectl get pods -n litellm看状态,再kubectl logs -n litellm <pod-name>看启动日志。如果日志停在读取 config,多半是 ConfigMap 挂载路径不对,确认mountPath是/app/config.yaml且subPath匹配。如果报Address already in use,检查 args 里的端口和 containerPort 是否一致。
reading choices 相关报错。这类多半是上游返回结构不符合预期,常见于模型名写错或上游不支持该参数。日志里会带KeyError: 'choices'或reading 'choices'。处理办法:先在模型对话页面用同一模型名手动发一次,确认上游本身可用;再检查 ConfigMap 里model字段的 provider 前缀是否正确,比如openai/和anthropic/不能混。drop_params: true能挡掉一部分参数不兼容的问题。
OAuth / token 过期类报错。如果你用的是需要 OAuth 的 provider,LiteLLM 侧要额外配置凭据刷新,纯 API Key 模式不会遇到。看到OAuth字样先确认是不是误配了需要交互登录的 provider,统一走 TaoToken 的 Key 模式可以规避这类问题。
Pod 一直 Pending。资源不够或节点亲和性问题,kubectl describe pod -n litellm <pod-name>看 Events,多半是 requests 超过节点可分配量,把 requests 调小即可。
排查时记住一个顺序:先看 Pod 状态,再看容器日志,最后看上游连通性。三步能定位九成问题。日志命令:
kubectl logs -n litellm -l app=litellm --tail=100 kubectl describe pod -n litellm -l app=litellm6. 长期编码与 Agent 场景的接入建议
集群里跑通 LiteLLM 只是第一步,真正省心的是把它接到日常编码和 Agent 工作流里。如果你团队在用 Claude Code 这类工具,或者要跑长任务的 Agent,建议把网关地址和 Key 固化到工具配置里,而不是每次手动填。
长期编码场景更适合用 Coding Plan 这类按周期计费的方式,入口在 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding_plan&utm_campaign=rewrite ,配合集群内 LiteLLM 做统一出口,额度管理和路由就都在你手里了。接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite ,里面有各语言 SDK 的 base_url 填法,照着改就行。
几个落地经验:ConfigMap 改动后记得kubectl rollout restart deployment/litellm -n litellm,LiteLLM 不会自动热加载;副本数别只开 1 个,滚动更新时会有短暂不可用;给网关加个 NetworkPolicy,只允许业务命名空间访问 8000 端口,减少暴露面。密钥轮换时先更新 Secret,再重启 Deployment,业务侧无感。
到这里,一个能稳定路由多模型调用的 LiteLLM 网关就在集群里跑起来了。后续要加模型,只改 ConfigMap 里的model_list,业务代码一行不用动。