vLLM × SkyPilot:在云与 Kubernetes 上启动并横向扩展多副本 LLM 推理服务
本文基于 vLLM 官方文档 docs/deployment/frameworks/skypilot.md 编写,讲解如何使用 SkyPilot 这一开源多云框架,将 vLLM 一键部署到云或 Kubernetes 上的单个实例,并通过内置的自动扩缩容、负载均衡与容错能力扩展为多副本服务。读完本文,你将掌握:SkyPilot YAML 任务文件中 resources / envs / setup / run 四段式的完整配置方法、sky launch 与 sky serve up 的实战命令、service 段的 readiness probe 与 replica_policy 自动扩缩容配置,以及如何把 Gradio 聊天界面挂接到服务负载均衡端点上。
一、方案概述
SkyPilot 是一个用于在任意云上运行 LLM 的开源框架。借助它,vLLM 可以在云与 Kubernetes 上以单实例或多服务副本两种形态运行与扩展。对于 Llama-3、Mixtral 等各种开源模型,SkyPilot 的示例库中也提供了更多可参考的配置。
vLLM 侧需要说明的核心事实:多副本场景下每个副本都是一个独立运行 vllm serve 的推理服务实例,SkyPilot 负责在其前面做服务发现、负载均衡与健康检查(readiness probe);而单实例场景则只是“在云节点上拉起一个 vLLM API Server + 可选 Gradio Web UI”的经典部署。
二、前置条件
在开始之前需要准备三件事:
- 模型访问权限:前往 HuggingFace 上
meta-llama/Meta-Llama-3-8B-Instruct的模型页面申请访问权限; - 安装 SkyPilot:按 SkyPilot 官方文档完成安装(可安装 nightly 版本);
- 确认云或 Kubernetes 已启用:
sky check的输出中应能看到已配置好的云账号或 Kubernetes 集群。
pip install skypilot-nightly
sky check
sky check 会检查本地已配置的云凭证(GCP、AWS 等)与 Kubernetes 上下文,未通过的云会在输出中标记为不可用,因此它是部署前的第一道检查。
三、单实例部署:YAML 任务文件逐段解析
单实例部署的核心是一份 SkyPilot YAML 任务文件(下文称为 serving.yaml)。完整配置如下,随后逐段说明:
resources:
accelerators: {L4, A10g, A10, L40, A40, A100, A100-80GB} # We can use cheaper accelerators for 8B model.
use_spot: True
disk_size: 512 # Ensure model checkpoints can fit.
disk_tier: best
ports: 8081 # Expose to internet traffic.
envs:
PYTHONUNBUFFERED: 1
MODEL_NAME: meta-llama/Meta-Llama-3-8B-Instruct
HF_TOKEN: <your-huggingface-token> # Change to your own huggingface token, or use --env to pass.
setup: |
conda create -n vllm python=3.10 -y
conda activate vllm
pip install vllm==0.4.0.post1
# Install Gradio for web UI.
pip install gradio openai
pip install flash-attn==2.5.7
run: |
conda activate vllm
echo 'Starting vllm api server...'
vllm serve $MODEL_NAME \
--port 8081 \
--trust-remote-code \
--tensor-parallel-size $SKYPILOT_NUM_GPUS_PER_NODE \
2>&1 | tee api_server.log &
echo 'Waiting for vllm api server to start...'
while ! `cat api_server.log | grep -q 'Uvicorn running on'`; do sleep 1; done
echo 'Starting gradio server...'
git clone https://github.com/vllm-project/vllm.git || true
python vllm/examples/applications/chatbot/gradio_openai_chatbot_webserver.py \
-m $MODEL_NAME \
--port 8811 \
--model-url http://localhost:8081/v1 \
--stop-token-ids 128009,128001
3.1 resources:资源选择与成本策略
accelerators:给出一个候选加速器集合{L4, A10g, A10, L40, A40, A100, A100-80GB}。SkyPilot 会在这些加速器中按“可用 + 成本”自动择优——8B 模型用更便宜的 L4/A10 级卡即可,无需默认落到 A100;use_spot: True:允许使用抢占式(spot)实例以降低成本;disk_size: 512:确保模型 checkpoint 能放得下(8B 模型权重加依赖环境需要较大的磁盘);disk_tier: best:选择性能更好的磁盘层级;ports: 8081:把 vLLM API Server 端口暴露到公网流量入口。
3.2 envs:注入环境变量
MODEL_NAME 指定模型、HF_TOKEN 用于从 HuggingFace 拉取受限模型。注意注释提示:token 可以写进 YAML,也可以不在文件里硬编码,而在启动时用 --env 参数传入(后文命令会演示这种方式,避免把凭证留在配置文件里)。
3.3 setup:构建运行环境
setup 段在节点上执行一次性的环境初始化:创建 Python 3.10 的 conda 环境 vllm,安装 vLLM、Gradio(Web UI 用)与 openai SDK,以及 flash-attn。
需要说明的是,文档中固定的是 vllm==0.4.0.post1 与 flash-attn==2.5.7 这一历史组合。在当前仓库中,vLLM 的版本与内核绑定关系已大幅演进,实际部署时建议按你所选 vLLM 版本对应发布的 flash-attn 要求来调整这两行固定版本,而不是照搬旧版本号。
3.4 run:启动 vLLM API Server 并等待就绪
run 段的执行流程是:
vllm serve $MODEL_NAME --port 8081 --trust-remote-code --tensor-parallel-size $SKYPILOT_NUM_GPUS_PER_NODE以后台方式启动 vLLM API Server,日志同时写入api_server.log;- 轮询日志,直到出现
Uvicorn running on字样才继续——这是 uvicorn 完成监听的标准启动标志; - 拉起 Gradio 聊天 Web 服务,指向本机
http://localhost:8081/v1。
其中几个值得展开的点:
--tensor-parallel-size $SKYPILOT_NUM_GPUS_PER_NODE:SKYPILOT_NUM_GPUS_PER_NODE是 SkyPilot 注入的环境变量,表示该节点分到的 GPU 数量。这样写的好处是同一份 YAML 无论调度到 1 卡还是多卡实例,张量并行度都会自动匹配。在 vLLM 当前仓库中,该参数定义于 vllm/engine/arg_utils.py(--tensor-parallel-size/-tp),--trust-remote-code同样注册在同一文件(vllm/engine/arg_utils.py),二者都是vllm serve的标准参数。stop_token_ids 128009,128001:这是 Llama-3 系列模型的结束消息 token,传给 Gradio 前端以在流式回复中正确截断。从源码看,仓库中的聊天示例 examples/applications/chatbot/gradio_openai_chatbot_webserver.py 会将其解析为整数列表后放入 OpenAI SDK 请求的extra_body中(见该文件第 36-47 行的client.chat.completions.create调用)。
3.5 启动命令与验证
在候选 GPU(L4、A10g 等)上启动 Llama-3 8B 服务:
HF_TOKEN="your-huggingface-token" sky launch serving.yaml --env HF_TOKEN
--env HF_TOKEN 表示把本地 shell 中该环境变量的值传入任务,而不是使用 YAML 里的占位符。
命令输出中会出现 Gradio 的公共链接(例如最后一行类似),在浏览器打开即可进行文本补全:
(task, pid=7431) Running on public URL: https://<gradio-hash>.gradio.live
这个公共链接正是由示例脚本 examples/applications/chatbot/gradio_openai_chatbot_webserver.py 中 gradio_interface.queue().launch(..., share=True) 的 share=True 参数生成的——Gradio 会自动建立一条到公网的转发隧道,这也是文档无需额外配置反向代理就能“浏览器直接用”的原因。
可选:换 70B 模型并使用更多 GPU。 用 --gpus 覆盖 YAML 中的加速器选择,并用 --env 覆盖 MODEL_NAME:
HF_TOKEN="your-huggingface-token" \
sky launch serving.yaml \
--gpus A100:8 \
--env HF_TOKEN \
--env MODEL_NAME=meta-llama/Meta-Llama-3-70B-Instruct
此时 SKYPILOT_NUM_GPUS_PER_NODE 为 8,vllm serve 会自动以 8 路张量并行运行 70B 模型。
3.6 关于 Gradio 示例脚本路径的一点勘误
文档的 GUI 示例段落中写的是 vllm/examples/applications/api_client/gradio_openai_chatbot_webserver.py,而当前仓库中该脚本实际位于 examples/applications/chatbot/gradio_openai_chatbot_webserver.py(git clone 下来的目录内也需按实际路径调整)。其命令行接口为:
| 参数 | 默认值 | 说明 |
|---|---|---|
-m / --model |
必填 | 传给 OpenAI API 的模型名 |
--model-url |
http://localhost:8000/v1 |
vLLM API Server 的 OpenAI 兼容地址 |
--port |
8001 |
Gradio 服务端口(文档示例用 8811 避免与 API Server 冲突) |
--temp |
0.8 |
采样温度 |
--stop-token-ids |
空 | 逗号分隔的停止 token ID 列表 |
四、横向扩展:多副本 + 就绪探针 + 自动扩缩容
SkyPilot 支持把服务扩展到多副本,并内置自动扩缩容、负载均衡与容错。做法是在 YAML 中追加一个 service 段:
service:
replicas: 2
# An actual request for readiness probe.
readiness_probe:
path: /v1/chat/completions
post_data:
model: $MODEL_NAME
messages:
- role: user
content: Hello! What is your name?
max_completion_tokens: 1
注意 readiness_probe 是一条真实的推理请求:它向 /v1/chat/completions 发送一个 max_completion_tokens: 1 的极简 chat 请求,只有服务真正能跑通推理时才判定副本就绪——比单纯探活 TCP/HTTP 端口更贴近“模型可服务”的语义。
4.1 完整的多副本 YAML
将 service 段与单实例配置合并(resources / envs / setup 与上文一致,run 段不再后台化、直接前台运行以便 SkyPilot 托管进程生命周期):
service:
replicas: 2
# An actual request for readiness probe.
readiness_probe:
path: /v1/chat/completions
post_data:
model: $MODEL_NAME
messages:
- role: user
content: Hello! What is your name?
max_completion_tokens: 1
resources:
accelerators: {L4, A10g, A10, L40, A40, A100, A100-80GB}
use_spot: True
disk_size: 512
disk_tier: best
ports: 8081 # Expose to internet traffic.
envs:
PYTHONUNBUFFERED: 1
MODEL_NAME: meta-llama/Meta-Llama-3-8B-Instruct
HF_TOKEN: <your-huggingface-token>
setup: |
conda create -n vllm python=3.10 -y
conda activate vllm
pip install vllm==0.4.0.post1
# Install Gradio for web UI.
pip install gradio openai
pip install flash-attn==2.5.7
run: |
conda activate vllm
echo 'Starting vllm api server...'
vllm serve $MODEL_NAME \
--port 8081 \
--trust-remote-code \
--tensor-parallel-size $SKYPILOT_NUM_GPUS_PER_NODE \
2>&1 | tee api_server.log
4.2 启动、观察与调用
启动多副本服务:
HF_TOKEN="your-huggingface-token" \
sky serve up -n vllm serving.yaml \
--env HF_TOKEN
周期性观察服务状态直到 READY:
watch -n10 sky serve status vllm
输出示例:
Services
NAME VERSION UPTIME STATUS REPLICAS ENDPOINT
vllm 1 35s READY 2/2 xx.yy.zz.100:30001
Service Replicas
SERVICE_NAME ID VERSION IP LAUNCHED RESOURCES STATUS REGION
vllm 1 1 xx.yy.zz.121 18 mins ago 1x GCP([Spot]{'L4': 1}) READY us-east4
vllm 2 1 xx.yy.zz.245 18 mins ago 1x GCP([Spot]{'L4': 1}) READY us-east4
可以看到:两个副本各自调度到一个 1×L4 spot 实例,对外则只暴露一个统一端点(xx.yy.zz.100:30001),负载均衡由 SkyPilot 完成。
服务 READY 后,用该端点直接以 OpenAI 兼容 API 调用(注意多副本场景下端点来自 sky serve status --endpoint 8081):
ENDPOINT=$(sky serve status --endpoint 8081 vllm)
curl -L http://$ENDPOINT/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "meta-llama/Meta-Llama-3-8B-Instruct",
"messages": [
{
"role": "system",
"content": "You are a helpful assistant."
},
{
"role": "user",
"content": "Who are you?"
}
],
"stop_token_ids": [128009, 128001]
}'
4.3 自动扩缩容(Autoscaling)
把固定的 replicas 替换为 replica_policy 即可启用基于 QPS 的自动扩缩容:
service:
replica_policy:
min_replicas: 2
max_replicas: 4
target_qps_per_replica: 2
含义:副本数始终维持在 2~4 之间,当单副本 QPS 超过 2 时触发扩容。结合上文的完整多副本 YAML,service 段最终形如:
service:
replica_policy:
min_replicas: 2
max_replicas: 4
target_qps_per_replica: 2
# An actual request for readiness probe.
readiness_probe:
path: /v1/chat/completions
post_data:
model: $MODEL_NAME
messages:
- role: user
content: Hello! What is your name?
max_completion_tokens: 1
修改配置后用 sky serve update 热更新服务,用 sky serve down 停止服务:
# 更新服务
HF_TOKEN="your-huggingface-token" sky serve update vllm serving.yaml --env HF_TOKEN
# 停止服务
sky serve down vllm
五、可选:为多副本服务挂接一个 GUI 前端
多副本场景下,也可以另起一个独立的 Gradio 前端:用户请求先到 GUI,GUI 再把请求转发到 SkyPilot 服务的统一端点,从而在各副本间负载均衡。前端本身不需要 GPU,只需 2 个 CPU:
envs:
MODEL_NAME: meta-llama/Meta-Llama-3-8B-Instruct
ENDPOINT: x.x.x.x:3031 # Address of the API server running vllm.
resources:
cpus: 2
setup: |
conda create -n vllm python=3.10 -y
conda activate vllm
# Install Gradio for web UI.
pip install gradio openai
run: |
conda activate vllm
export PATH=$PATH:/sbin
echo 'Starting gradio server...'
git clone https://github.com/vllm-project/vllm.git || true
python vllm/examples/applications/chatbot/gradio_openai_chatbot_webserver.py \
-m $MODEL_NAME \
--port 8811 \
--model-url http://$ENDPOINT/v1 \
--stop-token-ids 128009,128001 | tee ~/gradio.log
保存为 gui.yaml 后:
-
启动聊天 Web UI,并把服务统一端点注入
ENDPOINT:sky launch \ -c gui ./gui.yaml \ --env ENDPOINT=$(sky serve status --endpoint vllm) -
在返回的 Gradio 公共链接上访问,例如:
| INFO | stdout | Running on public URL: https://6141e84201ce0bb4ed.gradio.live
这里的 --model-url 指向 $ENDPOINT/v1 而非 localhost,与单实例场景的关键区别正在于此:GUI 与推理副本解耦,请求经 SkyPilot 端点被负载均衡到 2~4 个 vLLM 副本。
六、部署流程小结与源码索引
把两种形态放到一张流程图中:
- 单实例:
sky launch serving.yaml→ SkyPilot 按resources候选集选最省可用 GPU →setup装环境 →run拉起vllm serve(TP 自适应SKYPILOT_NUM_GPUS_PER_NODE)→ Gradio 前端经share=True生成公共链接; - 多副本:
sky serve up→ 每个副本独立运行一份vllm serve→readiness_probe以真实 1-token 推理请求探活 → 统一端点对外负载均衡 →replica_policy按 QPS 在 min/max 间伸缩 →sky serve update/sky serve down管理生命周期。
延伸阅读时可直接参考仓库内这些文件:
- 本文主体文档:docs/deployment/frameworks/skypilot.md;
- Gradio 聊天示例(前端调用链、参数解析):examples/applications/chatbot/gradio_openai_chatbot_webserver.py;
vllm serve入口:vllm/entrypoints/cli/serve.py;--tensor-parallel-size、--trust-remote-code等参数注册:vllm/engine/arg_utils.py。
最后强调适用前提:上述命令与 YAML 以 SkyPilot 的 sky launch / sky serve 子命令集为前提,需要先在本地完成云凭证配置并通过 sky check;示例中的 vLLM/flash-attn 固定版本来自文档编写时点,升级 vLLM 时请同步核对对应的依赖版本组合。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00