多租户 AI 网关 团队工作区 RBAC 计费隔离

面向团队的多租户 LLM 网关架构

设计多租户 LLM 网关,用团队作用域、项目密钥、隔离配额、使用日志与媒体所有权避免凭证和数据跨租户泄漏。

AveMujica API 2 分钟阅读

多租户 LLM 网关是一层控制面:它让多个团队、项目和应用共享一个 OpenAI 兼容入口,同时隔离凭证、配额、用量与媒体所有权。架构难点不是“加一列 tenant_id”,而是让每个请求始终回答四个问题:谁在调用、谁来付费、允许使用哪些模型,以及之后可以读取哪些产物。本文把这些问题映射到可落地的网关模式,包括团队工作区、项目作用域密钥、限流作用域,以及图片和视频任务的媒体隔离。

为什么多租户通常出现在首次生产成功之后

早期部署往往从一把管理员密钥和一个供应商通道开始。它会一直工作,直到出现以下情况:

  • 产品、研究与支持团队共用同一个费用池
  • 外包人员需要临时模型访问,但不能看到组织密钥
  • 财务需要知道哪个项目产生了上月账单
  • 某个生成视频 URL 不能被同级团队下载
  • 一个高噪声 agent 耗尽所有人的限流额度

此时租户边界必须落在网关,而不能只存在于应用代码。应用侧软限制有帮助,但无法阻止泄漏的密钥或配置错误的 worker 向错误所有者计费。没有租户隔离的 多供应商 LLM 网关 最终会变成共享爆炸半径的共享基础设施。可将它与 LLM 代理与 AI 网关 中的薄反向代理对比:代理只转发,多租户网关还负责授权和记账。

核心租户模型:所有者、执行者与作用域

每个请求都要分开维护三种身份:

  1. 执行者——发起调用的人类或服务主体。
  2. 计费所有者——请求结算时扣减配额的钱包。
  3. 访问作用域——限定密钥、模型和产物的团队/项目,或个人工作区。

在此类仓库形态的系统中,个人令牌通常向用户所有者计费;团队作用域令牌同时绑定团队与项目,并把计费解析到团队钱包。团队工作区被禁用、项目已停用或执行者缺少项目所需操作权限时,中间件应拒绝团队令牌。该检查必须在通道分发之前进入热路径。

Client / agent
   |  Bearer sk-...
   v
Auth middleware
   - resolve token -> user, team_id, project_id, owner_type
   - validate membership + project action grants
   v
Policy + rate-limit scope
   - team:project:user (or personal user scope)
   - model allowlists / group grants
   v
Relay / task submit
   - upstream channel selection
   - pre-consume quota against billing owner
   v
Usage log + optional media persistence
   - store actor, team, project, billing owner
   - authorize later content proxy by same scope

如果把执行者和计费所有者压成一个字段,就无法区分“谁花了团队预算”和“谁点击了生成”。如果作用域只是日志标签,那么 /v1/videos/{id}/content 的授权会跨租户泄漏。

必须保持一致的租户表面

1. API 密钥与项目绑定

把密钥作为一等租户对象签发:

  • 用于个人沙箱的个人密钥
  • 绑定 team_id + project_id 的团队密钥
  • 可选的分组或模型授权,用于限制密钥可调用哪些稳定网关别名

稳定别名,例如 gpt-image-2 或面向产品的 video-default,应在通道配置中映射到上游模型 ID。客户端保留别名,运维人员可轮换原始上游 ID,而不必重写每个服务。绝不要把上游供应商密钥嵌入客户端环境。客户端只向网关认证,供应商凭证由通道保存。在多团队产品中,应把同样的隔离纪律应用到 AI API 访问的 RBAC。

2. 配额与预扣安全

计费安全也是租户问题。昂贵任务开始前先向计费所有者预扣,待上游完成后结算或退款。对于图片 n、视频时长等媒体乘数,必须在校验阶段设置硬上限,避免恶意或有 bug 的客户端让配额计算溢出为负数费用。本代码库将图片数量限制为 MaxImageN = 128,并用 MaxTaskDurationSeconds 限制视频时长。即使团队策略设置了更严格的项目预算,多租户系统仍应全局保留这些防护。

3. 使用复合作用域键限流

团队流量可使用 team:{id}:project:{id}:user:{id} 形式的作用域键,个人流量则使用仅含用户的键。这样,一个项目的 agent 风暴不会饿死另一个项目的聊天流量。限流决策应独立于通道选择:团队可以获准使用某个模型,同时仍受流量限制。

4. 使用日志是审计表面

每个已结算调用都应保留执行者、计费所有者、团队/项目(若有)、模型别名、请求 ID,以及媒体乘数(n、秒数、尺寸)。财务与安全审阅者都需要这些字段。面向产品的用量视图是经过认证的控制台表面;公开文档应解释审计模型,而不是反复把读者链接到私有控制台路由。

5. 媒体所有权不是可选元数据

图片和视频产物会比 HTTP 请求存活更久。对象键与任务 ID 必须被视为租户资源:

表面本仓库中的作用域(声明前请验证)所有权规则
图片工作台 UI/API/api/user/image-workbench 下的个人/session/token 作用域及 API-key 变体;对象键归用户所有当前没有团队/项目图片工作台路由
视频工作台 UI/API/api/user/video-workbench 下的个人作用域,以及 /api/teams/:team_id/video-workbench 下的团队/项目作用域团队运行与资产按团队 + 项目授权
OpenAI 兼容图片入口POST /v1/images/generations、POST /v1/images/edits向令牌的计费所有者计费;除非自行持久化,否则不要虚构团队历史
OpenAI 兼容视频入口POST /v1/videos、查询、内容;remix 路由仍已注册Content GET 必须重新检查创建任务时的同一所有者/作用域

上游供应商 URL 经常会过期。把对象持久化到私有存储并通过授权代理重新提供,可以减少失效链接与意外公开暴露。工作台需要对象存储时,若存储配置错误,应失败关闭,而不是返回一个没有作用域保护的临时 URL。

接入第二个团队前的隔离清单

把它当作发布门禁,而不是演示幻灯片:

边界通过标准
鉴权已移除成员和已禁用项目使用团队令牌时失败
计费团队任务绝不扣个人钱包,反之亦然
模型未获授权的项目不能调用受限别名
日志跨团队日志查询返回空或拒绝,而不是部分行
媒体视频内容代理对外部团队任务 ID 返回未找到/禁止
限流项目 A 的负载不消耗项目 B 的 token bucket
管理超级管理员操作与租户管理员操作分开审计

自动化测试必须覆盖拒绝路径,而不只是 happy path。多租户 bug 常藏在“软 404”决策中:如果资源是否存在本身就是敏感信息,对外部资源返回 404 往往比 403 更合适。

团队作用域聊天的参考请求路径

curl https://your-gateway.example.com/v1/chat/completions \
  -H "Authorization: Bearer $TEAM_PROJECT_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "YOUR_STABLE_CHAT_ALIAS",
    "messages": [
      {"role": "user", "content": "Summarize yesterday deploy risk for project alpha."}
    ],
    "max_tokens": 400
  }'

网关内部应执行以下步骤:

  1. 认证密钥并解析 team_id / project_id。
  2. 确认执行者可以为该项目使用项目令牌。
  3. 通过允许的分组/通道集合解析模型别名。
  4. 从团队计费所有者预扣估算配额。
  5. 中继到上游,并写入同时包含执行者与所有者字段的消费日志。
  6. 在经过认证的用量视图中暴露相同标识,供财务和支持使用。

同一令牌规则下的媒体与不同工作台作用域

媒体端点不应为计费另造第二套鉴权系统。OpenAI 兼容入口应优先沿用相同的令牌与 session 规则:

# Image generation through OpenAI-compatible ingress (GPT Image returns b64_json)
curl https://your-gateway.example.com/v1/images/generations \
  -H "Authorization: Bearer $TEAM_PROJECT_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-image-2",
    "prompt": "Product hero shot on matte black pedestal, studio light",
    "size": "1024x1024",
    "n": 1,
    "output_format": "png"
  }'
# Async video job (evaluate Sora 2 only with the official deprecation timeline in mind)
curl https://your-gateway.example.com/v1/videos \
  -H "Authorization: Bearer $TEAM_PROJECT_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "YOUR_STABLE_VIDEO_ALIAS",
    "prompt": "Slow orbit around a ceramic mug on a wood table",
    "seconds": "4",
    "size": "1280x720"
  }'

两个工作台的 UI 作用域不同:

  • 图片工作台 是个人运维表面:预设、运行记录和资产都按用户划分。除非你已经实现,否则不要宣称存在团队图片历史或 /api/teams/:team_id/image-workbench 路由。
  • 视频工作台 同时支持个人与团队/项目作用域。把生成和管理资产能力映射到团队操作权限;session 绑定团队时,运行历史必须按项目划分。

重试持久化端点不得把资产重新归属到另一个所有者。对于新的绿地视频工作,考虑到 OpenAI Videos API / Sora 2 将在 2026-09-24 关闭,应优先选择关闭后仍能支持的供应商与网关适配器(参见 OpenAI 弃用公告);如果仍承载 Sora 流量,现在就要规划任务存储和客户端代码路径迁移。

无需重写客户端即可扩展的策略层

策略应从粗到细叠加:

  1. 平台默认值——最大图片 n、最大视频秒数、禁止模型。
  2. 团队策略——允许的分组、预算告警、功能开关。
  3. 项目授权——哪些成员可以生成媒体或管理视频资产。
  4. 密钥约束——IP allow list、过期时间、模型子集。
  5. 运行时限制——RPM/TPM 与并发任务上限。

客户端继续调用 /v1/*。运维人员在管理员配置和通道模型映射中调整策略。这正是 OpenAI 兼容 API 网关 的运维收益。

多租户网关特有的失败模式

  • 静默回退所有者: 团队解析失败时,不要为了“方便”而向执行者的个人钱包计费,应直接让请求失败。
  • 共享通道亲和性缺少隔离标签: 缓存键必须包含租户作用域,否则会混合粘性路由状态。
  • 误以为图片工作台支持团队: 用户所有的个人图片资产不同于团队视频项目。
  • 日志留存忽略法律边界: 团队移除可能要求选择性删除;留存任务必须按所有者过滤。
  • 内容代理混淆: Dashboard session 鉴权和 API token 鉴权都需要相同的所有权检查。
  • 预算告警没有操作权限: 如果任何成员仍可创建密钥,只提醒财务没有意义。

OWASP LLM Top 10 的安全指导仍然适用:当一个租户能影响另一个租户时,过度代理、敏感信息泄漏与无界消耗都会变成租户事故。

最小实现顺序

  1. 建模团队、项目、成员与操作授权。
  2. 为令牌和消费日志加入所有者字段。
  3. 在鉴权中间件中强制校验团队令牌。
  4. 为限流与用量查询添加作用域。
  5. 将视频任务鉴权和内容代理迁移到同一作用域 helper;除非有意增加团队图片持久化,否则保持图片工作台归用户所有。
  6. 为聊天、你保存的图片字节与视频内容添加跨租户拒绝的端到端测试。
  7. 完成这些步骤后,才把真实产品流量迁移到团队密钥。

跳过拒绝路径测试,就可能交付“有多租户 UI、没有多租户安全”的系统。

相关阅读

来源与延伸阅读

决策检查

是否必须为每个租户建立独立数据库?

多数 AI 网关不需要。通过严格查询过滤实现行级隔离很常见。独立数据库有助于受监管隔离或存储层的 noisy-neighbor 限制,但会成倍增加迁移与通道配置。应根据合规需求选择,而不是追逐潮流。

每个微服务都应该创建自己的供应商密钥吗?

不应该。应按服务身份创建网关密钥,把供应商密钥留在通道中。这样才能保留轮换、费用可见性与 failover 能力。

个人工作区如何与团队共存?

把个人所有者类型保留为一等路径。用户可先用个人密钥和个人图片工作台做原型,然后切换到团队项目密钥来共享聊天/视频费用,而不改变请求形状;只需更换 Bearer token 与策略。

多租户媒体最严重的错误是什么?

把上游结果 URL 当成持久公开链接,或假设每个工作台都是团队作用域。产品需要持久性时应保存对象,通过授权路由代理访问;无法保存时应说明过期规则,并如实说明个人与团队所有权。

迁移演练

选一个生产应用,把它从共享管理员密钥迁移到团队项目密钥。验证消费日志显示正确的计费所有者,外部视频任务 ID 在 /v1/videos/{id}/content 被拒绝,图片工作台资产仍归用户所有(除非你实现了额外共享),并确认项目限流不再与同级团队的负载测试相互碰撞。