路由到 LLM 提供商

简介

Envoy AI Gateway 可以通过一个兼容 OpenAI 的端点为外部 LLM 提供商提供前置接入。它使用 BackendSecurityPolicy 注入每个提供商的上游凭证,按模型名称进行路由,并在提供商之间自动故障切换。消费者只需调用单一的内部地址,且不会持有提供商密钥,因此网关会成为公共云 LLM 流量的受控出口点,并将与自托管模型相同的身份、配额和计量策略应用于外部模型。

使用场景

  • 公开托管模型,例如来自 OpenAI、AWS Bedrock、Azure OpenAI、GCP Vertex AI 或 Anthropic 的模型,而无需分发提供商密钥。
  • 将不同的模型名称路由到同一端点后的不同提供商。
  • 当主提供商不可用时,切换到备用提供商。

前提条件

  1. 已安装 Envoy AI Gateway,并且存在一个 Gateway 和一个 AIGatewayRoute。确认相关 CRD 已存在:

    kubectl get crd \
      aigatewayroutes.aigateway.envoyproxy.io \
      aiservicebackends.aigateway.envoyproxy.io \
      backendsecuritypolicies.aigateway.envoyproxy.io \
      backends.gateway.envoyproxy.io
  2. 已启用 Envoy Gateway Backend API。本文档通过 kind: Backend(Envoy Gateway 扩展资源)声明提供商上游,这要求在 EnvoyGateway 配置中设置 extensionApis.enableBackend: true——仅仅存在 CRD 还不够。请先确认,如缺失则启用它:

    kubectl -n envoy-gateway-system get configmap envoy-gateway-config \
      -o jsonpath='{.data.envoy-gateway\.yaml}' | grep -A2 extensionApis
    # expect to see: enableBackend: true

    如果未设置,请在 extensionApis 下添加它并重新启动控制平面:

    kubectl edit configmap envoy-gateway-config -n envoy-gateway-system
    # extensionApis:
    #   enableBackend: true
    kubectl rollout restart deployment envoy-gateway -n envoy-gateway-system
  3. 上游提供商凭证(在下一节创建)存储在路由命名空间中的一个 Secret 中。

  4. 从集群出口可以访问提供商端点。继续之前请先验证:

    # On clusters without docker.io egress (air-gapped / mirror-only), replace
    # curlimages/curl with any small curl/wget image from your registry mirror.
    kubectl run egress-probe --rm -i --restart=Never \
      --image=curlimages/curl -- \
      curl -s -o /dev/null -w '%{http_code}\n' https://api.openai.com/v1/models
    # expect: 401  (anything other than a connection error means egress works)
NOTE

请在专用命名空间中创建 GatewayAIGatewayRoute(例如 maas-system),不要创建在 Envoy Gateway 控制平面命名空间 envoy-gateway-system 中。放置在控制平面命名空间中的网关可能不会将 AI Gateway 请求处理过滤器和 SecurityPolicy 应用到其监听器上,这会静默破坏路由和策略执行。另请参阅 Envoy AI Gateway

步骤

存储上游凭证

创建保存提供商 API 密钥的 Secret。对于 type: APIKeydata-map key 必须严格为 apiKey —— BackendSecurityPolicy 会按名称查找该字段,因此使用 --from-literal=key=... 会导致上游调用未通过身份验证,即使策略报告为 Accepted

kubectl -n <your-namespace> create secret generic openai-key \
  --from-literal=apiKey="$OPENAI_API_KEY"   # data-map key must be 'apiKey'

使用 BackendSecurityPolicy 注入目标为后端的提供商凭证。type 字段用于选择提供商的身份验证方案。

apiVersion: aigateway.envoyproxy.io/v1alpha1
kind: BackendSecurityPolicy
metadata:
  name: openai-auth
  namespace: <your-namespace>
spec:
  type: APIKey
  apiKey:
    secretRef:
      name: openai-key  # Secret holding the provider API key (data key 'apiKey')
  targetRefs:
    - group: aigateway.envoyproxy.io
      kind: AIServiceBackend
      name: openai-backend

type 字段接受 APIKeyAWSCredentialsAzureAPIKeyAzureCredentialsGCPCredentialsAnthropicAPIKey。每种类型都需要匹配的凭证块和一组匹配的 Secret 数据键:

type凭证块必需的 Secret 数据键
APIKeyapiKey.secretRefapiKey
AWSCredentialsawsCredentials.credentialsFile.secretRefcredentials(AWS shared-credentials INI;外加内联 region
AzureAPIKeyazureAPIKey.secretRefapiKey
AzureCredentialsazureCredentials.clientSecretRefclient-secret(外加内联 clientID/tenantID
GCPCredentialsgcpCredentials.credentialsFile.secretRefservice_account.json(外加内联 projectName/region;或者使用 gcpCredentials.workloadIdentityFederationConfig 实现无密钥 WIF)
AnthropicAPIKeyanthropicAPIKey.secretRefapiKey

当上游身份验证方案错误时,上游通常会返回 401/403。当 Secret 的键名错误时(例如使用 key: 而不是 apiKey:),故障表现更难以识别:BackendSecurityPolicy 仍会报告 Accepted=True,但控制器日志会显示 failed to get backend auth from backend security policy. Skipping this backend. ... error: secret <name> does not contain key apiKey,并将该后端从路由中移除,因此发往该后端的请求会超时,而不是返回清晰的 401。引入新凭证时,请跟踪控制器日志:

kubectl -n envoy-gateway-system logs deploy/ai-gateway-controller -c ai-gateway-helm \
  | grep -E 'backend security policy|does not contain key'

定义提供商后端

有两个资源协同工作:Backend(Envoy Gateway)向数据平面说明要连接的网络端点,而 AIServiceBackend(Envoy AI Gateway)则向 AI 过滤器说明要转换成的提供商 schema

首先,将上游端点声明为 Backend

apiVersion: gateway.envoyproxy.io/v1alpha1
kind: Backend
metadata:
  name: openai-endpoint
  namespace: <your-namespace>
spec:
  endpoints:
    - fqdn:
        hostname: api.openai.com
        port: 443

然后引用该 Backend,将提供商注册为 AIServiceBackend

apiVersion: aigateway.envoyproxy.io/v1alpha1
kind: AIServiceBackend
metadata:
  name: openai-backend
  namespace: <your-namespace>
spec:
  schema:
    name: OpenAI
  backendRef:
    name: openai-endpoint  # Backend pointing at the provider host
    kind: Backend
    group: gateway.envoyproxy.io
  • schema.name:网关必须使用的上游协议。常见值包括:OpenAIAWSBedrockAzureOpenAIGCPVertexAIAnthropic。网关会先将传入的兼容 OpenAI 请求转换为该 schema,再转发出去。
  • backendRef:必须指向 Backendgateway.envoyproxy.io 组),而不是 Service——AI 过滤器依赖 Backend 来处理面向公共端点的 FQDN 和 TLS。

确认这两个资源都已完成协调:

kubectl get backend,aiservicebackend -n <your-namespace>
# AIServiceBackend shows ACCEPTED=True immediately;
# the Backend STATUS column stays empty until the next step's AIGatewayRoute
# actually references this AIServiceBackend — Envoy Gateway only reconciles a
# Backend once at least one HTTPRoute targets it.

按模型路由并进行故障切换

在一个 AIGatewayRoute 规则中引用多个后端,并设置 priority,以便网关从主后端故障切换到备用后端:

apiVersion: aigateway.envoyproxy.io/v1alpha1
kind: AIGatewayRoute
metadata:
  name: <aigatewayroute-name>
  namespace: <your-namespace>
spec:
  # ... parentRefs ...
  rules:
    - matches:
        - headers:
            - name: x-ai-eg-model
              type: Exact
              value: gpt-4o
      backendRefs:
        - name: openai-backend
          priority: 0   # primary
        - name: azure-backend
          priority: 1   # used when the primary is unavailable
  • matches.headers[x-ai-eg-model]:AI 过滤器会从请求体中解析 model 字段,并将其写入此 header 以供路由使用。因此,请求中的 "model":"gpt-4o" 才会进入该匹配条件——调用方无需手动设置 header。
  • priority:Envoy 使用优先级级别故障切换。只要 priority-0 组有足够的健康端点,就会承载所有流量;只有当 priority-0 退化时,priority-1 组才会接收流量——这由 Envoy 的 overprovisioning factor 和 panic threshold 决定,而不是严格要求“priority-0 的每个端点都必须宕机”。此 priority 字段会覆盖 Backend 级别的 fallback 设置。故障切换是自动的,但需要几秒钟而不是毫秒级;不要将其用于尾延迟预算。

验证

向网关发送一个兼容 OpenAI 的请求,并确认它能够到达提供商,客户端的 Authorization header 已被 BSP 注入的密钥替换,同时返回包含 token 使用量的有效响应:

# A deliberately-bogus client Authorization to prove the gateway strips it
# and substitutes the upstream key from the BackendSecurityPolicy.
curl -sv http://<gateway-address>/v1/chat/completions \
  -H 'Authorization: Bearer client-token-that-should-be-replaced' \
  -H 'Content-Type: application/json' \
  -d '{"model":"gpt-4o","messages":[{"role":"user","content":"ping"}]}'

成功响应(带有 usage 对象的 200 OK)意味着上游凭证已被注入且路由已解析。要检查实际命中上游的请求,可在 EnvoyProxy 资源上启用 Envoy 的访问日志,或者临时路由到一个调试回显后端;上游请求中的 Authorization header 应携带来自 openai-key Secret 的值,而不是上面的伪造客户端值。

要验证故障切换,可以通过将主 Backend 指向一个不可达主机(hostname: invalid.example.invalid)并维持几秒来模拟主服务中断,然后观察流量切换到备用服务;响应体中的 model 字段会反映新的提供商。

了解更多