模型服务#
SkyServe 是 SkyPilot 的模型服务库。SkyServe 接受现有的服务框架,并将其部署到一个或多个区域或云上。
为什么选择 SkyServe?
使用任何服务框架 (vLLM, TGI, FastAPI 等),并在多个区域/云上进行扩缩容
通过利用多个/更便宜的位置和硬件(竞价实例),降低成本并提高服务副本的可用性
服务副本的开箱即用负载均衡和自动扩缩容
隐私和控制:所有内容都在您的云账户和 VPC 内启动
使用单一控制平面管理多云、多区域部署
工作原理
每个服务都有一个端点,该端点会自动将请求分发给其副本。
同一服务的副本可以在不同区域和云中运行——这可以降低云成本并提高可用性。
SkyServe 处理副本的负载均衡、恢复和自动扩缩容。
提示
要开始使用 SkyServe,请使用 SkyPilot 的 nightly build 版本: pip install -U skypilot-nightly
快速导览:LLM 服务#
这是一个提供 LLM 模型服务(在 vLLM 上运行 Mixtral-8x7B-Instruct-v0.1
或在 TGI 上运行 lmsys/vicuna-13b-v1.5
)的简单示例
# service.yaml
service:
readiness_probe: /v1/models
replicas: 2
# Fields below describe each replica.
resources:
ports: 8080
accelerators: {L4:8, A10g:8, A100:4, A100:8, A100-80GB:2, A100-80GB:4, A100-80GB:8}
setup: |
conda create -n vllm python=3.9 -y
conda activate vllm
pip install vllm
run: |
conda activate vllm
python -m vllm.entrypoints.openai.api_server \
--tensor-parallel-size $SKYPILOT_NUM_GPUS_PER_NODE \
--host 0.0.0.0 --port 8080 \
--model mistralai/Mixtral-8x7B-Instruct-v0.1
# service.yaml
service:
readiness_probe: /health
replicas: 2
# Fields below describe each replica.
resources:
ports: 8080
accelerators: A100
run: |
docker run --gpus all --shm-size 1g -p 8080:80 -v ~/data:/data \
ghcr.io/huggingface/text-generation-inference \
--model-id lmsys/vicuna-13b-v1.5
运行 sky serve up service.yaml
以部署具有自动价格和容量优化的服务。部署后,使用 sky serve status
检查服务状态
提示
请注意,这两个副本部署在不同的区域/云中,以实现最低成本和最高 GPU 可用性。这会自动执行,就像常规的 sky launch
一样。
如果看到 STATUS
列变为 READY
,则服务已准备好接受流量!
只需 curl
服务端点即可,它会自动在两个副本之间进行负载均衡
$ curl 3.84.15.251:30001/v1/chat/completions \
-X POST \
-d '{"model": "mistralai/Mixtral-8x7B-Instruct-v0.1", "messages": [{"role": "user", "content": "Who are you?"}]}' \
-H 'Content-Type: application/json'
# Example output:
{"id":"cmpl-80b2bfd6f60c4024884c337a7e0d859a","object":"chat.completion","created":1005,"model":"mistralai/Mixtral-8x7B-Instruct-v0.1","choices":[{"index":0,"message":{"role":"assistant","content":" I am a helpful AI assistant designed to provide information, answer questions, and engage in conversation with users. I do not have personal experiences or emotions, but I am programmed to understand and process human language, and to provide helpful and accurate responses."},"finish_reason":"stop"}],"usage":{"prompt_tokens":13,"total_tokens":64,"completion_tokens":51}}
$ curl 44.211.131.51:30001/generate \
-X POST \
-d '{"inputs":"What is Deep Learning?","parameters":{"max_new_tokens":20}}' \
-H 'Content-Type: application/json'
# Example output:
{"generated_text":"\n\nDeep learning is a subset of machine learning that uses artificial neural networks to model and solve"}
教程:Hello, SkyServe!#
这里我们将通过一个示例来演示如何使用 SkyServe 部署一个简单的 HTTP 服务器。要启动一个服务,只需重用您的任务 YAML,并满足以下两个要求
一个 HTTP 端点(在
run
命令中启动)以及它监听的端口;在您的任务 YAML 中添加一个额外的
service
部分来描述服务配置。
建议先使用 sky launch
进行测试。例如,我们有以下任务 YAML 适用于 sky launch
resources:
ports: 8080
cpus: 2
workdir: .
run: python -m http.server 8080
在同一个目录下,我们有一个 index.html
文件
<html>
<head>
<title>My First SkyServe Service</title>
</head>
<body>
<p>Hello, SkyServe!</p>
</body>
</html>
注意
workdir 和 带有本地文件的文件挂载 将自动上传到 云存储桶。存储桶将在服务终止后创建并清理。
请注意,任务 YAML 中已有一个正在运行的 HTTP 端点,端口为 8080,并通过 resources
部分下的 ports
部分暴露。假设我们想用 SkyServe 将其扩展到多个区域/云中的多个副本。我们只需在 YAML 中添加一个 service
部分
# hello-sky-serve.yaml
service:
readiness_probe: /
replicas: 2
resources:
ports: 8080
cpus: 2
workdir: .
run: python -m http.server 8080
此示例将启动服务的两个副本,每个副本监听端口 8080。当副本响应 GET /
并返回 200 状态码时,该副本被视为准备就绪。您可以通过在 readiness_probe
字段中指定不同的路径来定制就绪探针。您可以在 服务 YAML 规范 中找到更多配置选项。
使用 sky serve up
启动服务
$ sky serve up hello-sky-serve.yaml
SkyServe 将启动(或重用)一个中心控制器/负载均衡器,并将服务副本部署到价格和可用性最佳的云位置。SkyServe 还会监控服务状态,如果其中一个副本失败,则会重新启动一个新副本。
在底层,sky serve up
启动一个控制器,负责自动扩缩容、监控和负载均衡;
返回一个服务端点,该端点将用于接收流量;
同时,控制器调配副本虚拟机,这些虚拟机稍后运行服务;
一旦有任何副本准备就绪,发送到服务端点的请求将被分发到其中一个端点副本。
注意
SkyServe 使用最少连接负载均衡(least load load balancing)将流量分发到副本。它跟踪每个副本处理的请求数量,并将下一个请求路由到负载最少的副本。
控制器调配完成后,您将在 sky serve status
输出中看到以下内容

您可以使用 watch
命令监控服务状态
$ watch -n10 sky serve status
一旦任何副本准备好提供服务(READY
),您就可以开始向 <endpoint-url>
发送请求(例如,44.201.119.3:30001
)
$ curl <endpoint-url>
<html>
<head>
<title>My First SkyServe Service</title>
</head>
<body>
<p>Hello, SkyServe!</p>
</body>
</html>
教程:部署聊天机器人 LLM 服务!#
让我们使用 FastChat + Vicuna 部署一个真正的 LLM 聊天服务。我们将使用 Vicuna OpenAI API Endpoint YAML 作为示例
resources:
ports: 8080
accelerators: A100:1
disk_size: 1024
disk_tier: best
setup: |
conda activate chatbot
if [ $? -ne 0 ]; then
conda create -n chatbot python=3.9 -y
conda activate chatbot
fi
# Install dependencies
pip install "fschat[model_worker,webui]==0.2.24"
pip install protobuf
run: |
conda activate chatbot
echo 'Starting controller...'
python -u -m fastchat.serve.controller --host 127.0.0.1 > ~/controller.log 2>&1 &
sleep 10
echo 'Starting model worker...'
python -u -m fastchat.serve.model_worker \
--model-path lmsys/vicuna-${MODEL_SIZE}b-v1.3 2>&1 \
--host 127.0.0.1 \
| tee model_worker.log &
echo 'Waiting for model worker to start...'
while ! `cat model_worker.log | grep -q 'Uvicorn running on'`; do sleep 1; done
echo 'Starting openai api server...'
python -u -m fastchat.serve.openai_api_server \
--host 0.0.0.0 --port 8080 | tee ~/openai_api_server.log
envs:
MODEL_SIZE: 7
上述 SkyPilot 任务 YAML 将使用 Vicuna 7B 模型启动一个 OpenAI API 端点。此 YAML 可用于常规的 sky launch
命令,以启动服务的单个副本。
然而,通过在 YAML 中添加一个 service
部分,我们可以将其扩展到多个区域/云中的多个副本
# vicuna.yaml
service:
readiness_probe: /v1/models
replicas: 3
resources:
ports: 8080
# Here goes other resources config
# Here goes other task config
现在我们有了可用于 SkyServe 的服务 YAML!只需运行
$ sky serve up vicuna.yaml -n vicuna
来部署服务(使用 -n
为您的服务命名!)。一段时间后,将有一个与 OpenAI 兼容的 API 端点准备好接受流量(以下示例中为 44.201.113.28:30001
)

使用以下 cURL 命令发送请求
$ curl http://<endpoint-url>/v1/chat/completions \
-X POST \
-d '{"model":"vicuna-7b-v1.3","messages":[{"role":"system","content":"You are a helpful assistant."},{"role":"user","content":"Who are you?"}],"temperature":0}' \
-H 'Content-Type: application/json'
# Example output:
{"id":"chatcmpl-gZ8SfgUwcm9Xjbuv4xfefq","object":"chat.completion","created":1702082533,"model":"vicuna-7b-v1.3","choices":[{"index":0,"message":{"role":"assistant","content":"I am Vicuna, a language model trained by researchers from Large Model Systems Organization (LMSYS)."},"finish_reason":"stop"}],"usage":{"prompt_tokens":19,"total_tokens":43,"completion_tokens":24}}
您也可以使用简单的聊天机器人 Python 脚本发送请求
import openai
stream = True
model = 'vicuna-7b-v1.3' # This is aligned with the MODEL_SIZE env in the YAML
init_prompt = 'You are a helpful assistant.'
history = [{'role': 'system', 'content': init_prompt}]
endpoint = input('Endpoint: ')
openai.api_base = f'http://{endpoint}/v1'
openai.api_key = 'placeholder'
try:
while True:
user_input = input('[User] ')
history.append({'role': 'user', 'content': user_input})
resp = openai.ChatCompletion.create(model=model,
messages=history,
stream=True)
print('[Chatbot]', end='', flush=True)
tot = ''
for i in resp:
dlt = i['choices'][0]['delta']
if 'content' not in dlt:
continue
print(dlt['content'], end='', flush=True)
tot += dlt['content']
print()
history.append({'role': 'assistant', 'content': tot})
except KeyboardInterrupt:
print('\nBye!')
常用 CLI 命令#
以下是一些 SkyServe 命令。请查阅 sky serve --help
以获取更多详情。
查看所有正在运行的服务
$ sky serve status

流式传输服务的日志
$ sky serve logs vicuna 1 # tail logs of replica 1, including provisioning and running logs
$ sky serve logs vicuna --controller # tail controller logs
$ sky serve logs vicuna --load-balancer --no-follow # print the load balancer logs so far, and exit
终止服务
$ sky serve down http-server # terminate the http-server service
$ sky serve down --all # terminate all services
自动扩缩容#
有关更多信息,请参阅 自动扩缩容。
SkyServe 架构#

SkyServe 有一个中心控制器虚拟机,用于管理您的服务部署。每个服务将有一个进程组来管理其副本并向其路由流量。
它由以下组件组成
控制器:控制器会监控副本的状态,如果其中一个副本失败,则会重新启动一个新副本。如果设置了自动扩缩容配置,它还会自动扩缩副本数量(更多信息请参阅 服务 YAML 规范)。
负载均衡器:负载均衡器会将流量路由到所有准备就绪的副本。它是一个轻量级的 HTTP 服务器,监听服务端点并将请求分发到其中一个副本。
所有进程组共享一个控制器虚拟机。控制器虚拟机将在具有最佳性价比的云中启动。您也可以根据需要定制控制器资源。
SkyServe 控制器#
SkyServe 控制器是一个运行在云中的小型按需 CPU 虚拟机,它负责
管理您的服务部署;
监控您的服务状态;
将流量路由到您的服务副本。
当部署第一个服务时,它会自动启动,并在空闲 10 分钟后自动停止(即所有服务终止后)。因此,管理其生命周期无需用户干预。
您可以使用 sky status
查看控制器,并使用 -r/--refresh
标志刷新其状态。
定制 SkyServe 控制器资源#
您可能出于以下几个原因想要定制 SkyServe 控制器的资源
使用成本较低的控制器。(如果运行的服务较少)
强制控制器在特定位置运行。当您希望服务端点位于特定地理区域内时,这特别有用。(默认:最便宜的位置)
更改可并发运行的最大服务数量,该数量是控制器 vCPU 数量的 4 倍与控制器内存(以 GiB 为单位)之间的最小值。(默认:16)
更改控制器的 disk_size 以存储更多日志。(默认:200GB)
要实现上述目的,您可以在 ~/.sky/config.yaml
文件中指定自定义配置,使用以下字段
serve:
# NOTE: these settings only take effect for a new SkyServe controller, not if
# you have an existing one.
controller:
# Enable high availability mode for the controller (optional).
#
# When set to true, the controller will be deployed with high availability
# capabilities on Kubernetes using Deployments. This allows the controller and load balancer
# to automatically recover from failures (e.g., node failures, pod crashes)
# and maintain service continuity.
#
# NOTE: This feature is ONLY supported when Kubernetes cloud is enabled. To enable kubernetes, see :ref:`Kubernetes Setup <kubernetes-setup>`.
# The service controller cluster will be scheduled to kubernetes. The k8s deployment needs to be always-on to keep the controller running. If using a local kubernetes deployment (e.g. `sky local up`), keeping the laptop/machines up is required.
# When enabled:
# - The controller is deployed as a Kubernetes Deployment instead of a Pod
# - Automatic pod rescheduling and recovery is handled by Kubernetes
#
# Default: false.
high_availability: true
resources:
# All configs below are optional.
# Specify the location of the SkyServe controller.
cloud: gcp
region: us-central1
# Specify the maximum number of services that can be run concurrently.
cpus: 2+ # number of vCPUs, max concurrent services = min(4 * cpus, memory in GiB)
# Specify the disk_size in GB of the SkyServe controller.
disk_size: 1024
resources
字段与正常的 SkyPilot 作业具有相同的规范;请参阅此处。
注意
如果您已有控制器(无论是已停止还是正在运行),这些设置将不会生效。要使其生效,请先拆除现有控制器,这需要终止所有服务。