使用ACS GPU算力构建Qwen3-32B模型推理服务

在使用容器计算服务 ACS(Container Compute Service)算力时,您无需深入了解底层硬件,也无需涉及GPU节点管理和配置即可开箱即用。ACS部署简单、支持按量付费,非常适合用于LLM推理任务,可以有效降低推理成本。本文介绍如何使用ACS GPU算力部署生产可用的Qwen3-32B模型推理服务。

背景信息

Qwen3-32B模型

Qwen3Qwen系列最新一代的大型语言模型,提供了一整套密集型和专家混合(MoE)模型。基于广泛的训练,Qwen3在推理、指令遵循、代理能力以及多语言支持方面实现了突破性进展,其主要功能包括:

  • 独特支持在单一模型中无缝切换思考模式(用于复杂逻辑推理、数学和编程)和非思考模式(用于高效的通用对话),确保在各种场景中实现最佳性能。

  • 在推理能力方面显著增强,超过了以思考模式运行的先前QwQ模型和以非思考模式运行的Qwen2.5指令模型,在数学、代码生成以及常识逻辑推理方面取得了更高的表现。

  • 出色的人类偏好对齐,在创意写作、角色扮演、多轮对话和指令遵循方面表现卓越,提供更加自然、引人入胜和沉浸的对话体验。

  • 在代理能力方面具有专业性,能够在思考模式和非思考模式下精确整合外部工具,并在复杂的基于代理任务中实现开源模型中的领先性能。

  • 支持超过100种语言和方言,具备强大的多语言指令遵循和翻译能力。

更多模型信息,请参见Qwen3-32B

vLLM

vLLM是一个高效易用的大语言模型推理服务框架,vLLM支持包括通义千问在内的多种常见大语言模型。vLLM通过PagedAttention优化、动态批量推理(continuous batching)、模型量化等优化技术,可以取得较好的大语言模型推理效率。更多关于vLLM框架的信息,请参见vLLM GitHub代码库

前提条件

  • 首次使用阿里云容器计算服务 ACS(Container Compute Service)时,需要为服务账号授予系统默认角色。当且仅当该角色被正确授予后,ACS才能正常地调用相关服务(ECS、OSS、NAS、CPFS、SLB等),创建集群以及保存日志等。具体操作,请参见首次使用容器计算服务

  • 已使用kubectl连接Kubernetes集群。具体操作,请参见获取集群kubeconfig并通过kubectl工具连接集群

GPU实例规格和成本预估

在推理阶段主要占用显存的是模型参数,可以通过以下公式计算。

模型参数量为:32B(即320亿),精度数据类型字节数为:默认精度16位浮点数 / 8位每字节 = 2字节。

除了加载模型占用的显存之外,还需要考虑运算时所需的KV Cache大小和GPU利用率,通常会预留一部分buffer,因此推荐使用80 GiB显存以上的资源配置:GPU:1卡,CPU:22 vCPU,内存:128 GiB。您可以参考规格推荐表GPU计算类型卡型规格来选择合适的实例规格。关于如何计算ACS GPU实例产生的费用,请参见计费说明

说明
  • 在使用ACS GPU实例时,实例规格同样遵循ACS Pod规格规整逻辑

  • ACS Pod默认提供30 GiB的免费的临时存储空间(EphemeralStorage),本文中使用的推理镜像占用约9.8 GiB。如果该存储空间大小无法满足您的需求,您可以自定义增加临时存储空间大小。详细操作,请参见增加临时存储空间大小

操作步骤

说明

Qwen3-32B模型文件大小约65G,下载和上传模型文件通常需要较长时间。您可以提交工单,快速将模型文件复制到您的OSS Bucket。

步骤一:准备模型数据

大语言模型因其庞大的参数量,需要占用大量的磁盘空间来存储模型文件。建议您使用NAS存储卷或OSS存储卷来持久化存储模型文件,以下步骤以使用OSS存储Qwen3-32B模型文件作为示例。

  1. 执行以下命令下载Qwen3-32B模型。

    说明

    请确认是否已安装git-lfs插件,如未安装可执行yum install git-lfs或者apt-get install git-lfs安装。更多的安装方式,请参见安装git-lfs

    git lfs install
    GIT_LFS_SKIP_SMUDGE=1 git clone https://www.modelscope.cn/Qwen/Qwen3-32B.git
    cd Qwen3-32B
    git lfs pull
  2. OSS中创建目录,将模型上传至OSS。

    说明

    关于ossutil工具的安装和使用方法,请参见安装ossutil

    ossutil mkdir oss://<your-bucket-name>/models/Qwen3-32B
    ossutil cp -r ./Qwen3-32B oss://<your-bucket-name>/models/Qwen3-32B
  3. 创建PVPVC。为目标集群配置名为llm-model的存储卷PV和存储声明PVC。具体操作,请参见使用OSS静态存储卷

    控制台操作示例

    以下为示例PV的基本配置信息:

    配置项

    说明

    存储卷类型

    OSS

    名称

    llm-model

    访问证书

    配置用于访问OSSAccessKey IDAccessKey Secret。

    Bucket ID

    选择上一步所创建的OSS Bucket。

    OSS Path

    选择模型所在的路径,如/models/Qwen3-32B

    以下为示例PVC的基本配置信息:

    配置项

    说明

    存储声明类型

    OSS

    名称

    llm-model

    分配模式

    选择已有存储卷。

    已有存储卷

    单击选择已有存储卷链接,选择已创建的存储卷PV。

    kubectl操作示例

    以下为示例YAML:

    apiVersion: v1
    kind: Secret
    metadata:
      name: oss-secret
    stringData:
      akId: <your-oss-ak> # 配置用于访问OSSAccessKey ID
      akSecret: <your-oss-sk> # 配置用于访问OSSAccessKey Secret
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: llm-model
      labels:
        alicloud-pvname: llm-model
    spec:
      capacity:
        storage: 150Gi 
      accessModes:
        - ReadOnlyMany
      persistentVolumeReclaimPolicy: Retain
      csi:
        driver: ossplugin.csi.alibabacloud.com
        volumeHandle: llm-model
        nodePublishSecretRef:
          name: oss-secret
          namespace: default
        volumeAttributes:
          bucket: <your-bucket-name> # bucket名称
          url: <your-bucket-endpoint> # Endpoint信息,如oss-cn-hangzhou-internal.aliyuncs.com
          otherOpts: "-o umask=022 -o max_stat_cache_size=0 -o allow_other"
          path: <your-model-path> # 本示例中为/models/Qwen3-32B/
    ---
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: llm-model
    spec:
      accessModes:
        - ReadOnlyMany
      resources:
        requests:
          storage: 30Gi
      selector:
        matchLabels:
          alicloud-pvname: llm-model

步骤二:部署模型

执行下列命令,基于vLLM模型推理框架部署Qwen3-32B模型的推理服务。

该推理服务暴露与OpenAI兼容的HTTP API。下列命令将模型参数文件视作是一种特殊类型的数据集合,挂载到推理服务容器的指定位置(/models/Qwen3-32B)。--max-model-len设置了该模型最大可处理的Token长度,增大该配置项可获得更好的模型对话效果,但是可能会占用更多GPU显存资源。

说明

本示例使用的是cn-beijing地域的VPC内网镜像,以减少镜像拉取的时间。若您希望使用其他地域的内网镜像,可以根据使用方式手动调整YAML中的镜像地址。

kubectl apply -f- <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: qwen3-32b
  name: qwen3-32b
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: qwen3-32b
  template:
    metadata:
      labels:
        app: qwen3-32b
        alibabacloud.com/compute-class: gpu
        alibabacloud.com/compute-qos: default
        alibabacloud.com/gpu-model-series: GU8TF
    spec:
      volumes:
        - name: model
          persistentVolumeClaim:
            claimName: llm-model
        - name: dshm
          emptyDir:
            medium: Memory
            sizeLimit: 64Gi
      containers:
        - command:
            - sh
            - -c
            - vllm serve /models/Qwen3-32B/ --port 8000 --trust-remote-code --max-model-len 32768 --gpu-memory-utilization 0.98
          image: acs-registry-vpc.cn-beijing.cr.aliyuncs.com/egslingjun/inference-nv-pytorch:25.05-vllm0.8.5.post1-pytorch2.7-cu128-20250513-serverless
          name: vllm
          ports:
            - containerPort: 8000
          readinessProbe:
            tcpSocket:
              port: 8000
            initialDelaySeconds: 30
            periodSeconds: 30
          resources:
            limits:
              nvidia.com/gpu: "1"
              cpu: "22"
              memory: 128G
          volumeMounts:
            - mountPath: /models/Qwen3-32B/
              name: model
            - mountPath: /dev/shm
              name: dshm
---
apiVersion: v1
kind: Service
metadata:
  name: qwen3-32b
spec:
  type: LoadBalancer
  ports:
    - port: 8000
      protocol: TCP
      targetPort: 8000
  selector:
    app: qwen3-32b
EOF

步骤三:验证推理服务

  1. 获取服务的公网IP 。

    export EXTERNAL_IP=$(kubectl get svc qwen3-32b -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
    echo ${EXTERNAL_IP}

    预期输出:

    60.xxx.xxx.225
  2. 发送一条推理请求。

    curl -H "Content-Type: application/json" \
         http://${EXTERNAL_IP}:8000/v1/chat/completions \
         -d '{
               "model": "/models/Qwen3-32B/",
               "messages": [
                 {
                   "role": "user",
                   "content": "Say this is a test!"
                 }
               ],
               "max_tokens": 512,
               "temperature": 0.7,
               "top_p": 0.9,
               "seed": 10
             }'

    预期输出:

    {"id":"chatcmpl-2e5fdb02c1b246dc96cxxxxxx29c0fd3","object":"chat.completion","created":1747042811,"model":"/models/Qwen3-32B/","choices":[{"index":0,"message":{"role":"assistant","reasoning_content":null,"content":"<think>\nOkay, the user wrote \"Say this is a test!\" So I need to respond to that. Let me think. They probably want me to acknowledge that it's a test. Maybe they're checking how I respond to test prompts. I should confirm that it's a test and ask if there's something specific they need help with. Keep it friendly and open-ended. Let me make sure I don't miss any underlying needs. Maybe they want to see if I follow instructions or handle certain types of queries. Alright, a simple response should work here.\n</think>\n\nYou're absolutely right—this is a test! Is there something specific you'd like me to test or help with? Let me know, and I'll do my best!","tool_calls":[]},"logprobs":null,"finish_reason":"stop","stop_reason":null}],"usage":{"prompt_tokens":14,"total_tokens":167,"completion_tokens":153,"prompt_tokens_details":null},"prompt_logprobs":null}