Kubernetes 是部署应用程序和微服务的实际标准。然而,AI 工作负载不同。开发 AI 模型是一个交互式且资源密集型过程,对资源的部署和管理需要一种根本不同的方法。
在本博客中,我们将
- 讨论 Kubernetes 对于 AI 工作负载的优缺点。
- 介绍 SkyPilot,以在 Kubernetes 及其他环境上轻松且经济高效地运行 AI。
- 提供分步指南,介绍如何使用 SkyPilot 在您的 Kubernetes 集群上运行整个 AI 生命周期——从开发到训练再到部署。
Kubernetes 并非为 AI 而生
Kubernetes 是托管通用微服务的绝佳选择,并为管理员提供了广泛的集群管理功能。
然而,AI 工作负载具有 Kubernetes 未设计考虑的独特要求。
AI 开发需要交互性
构建和部署 AI 需要与部署微服务根本不同的流程。开发模型和清理数据是迭代过程,需要频繁修改代码并进行快速迭代。
这与微服务的“即发即忘”部署形成对比,微服务的一次部署可以长时间运行而无需任何干预。
AI 需要大量资源
AI 不仅需要强大的 GPU 进行训练,控制成本还需要处理可能分布在不同地理区域和提供商的多样化资源类型。难怪 OpenAI 在多个区域和云中运行基础设施。
另一方面,Kubernetes 设计用于单个紧密联网的集群。etcd(Kubernetes 的底层数据存储)在跨区域运行时性能会下降。
因此,您的资源被锁定在单个区域,限制了可用性并增加了成本。
AI 有严格的调度要求
AI 训练有严格的调度要求。大规模分布式训练需要协同调度(gang scheduling),即所有资源必须同时分配才能取得进展。
Kubernetes 默认不支持协同调度,这使得高效运行分布式训练作业变得困难。
Kubernetes 学习曲线陡峭
AI 工程师需要与基础设施紧密合作来开发和部署模型。然而,Kubernetes 并不以对 AI 工程师和数据科学家友好而闻名。但他们被迫学习 Kubernetes 及其带来的所有复杂性——容器化、管理 Pod、服务等等。
因此,Kubernetes 成为了许多讨论、抱怨甚至梗图的主题。
AI 工程师不应该为基础设施烦恼。相反,他们应该专注于自己的核心优势——数据处理、模型开发和评估。
但是……Kubernetes 也有许多优势
事情并非一团糟。Kubernetes 提供了一系列出色的功能,对 AI 工作负载非常有帮助——自动伸缩、故障恢复、资源管理和生产就绪性。
然而,要在 Kubernetes 上利用这些功能来运行 AI,需要深入了解 Kubernetes 生态系统,并且需要一个专门的团队来开发和维护高度专业化的工具。
SkyPilot:在 Kubernetes 及其他环境上运行 AI
SkyPilot 是一个在任何基础设施上运行 AI 的框架。对于 Kubernetes 用户来说,它建立在 Kubernetes 的核心优势之上,不仅提供了更简单的接口,还提供了一个超出单个 Kubernetes 集群范围的、更具成本效益和更高可用性的基础设施层。
以下是在您的 Kubernetes 集群上使用 SkyPilot 的一些主要优势
更简单的开发者体验和内置交互性
SkyPilot 抽象化了 Kubernetes 的复杂性,提供了运行 AI 工作负载的简单接口。
SkyPilot 通过 SSH 访问和与 VSCode 及 Jupyter notebooks 的集成,提供了无缝的交互式开发体验。开发者可以专注于构建模型,无需担心底层基础设施。
示例:迭代模型开发
交互式工作流受益于 SkyPilot 更快的迭代速度。例如,AI 工程师的常见工作流是通过观察训练运行来调整代码和超参数,从而迭代开发和训练模型。
- 使用 Kubernetes,单次迭代是一个多步过程,包括构建 Docker 镜像、将其推送到注册表、更新 Kubernetes YAML 文件,然后进行部署。
- 使用 SkyPilot,一个简单的
sky launch
命令即可处理一切。在后台,SkyPilot 会提供 Pod、安装所有必需的依赖项、执行作业、返回日志并提供 SSH 访问以进行调试。
示例:模型部署
训练模型后的常见任务是部署。
- 使用 Kubernetes,您需要超过 65 行的 Kubernetes YAML 文件来启动使用 vLLM 部署的 Gemma 模型。
- 使用 SkyPilot,只需一个易于理解的仅 19 行的 YAML 文件即可启动一个使用 vLLM 部署 Gemma 的 Pod。
智能编排,最大化团队效率
在多租户 Kubernetes 集群中运行时,SkyPilot 会智能地跨用户调度 GPU。每个用户都有自己的隔离环境,确保其工作负载不相互干扰,同时最大化资源利用率。
无需手动调度 GPU——SkyPilot 会为您处理一切。
GPU 不够用了?SkyPilot 以最低成本找到更多
GPU 供应短缺。SkyPilot 旨在通过在您的 Kubernetes 集群、云和区域中查找 GPU,最大化您的 AI 工作负载的可用性。它可以自动从 GPU 故障、竞价实例抢占和其他故障中恢复。
如果您的本地集群资源不足,SkyPilot 可以突发到云端,并在任何可用之处找到资源,确保您的工作负载不被阻塞。
当您使用云时,每个 sky launch
命令都会调用 SkyPilot 的优化器,该优化器会在您所有基础设施中找到最具成本效益的资源。SkyPilot 还支持云上的竞价实例,并且可以混合使用竞价实例和按需实例,以在确保可用性的同时将成本降低高达 6 倍。
== Optimizer ==
Estimated cost: $0.0 / hour
Considered resources (1 node):
----------------------------------------------------------------------------------------------------------
CLOUD INSTANCE vCPUs Mem(GB) ACCELERATORS REGION/ZONE COST ($) CHOSEN
----------------------------------------------------------------------------------------------------------
Kubernetes 2CPU--8GB--1T4 2 8 T4:1 kubernetes 0.00 ✔
Azure Standard_NC4as_T4_v3 4 28 T4:1 eastus 0.53
AWS g4dn.xlarge 4 16 T4:1 us-east-1 0.53
GCP n1-highmem-4 4 26 T4:1 us-central1-a 0.59
----------------------------------------------------------------------------------------------------------
Launching a new cluster 'dev'. Proceed? [Y/n]:
统一的接口,适用于所有基础设施
SkyPilot 提供了一个统一的接口,用于在本地、云和混合环境中运行 AI 工作负载。同一个 YAML 规范可以在 12+ 个云提供商甚至您的本地 Kubernetes 集群上工作。一旦您的作业运行起来,sky status
命令会为您提供跨云所有资源的统一视图。
$ sky status
Clusters
NAME LAUNCHED RESOURCES STATUS AUTOSTOP COMMAND
sky-serve-controller-2ea485ea 1 hr ago 1x Kubernetes(4CPU--4GB, ports=['30001-30020']... UP 10m (down) sky serve up -n llama2 ll...
sky-jobs-controller-2ea485ea 1 hr ago 1x AWS(4CPU--4GB) UP 10m (down) sky jobs launch -c bert ...
Managed jobs
In progress tasks: 1 RUNNING
ID TASK NAME RESOURCES SUBMITTED TOT. DURATION JOB DURATION #RECOVERIES STATUS
1 - bert 2x[A100:1] 3 mins ago 3m 26s 2m 18s 0 RUNNING
Services
NAME VERSION UPTIME STATUS REPLICAS ENDPOINT
llama2 1 34m 44s READY 3/3 35.225.61.44:30001
Service Replicas
SERVICE_NAME ID VERSION ENDPOINT LAUNCHED RESOURCES STATUS REGION
llama2 1 1 http://34.173.84.219:8888 1 hr ago 1x Kubernetes({'T4': 1}) READY kubernetes
llama2 2 1 http://35.199.51.206:8888 1 hr ago 1x GCP([Spot]{'T4': 1}) READY us-east4
llama2 3 1 http://34.31.108.35:8888 1 hr ago 1x Kubernetes({'T4': 1}) READY kubernetes
* To see detailed service status: sky serve status -a
* 1 cluster has auto{stop,down} scheduled. Refresh statuses with: sky status --refresh
兼容您现有的 Kubernetes 工具
SkyPilot 在 Kubernetes 上像其他任何应用程序一样运行。在后台,它创建 Pod 为作业提供计算资源,并在需要时使用 Kubernetes Service 或 Ingress 暴露它们。它还可以与 Kueue 等其他 Kubernetes 控制器集成。
这意味着您的所有现有 Kubernetes 工具(用于监控、日志记录和告警)都可以与 SkyPilot 一起使用。
指南:使用 SkyPilot 在 Kubernetes 上运行 AI
让我们深入探讨如何使用 SkyPilot 在 Kubernetes 上运行整个 AI 生命周期——从开发到训练再到部署。
入门
要开始使用,请安装最新版本的 SkyPilot 以及 Kubernetes 依赖项
pip install skypilot-nightly[kubernetes]
接下来,我们需要将 Kubernetes 集群连接到 SkyPilot。
- 如果您已经有 Kubernetes 集群,您只需要一个有效的 kubeconfig 文件。确保您的凭据已在
~/.kube/config
中设置,并且您可以访问您的 Kubernetes 集群。您可以通过运行kubectl get nodes
进行测试。 - 如果您没有 Kubernetes 集群,请运行
sky local up
。这将设置一个本地 Kubernetes 集群用于开发和测试目的。
运行 sky check
以验证您的集群和 SkyPilot 是否设置正确
# Checks if your Kubernetes credentials are set up correctly
sky check kubernetes
您应该在已启用云列表下看到 Kubernetes。如果没有,SkyPilot 将显示未启用的原因并建议纠正步骤。有关如何设置 Kubernetes 的更多详细信息,请参阅我们的文档。
对于更高级的设置,SkyPilot 也可以配置为使用自定义命名空间和服务帐户。
我们现在准备好启动您的第一个 SkyPilot 集群了!
通过 SSH 和 VSCode 连接到 GPU Pod
AI 开发的初始阶段需要在 GPU 上进行大量的交互式开发。SkyPilot 允许您创建“集群”,这些集群是 Kubernetes 上 Pod 的集合。让我们启动一个启用了 GPU 的 SkyPilot 开发集群,并通过 SSH 和 VSCode 连接到它。
首先,让我们使用 sky show-gpus --cloud kubernetes
查看集群上有哪些 GPU 可用
$ sky show-gpus --cloud kubernetes
Kubernetes GPUs
GPU QTY_PER_NODE TOTAL_GPUS TOTAL_FREE_GPUS
T4 1 4 4
V100 1, 2 4 4
要启动一个带有 GPU 的集群进行开发,请使用 sky launch
# Launch a cluster named 'dev' with 1 NVIDIA T4 GPU. If you do not have a GPU, remove the --gpus flag.
sky launch -c dev --gpus T4:1
SkyPilot 将运行其优化器来查找最低成本,并向您显示运行您的开发集群的最便宜选项
== Optimizer ==
Estimated cost: $0.0 / hour
Considered resources (1 node):
----------------------------------------------------------------------------------------------------------
CLOUD INSTANCE vCPUs Mem(GB) ACCELERATORS REGION/ZONE COST ($) CHOSEN
----------------------------------------------------------------------------------------------------------
Kubernetes 2CPU--8GB--1T4 2 8 T4:1 kubernetes 0.00 ✔
Azure Standard_NC4as_T4_v3 4 28 T4:1 eastus 0.53
AWS g4dn.xlarge 4 16 T4:1 us-east-1 0.53
GCP n1-highmem-4 4 26 T4:1 us-central1-a 0.59
----------------------------------------------------------------------------------------------------------
Launching a new cluster 'dev'. Proceed? [Y/n]:
您的 SkyPilot 集群将作为 Pod 在您的 Kubernetes 集群中启动。SkyPilot 将负责启动 Pod、安装依赖项、设置 SSH 等等。
配置完成后,您可以通过 SSH 或 VSCode 连接到它。
通过 SSH 连接
SkyPilot 会自动配置您的 ssh config 文件,为开发集群添加一个别名。访问您的集群就像运行 ssh <cluster>
一样简单
ssh dev
通过 VSCode 连接
交互式开发的另一个常见用例是将本地 VSCode 连接到远程集群,并直接编辑集群上的代码。只需使用集群名称将 VSCode 连接到集群即可支持此操作。
- 单击顶部栏,输入:
> remote-ssh
,然后选择Remote-SSH: Connect Current Window to Host...
- 从主机列表中选择集群名称(例如,
dev
)。
运行 Jupyter Notebook
您也可以在集群上启动 Jupyter,以获得支持 GPU 的 notebook。连接到机器并转发 Jupyter notebook 使用的端口
ssh -L 8888:localhost:8888 dev
在集群内部,您可以运行以下命令启动 Jupyter 会话
pip install jupyter
jupyter notebook
在本地浏览器中,您现在应该能够访问 localhost:8888
并在您的 notebook 中使用 GPU
使用 SkyPilot 进行分布式训练
开发完模型后,您可以使用 SkyPilot 的托管作业功能大规模训练您的模型。
让我们定义训练作业。例如,我们将使用 torch 分布式数据并行 (DDP) 在 SQuAD 数据集上,跨两个节点使用 2 个 A100 GPU 训练 BERT 问答模型
envs:
WANDB_API_KEY: # TODO: Fill with your own wandb token, or use --env to pass.
resources:
accelerators: A100:1
# Run on two nodes with 1 GPU each
num_nodes: 2
setup: |
git clone https://github.com/huggingface/transformers.git -b v4.30.1
cd transformers
pip install -e .
cd examples/pytorch/question-answering/
pip install -r requirements.txt torch==1.12.1+cu113 --extra-index-url https://download.pytorch.org/whl/cu113
pip install wandb
run: |
cd transformers/examples/pytorch/question-answering/
NUM_NODES=`echo "$SKYPILOT_NODE_IPS" | wc -l`
HOST_ADDR=`echo "$SKYPILOT_NODE_IPS" | head -n1`
torchrun \
--nnodes=$NUM_NODES \
--nproc_per_node=$SKYPILOT_NUM_GPUS_PER_NODE \
--master_port=12375 \
--master_addr=$HOST_ADDR \
--node_rank=${SKYPILOT_NODE_RANK} \
run_qa.py \
--model_name_or_path bert-base-uncased \
--dataset_name squad \
--do_train \
--do_eval \
--per_device_train_batch_size 12 \
--learning_rate 3e-5 \
--num_train_epochs 50 \
--max_seq_length 384 \
--doc_stride 128 \
--report_to wandb \
--run_name $SKYPILOT_TASK_ID \
--output_dir ~/checkpoints \
--save_total_limit 10 \
--save_steps 1000
您也可以通过修改 --output_dir
标志,将检查点配置记录到持久卷或云存储桶。
要启动此作业,请将上述 YAML 保存到文件(例如,bert.yaml
),然后运行
sky jobs launch -n bert bert.yaml
SkyPilot 将提供一个控制器 Pod 来编排训练作业。该控制器将创建两个 Pod,分布在两个节点上,每个 Pod 请求一个 Nvidia A100 GPU。它还将确保协同调度,以便所有资源同时分配。
配置完成后,SkyPilot 运行时将安装所需的依赖项并执行训练脚本。此外,它会自动从任何故障中恢复,包括 GPU 错误和 NCCL 超时。
您可以使用 sky jobs queue
和 sky jobs logs
命令监控作业状态和查看日志
$ sky jobs queue
Fetching managed job statuses...
Managed jobs
In progress tasks: 1 RUNNING
ID TASK NAME RESOURCES SUBMITTED TOT. DURATION JOB DURATION #RECOVERIES STATUS
1 - bert 2x[A100:1] 3 mins ago 3m 26s 2m 18s 0 RUNNING
如果您使用 Weights and Biases (W&B) 进行日志记录,您也可以在 W&B 面板上查看训练进度
如果需要,您可以使用 sky jobs cancel
命令取消作业。SkyPilot 将终止 Pod 并清理作业使用的任何资源。
使用 SkyServe 在 Kubernetes 上部署生成式 AI
最后,训练完模型后,您可以使用 SkyPilot 的SkyServe 库对其进行部署。
- 支持任何部署框架:vLLM、TGI、FastAPI 等。
- SkyServe 为您的服务提供单一端点,由您所有基础设施中的副本支持,以确保高可用性和最低成本。
- SkyServe 管理自动伸缩和负载均衡,并允许自定义负载均衡策略。
例如,要通过兼容 OpenAI 的端点部署 Google 开源 Gemma 模型,我们可以使用此 SkyPilot YAML 在 Kubernetes 上运行 vLLM
envs:
MODEL_NAME: google/gemma-2b-it
HF_TOKEN: # TODO: Fill with your own huggingface token, or use --env to pass.
resources:
image_id: docker:vllm/vllm-openai:latest
accelerators: T4:1
ports: 8000
service:
readiness_probe:
path: /v1/chat/completions
post_data:
model: $MODEL_NAME
messages:
- role: user
content: Hello! What is your name?
max_tokens: 1
replicas: 3
run: |
conda deactivate
python3 -c "import huggingface_hub; huggingface_hub.login('${HF_TOKEN}')"
python3 -m vllm.entrypoints.openai.api_server --model $MODEL_NAME --host 0.0.0.0 --dtype half
service
部分指定了就绪探针(用于检查模型是否准备好提供服务)以及运行的副本数量。您可以指定自动伸缩策略、配置滚动更新等。有关更多详细信息,请参阅文档。
将上面的代码片段保存为 vllm.yaml
,确保填写了 HF_TOKEN
,并确保您可以访问该模型。
使用 sky serve up
命令启动服务
sky serve up -n vllm vllm.yaml
SkyPilot 将启动一个控制器,该控制器将充当负载均衡器并管理服务副本。此负载均衡器将提供一个统一的端点,同时在后台它将在您的 Kubernetes 集群中提供 3 个 Pod,每个 Pod 请求一个 T4 GPU,并使用 vLLM 容器镜像实现快速启动。一旦副本的就绪探针通过,统一端点将在这些副本之间进行负载均衡请求。
要查看您的服务状态,请运行 sky serve status
$ sky serve status
Services
NAME VERSION UPTIME STATUS REPLICAS ENDPOINT
vllm 1 3m 53s READY 3/3 34.44.26.104:30001
Service Replicas
SERVICE_NAME ID VERSION ENDPOINT LAUNCHED RESOURCES STATUS REGION
vllm 1 1 http://34.30.184.120:8000 5 mins ago 1x Kubernetes({'T4': 1}) READY kubernetes
vllm 2 1 http://34.27.200.138:8000 5 mins ago 1x Kubernetes({'T4': 1}) READY kubernetes
vllm 3 1 http://34.70.146.169:8000 3 mins ago 1x Kubernetes({'T4': 1}) READY kubernetes
SkyServe 公开了一个统一的端点地址,您的应用程序现在可以连接到该地址并从 Gemma 模型获取补全。在此端点背后,SkyPilot 将管理服务副本,根据负载自动伸缩它们并确保高可用性。
例如,让我们使用 curl 通过该端点获取 Gemma 模型的补全结果
$ ENDPOINT=$(sky serve status --endpoint vllm)
$ curl http://$ENDPOINT/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "google/gemma-2b-it",
"messages": [
{
"role": "user",
"content": "Hello! What is your name?"
}
],
"max_tokens": 25
}'
点击查看输出。
{
"id": "cmpl-79dc510b6e484352b74b056f6dc36028",
"object": "chat.completion",
"created": 1719526198,
"model": "google/gemma-2b-it",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "Hello! My name is Gemma, and I'm here to assist you with any questions or tasks you may have. ",
"tool_calls": []
},
"logprobs": null,
"finish_reason": "length",
"stop_reason": null
}
],
"usage": {
"prompt_tokens": 16,
"total_tokens": 41,
"completion_tokens": 25
}
}
扩展和更新服务
您也可以手动扩展和更新服务。例如,要将 vLLM 服务扩展到 5 个副本,请将 YAML 中的 replicas
字段更新为 5,然后运行
$ sky serve update -n vllm vllm.yaml
SkyPilot 将自动将服务扩展到 5 个副本。如果 Kubernetes 集群资源不足,SkyPilot 将突发到云端,以确保服务保持可用,即使在高负载下也是如此。
$ sky serve status
Services
NAME VERSION UPTIME STATUS REPLICAS ENDPOINT
vllm 1 18m 48s READY 5/5 34.44.26.104:30001
Service Replicas
SERVICE_NAME ID VERSION ENDPOINT LAUNCHED RESOURCES STATUS REGION
vllm 1 1 http://34.30.184.120:8000 20 mins ago 1x Kubernetes({'T4': 1}) READY kubernetes
vllm 2 1 http://34.27.200.138:8000 20 mins ago 1x Kubernetes({'T4': 1}) READY kubernetes
vllm 3 1 http://34.70.146.169:8000 18 mins ago 1x Kubernetes({'T4': 1}) READY kubernetes
vllm 4 1 http://3.182.116.201:8000 3 mins ago 1x GCP({'T4': 1}) READY us-central1
vllm 5 1 http://3.182.101.130:8000 2 mins ago 1x GCP({'T4': 1}) READY us-central1
结论
Kubernetes 是为微服务设计的,在其上运行 AI 工作负载可能具有挑战性。SkyPilot 基于 Kubernetes 的优势,通过统一的接口运行完整的 AI 生命周期,同时提供突发到云端以获取额外容量的能力,超越了 Kubernetes 集群的范围。通过这样做,SkyPilot 保证了您的 AI 工作负载的高可用性和低成本。
了解更多
- SkyPilot AI 库:一系列流行的 AI 工作负载,包括 Llama-3、Mistral、Gemma、Ollama 等,可以使用 SkyPilot 在您的 Kubernetes 集群上运行。
- SkyPilot 文档
- GitHub
要接收最新更新,请为项目 GitHub 仓库 点星并关注,关注 @skypilot_org,或加入 SkyPilot 社区 Slack。