集群内客户端通过ASM出口网关访问LLM服务

ASM支持通过出口网关访问外部LLM服务,主要适用于请求发起方位于集群内的场景。本文介绍当请求方位于集群内且注入了sidecar时,如何通过出口网关访问集群外服务。

前提条件

功能概述

未引入出口网关时,客户端请求被Sidecar拦截,由Sidecar代理向LLM提供商发起请求。Sidecar和客户端部署在同一个Pod中,这种使用方式存在诸多安全风险,可能出现API_KEY泄漏、未授权访问等问题,如果您比较对这方面风险比较敏感的话,请务必使用出口网关路由模型。

在请求链路中引入ASM出口网关之后,由于出口网关的独立于客户端部署,您可以通过ACK集群提供的RBAC机制方便的限制可以操作出口网关的用户,进而提升出口网关的安全水位。此时,API_KEY动态添加、认证鉴权策略全部在出口网关上执行,您可以使用全量的ASM网关安全能力。

本文演示的请求链路如下所示:

image

步骤一:创建出口网关和网关规则

  1. 创建出口网关,配置开放80端口并开启支持双向TLS认证。具体操作,请参见创建出口网关

  2. 使用以下内容,创建egress-gw.yaml。

    apiVersion: networking.istio.io/v1beta1
    kind: Gateway
    metadata:
      name: egress-gw
      namespace: istio-system
    spec:
      selector:
        istio: egressgateway
      servers:
        - hosts:
            - '*'
          port:
            name: http
            number: 80
            protocol: HTTPS
          tls:
            mode: ISTIO_MUTUAL
  3. 使用ASM实例的kubeconfig,执行以下命令,创建网关规则。

    kubectl apply -f egress-gw.yaml

步骤二:创建仅在出口网关生效的LLMProvider

仅在出口网关生效的LLMProvider可以确保API KEY只会存在于出口网关的内存中,不会轻易被客户端获取。

  1. 使用以下内容,创建dashscope-qwen.yaml。

    apiVersion: istio.alibabacloud.com/v1beta1
    kind: LLMProvider
    metadata:  
      name: dashscope-qwen
      namespace: istio-system
    spec:
      workloadSelector:
        labels:
          istio: egressgateway
      host: dashscope.aliyuncs.com
      path: /compatible-mode/v1/chat/completions
      configs:
        defaultConfig:
          openAIConfig:
            model: qwen-1.8b-chat  # 千问开源系列大模型
            stream: false
            apiKey: ${API_KEY}
  2. 执行以下命令,创建LLMProvider。

    kubectl apply -f dashscope-qwen.yaml

步骤三:创建LLMRoute

  1. 使用以下内容创建dashscope-route.yaml,将流量指向出口网关。

    apiVersion: istio.alibabacloud.com/v1beta1
    kind: LLMRoute
    metadata:  
      name: dashscope-route
    spec:
      host: dashscope.aliyuncs.com
      gateways:
      - mesh
      - istio-system/egress-gw
      rules:
      - name: mesh-route # sidecar收到dashscope.aliyuncs.com的请求之后,转发给出口网关
        matches:
        - gateways:
          - mesh
        backendRefs:
        - providerHost: istio-egressgateway.istio-system.svc.cluster.local
      - name: egress-gw-route # 出口网关收到dashscope.aliyuncs.com的请求之后,转发给真正的provider
        matches:
        - gateways:
          - istio-system/egress-gw
        backendRefs:
        - providerHost: dashscope.aliyuncs.com
  2. 执行以下命令,创建LLMRoute。

    kubectl apply -f dashscope-route.yaml

步骤四:执行测试

使用ACK集群kubeconfig,执行以下命令发起测试。

kubectl exec deployment/sleep -it -- curl --location 'http://dashscope.aliyuncs.com' \
--header 'Content-Type: application/json' \
--data '{
    "messages": [
        {"role": "user", "content": "请介绍你自己"}
    ]
}'

预期输出:

{"choices":[{"message":{"role":"assistant","content":"我是来自阿里云的大规模语言模型,我叫通义千问。我的主要功能是回答用户的问题、提供信息和进行对话交流。我可以理解用户的提问,并基于自然语言生成相应的答案或建议。我也可以学习新的知识,并将其应用于各种场景中。如果您有任何问题或需要帮助,请随时告诉我,我会尽力为您提供支持。"},"finish_reason":"stop","index":0,"logprobs":null}],"object":"chat.completion","usage":{"prompt_tokens":3,"completion_tokens":72,"total_tokens":75},"created":1720680044,"system_fingerprint":null,"model":"qwen-1.8b-chat","id":"chatcmpl-1c33b950-3220-9bfe-9066-xxxxxxxxxxxx"}

步骤五:配置授权策略

  1. 使用以下内容,创建authpolicy.yaml。

    apiVersion: security.istio.io/v1beta1
    kind: AuthorizationPolicy
    metadata:
      name: test
      namespace: istio-system
    spec:
      action: DENY
      rules:
      - from:
        - source:
            principals:
            - cluster.local/ns/default/sa/sleep
        to:
        - operation:
            hosts:
            - dashscope.aliyuncs.com
      selector:
        matchLabels:
          istio: egressgateway
  2. 使用ASM kubeconfig,执行以下命令配置授权策略。

    kubectl apply -f authpolicy.yaml
  3. 再次执行步骤四中的命令发起测试。

    预期输出:

    RBAC: access denied

    可以看到请求被拒绝。

说明

ASM网关针对普通HTTP请求所具备的安全能力同样适用于LLM请求,包括完整的授权策略、JWT认证和自定义授权服务等。通过在出口网关上应用这些策略,可以更有效地保障您的应用安全。