部署单机LLM推理服务
本文以Qwen3-32B模型为例,演示如何在CCE中使用vLLM及SGLang部署单机LLM推理服务。
背景知识
- Qwen3-32B
Qwen3-32B 是通义千问系列最新一代的大型语言模型,基于328亿参数的密集模型架构,兼具卓越的推理能力与高效的对话性能。其最大特色在于支持思考模式与非思考模式的无缝切换。在复杂逻辑推理、数学计算和代码生成任务中表现出众,而在日常对话场景下也可高效响应。模型具备出色的指令遵循、多轮对话、角色扮演和创意写作能力,并在Agent任务中实现领先的工具调用表现。原生支持32K上下文,结合YaRN技术可扩展至131K。同时,支持100多种语言,具备强大的多语言理解与翻译能力,适用于全球化应用场景。有关更多详细信息,请参阅博客、GitHub和文档。
- vLLM
vLLM是一个高效、轻量的大型语言模型推理引擎,它采用创新的 PagedAttention 技术,高效管理KV缓存,支持连续批处理、CUDA/HIP 图加速、chunked prefill和Speculative decoding,显著提升服务吞吐与响应速度。支持多种量化格式(如 GPTQ、AWQ、INT4/8、FP8)及 FlashAttention 等优化内核。vLLM 兼容 Hugging Face和ModeScope模型,支持TP、PP、DP和EP并行,提供流式输出和 OpenAI 兼容 API。支持 NVIDIA、AMD、Intel 等多种硬件,覆盖 Qwen、Deepseek、Llama、E5-Mistral等主流模型,广泛应用于对话系统、内容生成、AI Agent 等场景,是构建大模型应用的理想选择。更多关于vLLM框架的信息,请参见vLLM GitHub。
- SGLang
SGLang 是一个高性能的大型语言模型与多模态模型服务推理引擎,通过前后端协同设计,提升模型交互速度与控制能力。其后端支持 RadixAttention(前缀缓存)、零开销 CPU 调度、PD分离、Speculative decoding、连续批处理、PagedAttention、TP/DP/PP/EP并行、结构化输出、chunked prefill及多种量化技术(FP8/INT4/AWQ/GPTQ)和多LoRA批处理,显著提升推理效率。前端提供灵活编程接口,支持链式生成、高级提示、控制流、多模态输入、并行处理和外部交互,便于构建复杂应用。支持 Qwen、DeepSeek、Llama等生成模型,E5-Mistral等嵌入模型以及 Skywork 等奖励模型,易于扩展新模型。更多关于SGLang推理引擎的信息,请参见SGLang GitHub。
前提条件
已创建CCE集群且集群版本为1.31及以上,并且已经为集群添加GPU节点。
具体操作,请参见创建CCE托管集群。
本文要求GPU显存需大于64GB,推荐使用bcc.lsgn7ec.c176m1952.8h20-141.2d规格(请联系客户经理申请GPU规格邀测)。
模型部署
步骤一:准备Qwen3-32B模型文件
- 执行以下命令从ModelScope下载Qwen-32B模型。
请确认是否已安装git-lfs插件,如未安装可执行
yum install git-lfs
或者apt-get install git-lfs
安装。更多的安装方式,请参见安装git-lfs。
1git lfs install
2GIT_LFS_SKIP_SMUDGE=1 git clone https://www.modelscope.cn/Qwen/Qwen3-32B.git
3cd Qwen3-32B/
4git lfs pull
- 登录PFS控制台,将集群中的节点挂载到PFS挂载服务中,参考控制台操作文档和命令行操作文档。如何创建PFS文件系统,创建挂载服务并绑定存储实例,请参考创建文件系统,创建挂载服务,绑定存储实例。
- 在PFS中创建目录,将模型拷贝到PFS中。
1mkdir Qwen-models
2cp /Qwen3-32B/ <pfs目录>/Qwen-models/
- 创建PV和PVC。为目标集群配置存储卷PV和存储声明PVC。请参考使用并行文件存储PFS L2。
- 通过Yaml新建PV示例:
1apiVersion: v1
2kind: PersistentVolume
3metadata:
4 name: <your-pv-name> #本示例中为test-pv-02
5spec:
6 accessModes:
7 - ReadOnlyMany
8 capacity:
9 storage: 500Gi
10 local:
11 path: <your-pfs-path> #本示例中为/pfs/pfs-qnL8Jh/Qwen-models
12 nodeAffinity:
13 required:
14 nodeSelectorTerms:
15 - matchExpressions:
16 - key: ready-for-pfsl2
17 operator: In
18 values:
19 - "true"
20 persistentVolumeReclaimPolicy: Retain
21 storageClassName: local-volume
22 volumeMode: Filesystem
- 通过Yaml新建PVC示例:
1apiVersion: v1
2kind: PersistentVolumeClaim
3metadata:
4 finalizers:
5 - kubernetes.io/pvc-protection
6 name: <your-pvc-name> #本示例中为test-pvc-02
7 namespace: default
8spec:
9 accessModes:
10 - ReadOnlyMany
11 resources:
12 requests:
13 storage: 500Gi
14 storageClassName: local-volume
15 volumeMode: Filesystem
16 volumeName: <your-pv-name> #本示例中为test-pv-02
步骤二:部署推理服务
参考以下YAML代码示例,在CCE中使用vLLM及SGLang推理引擎部署单机LLM推理服务。
vLLM框架部署单机推理服务:创建StatefulSet工作负载
1apiVersion: apps/v1
2kind: StatefulSet
3metadata:
4 labels:
5 # for prometheus to scrape
6 baidu-cce/inference-workload: vllm-inference-dshm
7 baidu-cce/inference_backend: vllm
8 name: vllm-inference-dshm-002
9 namespace: default
10spec:
11 replicas: 1
12 selector:
13 matchLabels:
14 baidu-cce/inference-workload: vllm-inference-dshm
15 baidu-cce/inference_backend: vllm
16 template:
17 metadata:
18 labels:
19 baidu-cce/inference-workload: vllm-inference-dshm
20 baidu-cce/inference_backend: vllm
21 spec:
22 nodeSelector:
23 gputype: h20
24 volumes:
25 - name: bos-pvc
26 persistentVolumeClaim:
27 claimName: <your-pvc-name> #本示例中为test-pvc-02
28 readOnly: true
29 - name: dshm
30 emptyDir:
31 medium: Memory
32 sizeLimit: 15Gi
33 containers:
34 - command:
35 - sh
36 - -c
37 - vllm serve <your-Qwen3-32B-path> --port 8000 --trust-remote-code --gpu-memory-utilization 0.85 --tensor-parallel-size 2
38 image: registry.baidubce.com/ai-native-dev/infer-manager/vllm/vllm-openai:v0.10.0
39 name: vllm
40 ports:
41 - containerPort: 8000
42 name: http
43 readinessProbe:
44 initialDelaySeconds: 30
45 periodSeconds: 10
46 tcpSocket:
47 port: 8000
48 resources:
49 limits:
50 nvidia.com/gpu: "2"
51 memory: "64Gi"
52 cpu: "16"
53 requests:
54 nvidia.com/gpu: "2"
55 memory: "64Gi"
56 cpu: "16"
57 volumeMounts:
58 - mountPath: <your-model-path> #本示例中为/Qwen-models
59 name: bos-pvc
60 - mountPath: /dev/shm
61 name: dshm
SGLang部署单机推理服务:创建StatefulSet工作负载
1apiVersion: apps/v1
2kind: StatefulSet
3metadata:
4 labels:
5 baidu-cce/inference-workload: sgl-inference
6 baidu-cce/inference_backend: sglang
7 name: sgl-inference-custom-cu124
8 namespace: default
9spec:
10 persistentVolumeClaimRetentionPolicy:
11 whenDeleted: Retain
12 whenScaled: Retain
13 podManagementPolicy: OrderedReady
14 replicas: 1
15 revisionHistoryLimit: 10
16 selector:
17 matchLabels:
18 baidu-cce/inference-workload: sgl-inference
19 baidu-cce/inference_backend: sglang
20 serviceName: ""
21 template:
22 metadata:
23 annotations:
24 kubectl.kubernetes.io/restartedAt: "2025-08-30T19:30:01+08:00"
25 creationTimestamp: null
26 labels:
27 baidu-cce/inference-workload: sgl-inference
28 baidu-cce/inference_backend: sglang
29 spec:
30 containers:
31 - command:
32 - sh
33 - -c
34 - python -m sglang.launch_server --model-path /Qwen-models/Qwen3-32B --tp 2 --trust-remote-code --host 0.0.0.0 --port 8000 --enable-metrics
35 image: registry.baidubce.com/ai-native-dev/infer-manager/dev-image:0.3.ubuntu2204-py313-sglang0.5.1.post3-cuda12.4
36 imagePullPolicy: IfNotPresent
37 name: sglang
38 ports:
39 - containerPort: 8000
40 name: http
41 protocol: TCP
42 readinessProbe:
43 failureThreshold: 3
44 initialDelaySeconds: 30
45 periodSeconds: 10
46 successThreshold: 1
47 tcpSocket:
48 port: 8000
49 timeoutSeconds: 1
50 resources:
51 limits:
52 cpu: "16"
53 memory: 64Gi
54 nvidia.com/gpu: "2"
55 requests:
56 cpu: "16"
57 memory: 64Gi
58 nvidia.com/gpu: "2"
59 terminationMessagePath: /dev/termination-log
60 terminationMessagePolicy: File
61 volumeMounts:
62 - mountPath: <your-model-path> #本示例中为/Qwen-models
63 name: bos-pvc
64 - mountPath: /dev/shm
65 name: dshm
66 dnsPolicy: ClusterFirst
67 nodeSelector:
68 node.kubernetes.io/cce-instance-type: ehc.lgn5.c128m1024.8a800.8re.4d
69 restartPolicy: Always
70 schedulerName: default-scheduler
71 securityContext: {}
72 terminationGracePeriodSeconds: 30
73 volumes:
74 - name: bos-pvc
75 persistentVolumeClaim:
76 claimName: <your-pv-name> #本示例中为test-pvc-02
77 readOnly: true
78 - emptyDir:
79 medium: Memory
80 sizeLimit: 15Gi
81 name: dshm
82 updateStrategy:
83 rollingUpdate:
84 partition: 0
85 type: RollingUpdate
步骤三:验证推理服务
- 登录容器,执行以下命令,向模型推理服务发送一条示例的模型推理请求。
1curl http://127.0.0.1:8000/v1/chat/completions -H "Content-Type: application/json" -d '{"model": "/Qwen-models/Qwen3-32B", "messages": [{"role": "user", "content": "测试一下,用python代码写出hello world"}], "max_tokens": 2000, "temperature": 0.7, "top_p": 0.9, "seed": 10}'
预期输出:
1{"id":"chatcmpl-c12bc2157cbb4f74881a66e4647aeb91","object":"chat.completion","created":1759130450,"model":"/Qwen-models/Qwen3-32B","choices":[{"index":0,"message":{"role":"assistant","content":"<think>\n好的,用户让我用Python写一个“Hello, World!”程序。这看起来很简单,但我得仔细想想怎么最好地完成这个任务。首先,我应该回忆一下Python的基本语法。记得在Python中,打印语句是用print函数。那正确的语法应该是print(\"Hello, World!\")。不过,用户可能有不同的需求,比如是否需要考虑大小写或者标点符号?比如,用户写的是“hello world”中间没有逗号,但通常标准的写法是带逗号的。不过用户示例中的输出是“Hello, World!”,所以可能用户希望的是标准的版本。\n\n接下来,我需要考虑用户可能的水平。如果用户是初学者,可能需要一个最简单的例子,直接使用print函数。但有没有其他可能性?比如,用户是否希望用变量存储字符串再打印?或者是否有其他特殊要求?比如,多行输出?不过根据问题描述,用户只要求写出hello world,所以应该保持最简单的方式。\n\n另外,需要注意Python的版本问题。比如,在Python 2中,print是一个语句,不需要括号,但在Python 3中,print是一个函数,必须用括号。用户可能使用的是Python 3,所以应该给出print(\"Hello, World!\")的写法。不过,现在Python 2已经不再维护了,所以可能用户都是用Python 3,但最好还是确认一下。不过用户没有说明,所以默认使用Python 3的语法 \n\n还有,用户是否需要解释代码?比如,是否需要注释或者说明?用户的问题只是让写出代码,所以可能不需要注释。但有时候用户可能希望有简单的解释。不过根据用户的问题,可能只需要代码。不过,为了更全面,可能在回答中简单说明代码的作用,但用户的问题没有明确要求,所以可能保持简洁。\n\n有没有可能用户有其他隐藏的需求?比如,希望用不同的方式输出,比如使用转义字符或者多行字符串?比如,print(\"Hello\\nWorld!\"),但这样可能不符合用户的要求。用户明确说“hello world”作为一个字符串,所以应该是一行输出。所以正确的做法是直接使用print函数输出带逗号的字符串。\n\n另外,检查是否有拼写错误。比如,是否应该用双引号还是单引号?Python中两者都可以,但通常双引号更常见,尤其是在字符串内部没有单引号的情况下。所以选择双引号更合适。\n\n最后,测试一下代码是否正确。在Python环境中运行print(\"Hello, World!\")应该会输出正确的结果。确认没有语法错误,比如漏掉冒号或者括号。确保代码正确无误。\n</think>\n\n以下是使用 Python 编写的 \"Hello, World!\" 程序:\n\n```python\nprint(\"Hello, World!\")\n```\n\n### 代码说明:\n1. 使用 Python 内置的 `print()` 函数输出字符串。\n2. 字符串内容为 `\"Hello, World!\"`,符合标准格式(包含逗号和感叹号)。\n3. 语法适用于 Python 3(推荐当前主流版本)。\n\n### 运行方式:\n1. 将代码保存为 `hello.py` 文件,使用 Python 解释器运行:\n ```bash\n python hello.py\n ```\n2. 或直接在 Python 交互式环境中输入代码。\n\n### 输出结果:\n```\nHello, World!\n```","refusal":null,"annotations":null,"audio":null,"function_call":null,"tool_calls":[],"reasoning_content":null},"logprobs":null,"finish_reason":"stop","stop_reason":null}],"service_tier":null,"system_fingerprint":null,"usage":{"prompt_tokens":17,"total_tokens":721,"completion_tokens":704,"prompt_tokens_details":null},"prompt_logprobs":null,"kv_transfer_params":null}
输出结果表明模型可以根据给定的输入(在这个例子中是一条测试消息,用python代码写出hello world)生成相应的回复。