使用ASM回退功能构建高可用的LLM服务

LLM场景中,业务应用需要对接内部或外部的基础模型服务。服务网格 ASM(Service Mesh)支持同时对接多个基础模型服务,并且可以实现当一个模型服务不可用时,自动回退到另一个模型服务,助力企业实现LLM应用的高可用。本文介绍如何在对接LLM服务时使用流量回退功能。

前提条件

步骤一:创建两个LLMProvider

  1. 使用以下内容创建provider.yaml。此YAML将会在ASM中创建两个LLMProvider,一个是测试Provider,用于模拟Provider出现无法提供服务时的场景,另一个是可以正常使用的通义千问Provider。

    apiVersion: istio.alibabacloud.com/v1beta1
    kind: LLMProvider
    metadata:  
      name: asm-llm-provider-test
    spec:
      host: asm-llm-provider-test.com
      path: /compatible-mode/v1/chat/completions
      workloadSelector:
        labels:
          app: sleep
      configs:
        defaultConfig:
          openAIConfig:
            model: test-model
            stream: false
            apiKey: test-api-key
    ---
    apiVersion: istio.alibabacloud.com/v1beta1
    kind: LLMProvider
    metadata:  
      name: dashscope-qwen
    spec:
      host: dashscope.aliyuncs.com
      path: /compatible-mode/v1/chat/completions
      workloadSelector:
        labels:
          app: sleep
      configs:
        defaultConfig:
          openAIConfig:
            model: qwen1.5-72b-chat  # 千问开源系列大模型
            stream: false
            apiKey: ${dashscopeAPI_KEY}
    您可以根据实际需求修改.spec.configs.defaultConfig.openAIConfig.model来体验其他模型。更多千问开源模型,请参见文本生成-通义千问-开源版
  2. 使用ASMkubeconfig执行以下命令,部署LLMProvider。

    kubectl apply -f provider.yaml

步骤二:配置异常端点驱逐策略以及回退策略

异常端点驱逐策略需要在目标规则中进行配置。通过配置驱逐策略和回退策略,可以在LLM请求出现异常时,驱逐对应的Provider,并将请求流量回退到可用的Provider上。LLMProvider资源默认会自动生成对应的目标规则,因此需要修改对应的目标规则资源来添加异常端点驱逐策略。

  1. 执行以下命令,为LLMProvider asm-llm-provider-test配置注解以开启自定义目标规则,防止修改后的目标规则被ASM控制面覆盖。

    kubectl annotate llmprovider asm-llm-provider-test asm.alibabacloud.com/custom-destinationrule=true
  2. 执行以下命令,修改目标规则,增加异常端点驱逐策略。

    kubectl edit DestinationRule/asm-llm-provider-test

    修改后目标规则如下。

    apiVersion: networking.istio.io/v1beta1
    kind: DestinationRule
    metadata:
      name: asm-llm-provider-test
      namespace: default
    spec:
      host: asm-llm-provider-test.com
      trafficPolicy:
        portLevelSettings:
        - port:
            number: 80
          tls:
            mode: SIMPLE
            sni: asm-llm-provider-test
          outlierDetection:
            consecutive5xxErrors: 1
            interval: 1s
            baseEjectionTime: 10s
            maxEjectionPercent: 100
            minHealthPercent: 0

    以上修改在目标规则中新增了一段outlierDetection配置。如果LLM请求在1s内出现15xx错误,将驱逐该端点,驱逐的时长为10s。

    outlierDetection配置说明如下:

    配置项

    说明

    consecutive5xxErrors

    定义在驱逐之前,允许的连续5xx错误请求的最大数量。如果达到这个阈值,将进行驱逐。默认值为5,即如果连续五次请求返回5xx错误,服务将被标记为不健康。

    interval

    定义检测间隔时间,即多长时间检查一次服务的健康状况。默认值为10s。例如,5s表示每五秒检查一次。支持格式为1h/1m/1s/1ms,最小值必须≥1ms

    baseEjectionTime

    指定服务被驱逐的基础时间。即一个服务在被标识为不健康后,将在此时间内不被重新使用,默认值为30s。支持格式为1h/1m/1s/1ms,最小值必须≥1ms

    maxEjectionPercent

    允许被驱逐的最大服务比例,防止过多服务被同时排除。例如,设置为100表示可以驱逐所有服务。默认值为10%

    minHealthPercent

    定义健康服务的最小百分比,以确保在驱逐某些服务后,仍然有足够的健康服务可供请求处理。默认值为0,表示禁用检测当前是否存在处于健康状态的服务,即允许所有服务被标记为不健康。

    更多关于outlierDetection的配置信息,请参见OutlierDetection

  3. 创建虚拟服务,配置回退策略。

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

      apiVersion: networking.istio.io/v1alpha3
      kind: VirtualService
      metadata:
        name: test-fallback-llm-vs
        namespace: default
      spec:
        hosts:
        - asm-llm-provider-test.com
        http:
        - name: fallback-route
          route:
          - destination:
              host: asm-llm-provider-test.com
              port:
                number: 80
            fallback:
              target:
                host: dashscope.aliyuncs.com
    2. 执行以下命令,创建虚拟服务。

      kubectl apply -f vs.yaml

      此配置声明了当asm-llm-provider-test.com被判定为不健康时,请求将自动转发给dashscope.aliyuncs.com

步骤三:创建测试应用sleep

为了确保配置的asm-llm-provider-test.com可以被DNS解析,此sleep Deployment中使用hostAlias添加了静态的DNS配置。
  1. 使用以下内容,创建sleep.yaml

    展开查看YAML内容

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: sleep
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: sleep
      labels:
        app: sleep
        service: sleep
    spec:
      ports:
      - port: 80
        name: http
      selector:
        app: sleep
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: sleep
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: sleep
      template:
        metadata:
          labels:
            app: sleep
        spec:
          terminationGracePeriodSeconds: 0
          serviceAccountName: 
          hostAliases:
          - hostnames:
            - asm-llm-provider-test.com
            ip: 1.2.3.4
          containers:
          - name: sleep
            image: registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/curl:asm-sleep
            command: ["/bin/sleep", "infinity"]
            imagePullPolicy: IfNotPresent
            volumeMounts:
            - mountPath: /etc/sleep/tls
              name: secret-volume
          volumes:
          - name: secret-volume
            secret:
              secretName: sleep-secret
              optional: true
    ---
  2. 使用数据面集群的kubeconfig,执行以下命令。

    kubectl apply -f sleep.yaml

步骤四:测试

sleep Pod中连续发起两次以下LLM请求。

本文中配置的驱逐时长为10s,因此需要在10s内发起第二次请求。您可以根据实际业务需求,自行调整outlierDetection配置。
kubectl exec deployment/sleep -it -- curl http://asm-llm-provider-test.com \
--header 'Content-Type: application/json' \
--data '{
    "messages": [
        {"role": "user", "content": "请介绍你自己"}
    ]
}'

预期输出:

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

可以看到,请求直接被发送给了dashscope.aliyuncs.com。

相关文档

流量回退是流量路由中的一种重要流量管理策略,当请求链路中某个LLM Provider出现临时的不可用状态时,您可以通过配置异常驱逐和回退策略来确保服务的正常运行。若您想了解更多流量路由的应用场景,例如不同用户访问不同的LLM Provider,请参见流量路由:使用ASM高效管理LLM流量