SkyPilot 深度实战:从多云 AI 调度到成本优化的企业级完全指南
2026 年,当 AI 工作负载从单云走向多云、从训练走向推理、从实验走向生产,基础设施的碎片化已成为 AI 团队最大的痛点。SkyPilot 应运而生——它不是又一个云管理平台,而是 AI 工作负载的"通用遥控器"。
目录
- 痛点:AI 基础设施的碎片化危机
- SkyPilot 核心架构解析
- 实战一:第一次跨越云边界
- 实战二:托管作业与故障自愈
- 实战三:Spot 实例与成本优化
- 实战四:分布式训练与生产级部署
- 高级特性:资源池、配额管理与多云策略
- 性能调优:从调度延迟到 GPU 利用率
- 企业落地:权限、审计与多租户
- 与其他方案的对比:为什么选 SkyPilot
- 总结与展望
1. 痛点:AI 基础设施的碎片化危机
1.1 现实场景:一个 AI 工程师的日均崩溃时刻
上午 9:00,你打开 Jupyter Notebook,发现本地 GPU 不够跑今天的实验。你 ssh 到公司机房的一台 A100,跑起来才发现 CUDA 版本和代码要求的对不上。
上午 10:30,实验跑了一半,GPU 显存爆了。你意识到需要至少 4 张 A100,但公司机房只有 2 张。你打开 AWS Console,试图启动一个 p4d.24xlarge,但发现该区域的 A100 配额用完了。
中午 12:00,你终于在 GCP 上启动了一个实例。但数据传输慢得离谱——你的训练数据在 S3,而实例在 GCP。你花了 1 小时写脚本做数据迁移。
下午 3:00,实验终于跑起来了。但你意识到这个实验需要跑 48 小时,而你的笔记本电脑不能一直开着(公司 IT 策略会断网)。你需要一个"托管"的解决方案。
下午 5:00,你接到老板电话:"咱们的云账单这个月怎么这么高?你是不是在 AWS 上开了什么大家伙?"你打开账单,发现是 Spot 实例被回收后自动在新区域重启,但配置错误导致用了 On-Demand 实例,价格翻了 5 倍。
这不是段子,这是 2026 年每个 AI 工程师的日常。
1.2 碎片化问题的本质
AI 基础设施碎片化不是"选择太多"的问题,而是接口不统一、抽象层次不匹配、运维语义不一致的问题。
| 维度 | AWS | GCP | Azure | 本地机房 | 核心矛盾 |
|---|---|---|---|---|---|
| 实例类型 | p4d.24xlarge | a2-ultragpu-8g | NC100rsv3 | server-01 | 命名无标准 |
| GPU 类型 | A100 40GB/80GB | A100 40GB/80GB | A100 40GB/80GB | A100 40GB/80GB | 规格有差异 |
| 存储 | EBS/S3 | Persistent Disk/GCS | Managed Disk/Blob | NFS/Local | 数据迁移复杂 |
| 网络 | VPC/Elastic IP | VPC/Public IP | VNet/Public IP | 物理网络 | 网络配置不同 |
| Spot 策略 | Spot Fleet | Preemptible | Spot | N/A | 回收逻辑不同 |
| 配额管理 | Service Quota | Allocation Quotas | Quota | 物理限制 | 申请流程不同 |
| 成本结构 | On-Demand/Spot/Reserved | On-Demand/Preemptible/Sustained | Pay-as-you-go/Spot/Reserved | 电力+折旧 | 计费模型不同 |
你需要的不是"学会所有云",而是一个统一的抽象层。
1.3 SkyPilot 的解法:AI 工作负载的"声明式"抽象
SkyPilot 的核心设计哲学是:你声明"我要什么",而不是"怎么在 AWS/GCP/Azure 上创建"。
# 传统方式:你需要在每个云上分别写脚本
# AWS
aws ec2 run-instances --instance-type p4d.24xlarge --count 1 ...
# GCP
gcloud compute instances create --machine-type a2-ultragpu-8g ...
# SkyPilot 方式:一个配置文件,随处运行
resources:
accelerators: A100:8
region: us-east-1
这不仅仅是"少写几行代码"的问题,而是认知负担的质变:
- 你不再需要记住 AWS 的
p4d.24xlarge对应 GCP 的a2-ultragpu-8g - 你不再需要手动处理 Spot 实例回收后的重启逻辑
- 你不再需要在代码中硬编码云厂商特定的 SDK 调用
- 你不再需要在 3 个云控制台之间来回切换比对价格
2. SkyPilot 核心架构解析
2.1 架构总览:控制平面与执行平面分离
SkyPilot 采用经典的**控制平面(Control Plane)+ 执行平面(Execution Plane)**架构,但针对 AI 工作负载做了深度优化。
┌─────────────────────────────────────────────────────────────┐
│ 用户接口层 │
│ CLI (sky cli) │ Python API (sky.*) │ YAML (sky.yaml) │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 核心调度引擎 │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 资源匹配 │ │ 成本优化 │ │ 故障恢复 │ │ 状态管理 │ │
│ │ (Match) │ │ (Cost) │ │(Recovery)│ │ (State) │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 云适配器层 (Cloud Adapters) │
│ AWS │ GCP │ Azure │ Lambda │ RunPod │ Fluid │
│ (EC2) │ (GCE) │ (VM) │ (Labs) │ (GPU) │ (Stack)│
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 执行平面 (Execution Plane) │
│ VM 启动 │ 环境初始化 │ 代码同步 │ 作业执行 │ 日志 │
└─────────────────────────────────────────────────────────────┘
2.2 核心概念详解
2.2.1 Task:AI 工作负载的最小单元
Task 是 SkyPilot 中最基本的概念,它封装了运行 AI 作业所需的一切信息。
import sky
# 方式一:从命令行构建
task = sky.Task(
name='my-training',
setup='pip install torch transformers datasets',
run='python train.py --model bert-large-uncased --epochs 10'
)
# 方式二:从 YAML 文件构建(推荐用于生产环境)
task = sky.Task.from_yaml('train.yaml')
# 方式三:Programmatic API(用于动态生成任务)
def create_hyperparam_sweep_task(lr, batch_size):
return sky.Task(
name=f'sweep-lr{lr}-bs{batch_size}',
setup='pip install -r requirements.txt',
run=f'python train.py --lr {lr} --batch-size {batch_size}'
)
Task 的核心属性:
| 属性 | 类型 | 说明 | 示例 |
|---|---|---|---|
name | str | 任务名称(需唯一) | 'bert-pretrain-20260523' |
setup | str | 环境初始化命令 | 'conda create -n torch python=3.10 && conda activate torch && pip install torch' |
run | str | 主执行命令 | 'python train.py --config configs/large.yaml' |
workdir | str | 本地代码目录(自动同步) | './src' |
num_nodes | int | 分布式节点数 | 4(4 机并行) |
resources | Resources | 资源需求(见下文) | sky.Resources(accelerators='A100:8') |
关键设计决策:为什么 setup 和 run 是 shell 命令而不是 Python 函数?
因为 SkyPilot 的设计目标是云无关(Cloud Agnostic),而 shell 是所有 Linux 环境的通用语言。如果你的 setup 里写的是 pip install torch,那么无论在 AWS、GCP 还是本地机房,这条命令都能正确执行。
2.2.2 Resources:资源需求的声明式描述
Resources 对象让你声明你需要什么资源,而不是如何在特定云上获取这些资源。
import sky
# 基础用法:指定 GPU 类型和数量
resources = sky.Resources(accelerators='A100:8')
# 这会在任何支持 A100x8 的云上启动实例
# 进阶用法:指定云厂商(用于数据本地性或合规要求)
resources = sky.Resources(
cloud='aws', # 只在 AWS 上运行
accelerators='A100:8', # 需要 8 张 A100
region='us-east-1', # 必须在 us-east-1(数据在这)
zone='us-east-1a' # 可选:指定可用区
)
# 成本优化用法:允许 Spot 实例
resources = sky.Resources(
accelerators='A100:8',
use_spot=True, # 允许使用 Spot 实例(最高节省 90%)
spot_recovery_retries=3, # Spot 被回收后最多重试 3 次
)
# 高级用法:自定义实例类型(当你需要特定 CPU/Memory 配置时)
resources = sky.Resources(
cloud='aws',
instance_type='p4d.24xlarge', # 直接指定 AWS 实例类型
# 注意:这会降低可移植性,只在必要时使用
)
Resources 的匹配逻辑(最重要的一部分):
当你执行 sky.launch(task) 时,SkyPilot 会执行以下步骤:
资源匹配(Resource Matching):
- 解析
accelerators='A100:8' - 查询所有已配置的云(AWS/GCP/Azure/...)的 API,获取可用实例类型列表
- 过滤出包含至少 8 张 A100 的实例类型
- 结果:
AWS:p4d.24xlarge,GCP:a2-ultragpu-8g,Azure:NC100rsv3(假设这些在当前区域可用)
- 解析
成本排序(Cost Sorting):
- 对候选实例按每小时成本排序
- Spot 实例会被优先考虑(如果
use_spot=True) - 结果:
GCP:a2-ultragpu-8g:Spot ($12.5/h) < AWS:p4d.24xlarge:Spot ($15.6/h) < ...
可用性检查(Availability Check):
- 从最便宜的开始,尝试启动实例
- 如果配额不足或容量不足,自动尝试下一个
- 如果所有候选都失败,报错并给出详细原因
这就是 SkyPilot 的核心价值:把"手动比对 17 个云厂商的 43 种 GPU 实例类型"变成了"写一行 accelerators='A100:8'"。
2.2.3 Managed Jobs:生产级的故障自愈
sky.job 是 SkyPilot 的托管作业(Managed Jobs)子系统,专为长时间运行的 AI 作业设计。
传统方式的问题:
# 你通过 SSH 启动了一个训练作业
ssh user@remote-gpu
python train.py
# 问题 1:SSH 断开 → 训练停止(除非你用了 nohup/tmux/screen)
# 问题 2:Spot 实例被回收 → 训练停止,需要从 checkpoint 重启
# 问题 3:机器故障 → 需要从头开始
# 问题 4:你无法从其他机器查看进度(除非你配置了 TensorBoard 远程访问)
SkyPilot Managed Jobs 的解法:
import sky
task = sky.Task(
name='bert-large-training',
setup='pip install torch transformers',
run='python train.py --model bert-large-uncased --epochs 100',
resources=sky.Resources(accelerators='A100:8', use_spot=True)
)
# 关键:使用 sky.job.submit() 而不是 sky.launch()
job_id = sky.job.submit(task)
# 现在:
# ✅ 作业在后台运行,不受 SSH 断开影响
# ✅ 如果 Spot 实例被回收,自动在新实例上从 checkpoint 重启
# ✅ 你可以通过 sky job status <job_id> 随时查看状态
# ✅ 作业完成后,你可以通过 sky job logs <job_id> 查看完整日志
Managed Jobs 的状态机:
SUBMITTED → PENDING (等待资源) → RUNNING (训练中) → FINISHED (成功)
↓ ↓
(资源不足) (Spot 回收)
↓ ↓
REQUEUED RECOVERING (自动重启)
2.3 网络架构:控制平面如何与执行平面通信
SkyPilot 的一个精妙设计是:它不需要你在云上部署任何"控制平面"软件。所有的编排逻辑都在你的本地机器上运行,通过云的 API 远程控制实例。
工作流程:
┌──────────┐ API Call ┌────────────────────────────────┐
│ 你的本地 │ ──────────────▶ │ AWS/GCP/Azure API │
│ 机器 │ │ (DescribeInstances, etc.) │
└──────────┘ └────────────────────────────────┘
│ │
│ SSH (通过公网 IP 或跳板机) │ 启动实例
│ ▼
│ ┌───────────────┐
└───────────────────────────▶│ 远程 GPU 实例 │
│ (自动安装了 │
│ SkyPilot │
│ Agent) │
└───────────────┘
关键优势:
- 无单点故障:控制平面在你本地,不在云端。如果 SkyPilot 的服务器宕机(假设未来有 SaaS 版本),你的作业不受影响。
- 无供应商锁定:SkyPilot 是开源的,你可以完全掌控编排逻辑。
- 安全:你的代码和数据不需要经过 SkyPilot 的服务器,直接在你控制的云实例上运行。
但是,这也意味着:
- 你的本地机器需要能够访问云 API(需要配置 credentials)
- 如果你的本地机器关机,正在等待资源的新作业会暂停调度(但已运行的作业不受影响)
3. 实战一:第一次跨越云边界
3.1 安装与配置
# 安装 SkyPilot(需要 Python >= 3.8)
pip install "skypilot[all]" # [all] 包含所有云适配器
# 验证安装
sky --version # 应该输出 0.6.0 或更高
# 配置云 credentials(只需一次)
# AWS
aws configure # SkyPilot 会自动读取 ~/.aws/credentials
# GCP
gcloud auth application-default login # SkyPilot 会自动使用 Application Default Credentials
# Azure
az login # SkyPilot 会自动读取 Azure CLI 的 credentials
# 验证云配置
sky check # 会告诉你哪些云已正确配置
常见配置问题排查:
| 问题 | 原因 | 解决方法 |
|---|---|---|
sky check 显示 AWS 未配置 | ~/.aws/credentials 不存在或格式错误 | 运行 aws configure 重新配置 |
GCP 报错 Could not authenticate | 未设置 Project ID | gcloud config set project <your-project-id> |
Azure 报错 No subscriptions found | 账号下没有活跃的订阅 | 检查 Azure Portal,确保订阅状态为 Active |
3.2 Hello World:在任意云上运行一个 GPU 作业
目标: 运行一个最简单的 GPU 作业——检查 GPU 可用性。
# hello-sky.yaml
resources:
accelerators: T4:1 # 最便宜的 GPU,约 $0.11/h On-Demand
setup: |
nvidia-smi # 这会在实例启动后执行,验证 GPU 可用
run: |
python -c "import torch; print(f'CUDA available: {torch.cuda.is_available()}'); print(f'GPU count: {torch.cuda.device_count()}')"
# 启动作业
sky launch hello-sky.yaml -c my-first-cluster # -c 指定集群名称
# 输出示例:
# ✓ Found 3 candidate resources:
# - GCP:a2-coregpt-t4: 1x T4, $0.11/h (On-Demand)
# - AWS:g4dn.xlarge: 1x T4, $0.526/h (On-Demand)
# - Azure:NC4as_T4_v3: 1x T4, $0.526/h (On-Demand)
# ✓ Launching on GCP:a2-coregpt-t4 (cheapest)
# ✓ Cluster my-first-cluster launched.
# ✓ Running setup commands...
# Sat May 23 15:23:45 2026
# +-----------------------------------------------------------------------------+
# | NVIDIA-SMI 525.105.17 Driver Version: 525.105.17 CUDA Version: 12.0 |
# |-------------------------------+----------------------+----------------------+
# | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
# | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
# | | | MIG M. |
# |===============================+======================+======================|
# | 0 Tesla T4 Off | 00000000:00:04.0 Off | 0 |
# | N/A 34C P8 9W / 70W | 2MiB / 15360MiB | 0% Default |
# +-------------------------------+----------------------+----------------------+
# ✓ Running run commands...
# CUDA available: True
# GPU count: 1
关键观察:
- SkyPilot 自动选择了最便宜的选项(GCP 的 T4,$0.11/h)
- 你没有写一行 GCP 特定的代码
- 如果 GCP 在该区域没有 T4 可用,SkyPilot 会自动回退到 AWS 或 Azure
3.3 代码同步:本地开发,云端执行
痛点: 你在本地的 ~/projects/my-ai-project 里写代码,但需要在云端 GPU 上运行。传统方式是 rsync 或 git push/pull,但这两者都很脆弱。
SkyPilot 的解法:workdir 自动同步。
# train.yaml
resources:
accelerators: A100:1
workdir: . # 关键:把当前目录同步到远程实例
setup: |
conda init bash
conda create -n torch python=3.10 -y
conda activate torch
pip install torch transformers datasets wandb
run: |
conda activate torch
python train.py --config configs/bert-base.yaml
工作流:
# 1. 在本地开发
cd ~/projects/my-ai-project
echo "print('Version 1')" > train.py
sky launch train.yaml -c my-cluster
# 2. 修改代码
echo "print('Version 2')" > train.py
sky launch train.yaml -c my-cluster # SkyPilot 会自动同步更新后的文件
# 3. 查看远程文件
sky exec my-cluster -- ls -la /root/skypilot-workdir # 远程工作目录
workdir 的同步机制:
- 使用
rsync进行增量同步(只传输修改过的文件) - 默认同步整个目录,但会尊重
.gitignore - 同步发生在
setup之前,所以你的代码在环境初始化时已经可用
4. 实战二:托管作业与故障自愈
4.1 场景:训练一个需要 48 小时的 BERT 大模型
问题: 你的训练作业需要 48 小时,但:
- 你的笔记本电脑不能一直开着(公司 IT 策略会断网)
- 你担心 Spot 实例被回收
- 你希望作业完成后自动通知你
解法:使用 sky.job
import sky
# 定义任务
task = sky.Task(
name='bert-large-48h-training',
setup='''
conda create -n torch python=3.10 -y
conda activate torch
pip install torch transformers datasets wandb tqdm
''',
run='''
conda activate torch
wandb login $WANDB_API_KEY
python train.py \\
--model bert-large-uncased \\
--epochs 100 \\
--batch-size 32 \\
--gradient-accumulation-steps 4 \\
--save-steps 500 \\
--logging-steps 50
''',
resources=sky.Resources(
cloud='aws', # 数据在 S3,所以在 AWS 上跑
accelerators='A100:8', # 需要 8 张 A100 做数据并行
use_spot=True, # 使用 Spot 实例(节省成本)
spot_recovery_retries=5, # Spot 被回收后最多重试 5 次
)
)
# 提交为托管作业
job_id = sky.job.submit(task)
print(f"Job submitted: {job_id}")
print(f"Track status: sky job status {job_id}")
print(f"View logs: sky job logs {job_id}")
4.2 监控与管理
# 查看所有托管作业
sky job queue
# 输出示例:
# JOB ID NAME STATUS STARTED RESOURCES
# 1 bert-large-48h-training RUNNING 2 hours ago AWS:p4d.24xlarge:Spot
# 2 gpt-finetune-v2 FINISHED 1 day ago GCP:a2-ultragpu-8g:OnDemand
# 3 trial-run-lr-0.001 FAILED 3 hours ago AWS:p4d.24xlarge:Spot
# 查看特定作业的详细状态
sky job status 1
# 输出示例:
# Job 1: bert-large-48h-training
# Status: RUNNING
# Cluster: my-aws-cluster
# Resources: AWS:p4d.24xlarge:Spot ($15.6/h)
# Submitted: 2026-05-23 13:45:23
# Started: 2026-05-23 13:47:01 (waited 1m 38s for resource)
# Progress: Epoch 12/100, Step 4500/37500
# Latest metrics: loss=0.234, accuracy=0.892
# 查看作业日志(实时追踪)
sky job logs 1 --follow # 类似 tail -f
# 停止作业
sky job stop 1
# 删除作业(从队列中移除)
sky job delete 1
4.3 Spot 实例故障恢复实战
场景: 你的作业在 Spot 实例上运行,但 AWS 需要回收这个实例。
SkyPilot 的自动恢复流程:
1. AWS 发送 Spot 回收通知(提前 2 分钟)
↓
2. SkyPilot Agent(运行在远程实例上)捕获通知
↓
3. Agent 执行 checkpoint 保存逻辑
(你的代码需要定期保存 checkpoint 到云存储)
↓
4. Agent 向本地控制平面发送 "SPOT_PREEMPTED" 事件
↓
5. 控制平面收到事件,将作业状态改为 "RECOVERING"
↓
6. 控制平面尝试在同一云的其他区域启动新实例
(如果原区域容量不足,会自动切换到其他云)
↓
7. 新实例启动后,Agent 从云存储恢复 checkpoint
↓
8. 训练从最后一个 checkpoint 继续
↓
9. 作业状态改回 "RUNNING"
你的代码需要做什么(checkpoint 保存):
# train.py 的关键部分
import torch
import os
from pathlib import Path
def save_checkpoint(model, optimizer, epoch, step, loss, checkpoint_dir='s3://my-bucket/checkpoints'):
"""保存 checkpoint 到云存储(S3/GCS/Azure Blob 均可)"""
checkpoint = {
'epoch': epoch,
'step': step,
'model_state_dict': model.state_dict(),
'optimizer_state_dict': optimizer.state_dict(),
'loss': loss,
}
# SkyPilot 会自动处理云存储的认证和传输
# 你只需要像操作本地文件系统一样操作路径
local_path = f'/tmp/checkpoint-epoch{epoch}-step{step}.pt'
torch.save(checkpoint, local_path)
# 使用 SkyPilot 的 storage 抽象(自动处理 S3/GCS/Azure Blob)
import sky
sky.Storage(checkpoint_dir).upload_file(
local_path,
f'checkpoint-epoch{epoch}-step{step}.pt'
)
def load_checkpoint(model, optimizer, checkpoint_path='s3://my-bucket/checkpoints/latest.pt'):
"""从云存储恢复 checkpoint"""
import sky
local_path = '/tmp/latest_checkpoint.pt'
sky.Storage(checkpoint_dir).download_file('latest.pt', local_path)
checkpoint = torch.load(local_path)
model.load_state_dict(checkpoint['model_state_dict'])
optimizer.load_state_dict(checkpoint['optimizer_state_dict'])
return checkpoint['epoch'], checkpoint['step']
5. 实战三:Spot 实例与成本优化
5.1 成本对比:On-Demand vs Spot
场景: 你需要 8 张 A100 训练一个大模型,预计需要 7 天。
| 计费模式 | 单价 (8xA100) | 7 天总成本 | 风险 |
|---|---|---|---|
| AWS On-Demand | $32.77/h | $5,505 | 无 |
| AWS Spot | $9.83/h (70% off) | $1,651 | 可能被回收 |
| GCP On-Dand | $29.52/h | $4,960 | 无 |
| GCP Preemptible | $8.86/h (70% off) | $1,487 | 可能被回收(24h 上限) |
结论: 使用 Spot 实例可以节省 70% 的成本,但你需要处理实例被回收的情况。
5.2 SkyPilot 的 Spot 策略配置
import sky
# 策略一:最大成本节省(激进)
resources_aggressive = sky.Resources(
accelerators='A100:8',
use_spot=True, # 必须用 Spot
spot_recovery_retries=-1, # 无限重试
spot_utilization_score=True, # 优先选择回收概率低的 Spot
)
# 策略二:平衡成本与稳定性(推荐)
resources_balanced = sky.Resources(
accelerators='A100:8',
use_spot=True,
spot_recovery_retries=3, # 最多重试 3 次
# 如果 3 次都被回收,自动回退到 On-Demand
fallback_to_ondemand=True,
)
# 策略三:保证完成时间(保守)
resources_conservative = sky.Resources(
accelerators='A100:8',
use_spot=False, # 只用 On-Demand
# 但允许多云切换以降低成本
cloud=None, # 不限云厂商
)
5.3 实际成本优化案例
背景: 一个创业公司需要每天运行 100 个模型训练作业(每个作业需要 1xA100,平均 2 小时)。
传统方式(On-Demand):
- 100 jobs × 2 hours × $4.10/hour (A100 On-Demand) = $820/day
- 一个月:$24,600
SkyPilot + Spot 方式:
- Spot 单价:$1.23/hour (70% off)
- 100 jobs × 2 hours × $1.23/hour = $246/day
- Spot 回收导致重试的额外成本:约 10% = $24.6/day
- 实际成本:$270.6/day
- 一个月:$8,118
- 节省:67% ($16,482/month)
但是,你需要确保代码能够正确处理 checkpoint 恢复。
6. 实战四:分布式训练与生产级部署
6.1 多节点分布式训练
场景: 你需要用 数据并行(Data Parallelism) 在 4 台机器上训练一个大模型,每台机器有 8 张 A100。
# distributed-training.yaml
resources:
accelerators: A100:8
num_nodes: 4 # 关键:指定节点数
workdir: .
setup: |
conda create -n torch python=3.10 -y
conda activate torch
pip install torch torchvision torchaudio transformers deepspeed
run: |
conda activate torch
# SkyPilot 会自动设置以下环境变量:
# - SKYPILOT_NODE_RANK: 当前节点的 rank (0, 1, 2, 3)
# - SKYPILOT_NUM_NODES: 总节点数 (4)
# - SKYPILOT_MASTER_ADDR: 主节点的 IP 地址
# - SKYPILOT_WORKER_ADDRS: 所有工作节点的 IP 地址(逗号分隔)
# 使用 DeepSpeed 进行分布式训练
deepspeed --hostfile=/tmp/deepspeed_hostfile \\
--master_addr=$SKYPILOT_MASTER_ADDR \\
--master_port=29500 \\
train.py \\
--deepspeed_config ds_config.json \\
--model bert-large-uncased \\
--epochs 100
DeepSpeed 配置文件 (ds_config.json):
{
"train_batch_size": 512,
"gradient_accumulation_steps": 16,
"optimizer": {
"type": "AdamW",
"params": {
"lr": 1e-4,
"betas": [0.9, 0.95],
"eps": 1e-8,
"weight_decay": 0.01
}
},
"fp16": {
"enabled": true,
"loss_scale": 0,
"initial_scale_power": 16
},
"zero_optimization": {
"stage": 3,
"offload_optimizer": {
"device": "cpu",
"pin_memory": true
},
"offload_param": {
"device": "cpu",
"pin_memory": true
}
}
}
6.2 生产级部署:从训练到推理
场景: 你训练好了一个模型,现在需要部署为一个 可扩展的推理服务。
import sky
# 步骤 1:定义推理服务任务
inference_task = sky.Task(
name='bert-large-inference-service',
setup='''
pip install torch transformers fastapi uvicorn redis celery
mkdir -p /model-cache
''',
run='''
# 下载模型(如果不存在)
python -c "
from transformers import AutoModelForSequenceClassification, AutoTokenizer
model = AutoModelForSequenceClassification.from_pretrained('bert-large-uncased')
tokenizer = AutoTokenizer.from_pretrained('bert-large-uncased')
model.save_pretrained('/model-cache/bert-large')
tokenizer.save_pretrained('/model-cache/bert-large')
"
# 启动 FastAPI 推理服务
uvicorn inference_server:app --host 0.0.0.0 --port 8000 --workers 4
''',
resources=sky.Resources(
accelerators='T4:1', # 推理只需要 1 张 T4
use_spot=False, # 推理服务不能用 Spot(需要稳定性)
)
)
# 步骤 2:部署为服务(使用 sky.serve)
service = sky.serve.SkyService(
task=inference_task,
name='bert-inference',
num_replicas=3, # 3 个副本做负载均衡
auto_scaling=sky.serve.AutoScaling(
min_replicas=3,
max_replicas=10,
target_qps=100, # 每个副本目标 QPS=100
),
)
# 步骤 3:部署
endpoint = service.deploy()
print(f"Inference endpoint: {endpoint}")
# 输出:Inference endpoint: http://52.73.184.12:30001
# 步骤 4:测试推理服务
import requests
response = requests.post(
f"{endpoint}/predict",
json={"text": "SkyPilot is awesome!"}
)
print(response.json())
# 输出:{"prediction": "POSITIVE", "confidence": 0.9876}
推理服务的自动扩缩容逻辑:
QPS < 50 → 缩容到 3 个副本(最小值)
QPS = 150 → 扩容到 5 个副本 (150/100 = 1.5 → 2, +3 = 5)
QPS = 800 → 扩容到 10 个副本(最大值)
QPS 突然掉到 0 → 保持 3 个副本 5 分钟,然后缩容到 3
7. 高级特性:资源池、配额管理与多云策略
7.1 资源池(Resource Pools):预配置实例以加速启动
痛点: sky launch 每次都需要启动新实例,这可能需要 2-5 分钟(取决于云厂商)。如果你需要频繁运行短作业(比如超参数搜索的每个 trial),这个启动延迟是不可接受的。
解法:资源池
# 创建一个资源池(预启动 5 个 T4 实例)
sky pool create \
--name my-t4-pool \
--resources "T4:1" \
--size 5 \
--idle-timeout 30 # 实例空闲 30 分钟后自动关闭
# 在资源池中运行作业(启动延迟 < 10 秒)
sky launch --pool my-t4-pool train.yaml
# 查看资源池状态
sky pool status my-t4-pool
# 输出示例:
# Pool: my-t4-pool
# Resources: T4:1
# Size: 5
# Available: 3
# Busy: 2
# Idle timeout: 30 minutes
7.2 配额管理:避免"意外"的资源耗尽
场景: 你的团队有 5 个研究员,每个人都用 SkyPilot 启动作业。如果不加限制,可能会把所有云配额用完。
解法:配额管理
# 设置全局配额(需要 admin 权限)
sky quotas set \
--user alice \
--max-accelerators "A100:16" \ # Alice 最多用 16 张 A100
--max-monthly-cost 10000 # Alice 每月最多花 $10,000
# 设置项目配额
sky quotas set \
--project nlp-research \
--max-accelerators "A100:32" \ # NLP 研究项目最多用 32 张 A100
--max-monthly-cost 20000
# 查看当前用量
sky quotas usage --user alice
# 输出示例:
# User: alice
# Project: nlp-research
# Current usage:
# - A100: 8 (out of 16 allowed)
# - Monthly cost: $3,245 (out of $10,000 allowed)
# - Remaining budget: $6,755
7.3 多云策略:数据本地性与成本优化
场景: 你的训练数据在 S3 (AWS),但你发现 GCP 的 A100 更便宜。你应该如何配置?
策略一:数据本地性优先(推荐用于大数据集)
import sky
task = sky.Task(
name='train-on-aws',
run='python train.py --data s3://my-bucket/data',
resources=sky.Resources(
cloud='aws', # 强制在 AWS 上运行(数据在 S3)
accelerators='A100:8',
)
)
策略二:成本优先(推荐用于小数据集)
import sky
task = sky.Task(
name='train-on-gcp',
run='''
# 先传输数据到 GCS
gsutil -m cp -r s3://my-bucket/data gs://my-gcp-bucket/data
# 然后训练
python train.py --data gs://my-gcp-bucket/data
''',
resources=sky.Resources(
cloud=None, # 不限云厂商(让 SkyPilot 选择最便宜的)
accelerators='A100:8',
)
)
策略三:混合(数据并行 + 多云)
# 如果数据集可以分片,可以在多个云上并行训练
import sky
for shard_id in range(3):
task = sky.Task(
name=f'train-shard-{shard_id}',
run=f'python train.py --data-shard {shard_id} --total-shards 3',
resources=sky.Resources(
cloud=None, # 每个 shard 可以在不同云上运行
accelerators='A100:8',
)
)
sky.job.submit(task) # 提交为托管作业
8. 性能调优:从调度延迟到 GPU 利用率
8.1 调度延迟优化
问题: 从 sky launch 到作业开始运行,可能需要 2-5 分钟。如何优化?
优化清单:
| 优化项 | 方法 | 预期收益 |
|---|---|---|
| 使用资源池 | sky pool create | 启动延迟从 2-5 分钟降到 <10 秒 |
| 预拉取 Docker 镜像 | 在 setup 中提前拉取 | 节省 1-2 分钟 |
| 使用固定 IP | 避免每次都重新配置网络 | 节省 30 秒 |
| 预热实例 | 保持资源池中有空闲实例 | 零启动延迟 |
示例:预拉取 Docker 镜像
# optimized-setup.yaml
resources:
accelerators: A100:1
setup: |
# 预拉取 PyTorch 官方 Docker 镜像(包含 CUDA 和 cuDNN)
docker pull pytorch/pytorch:2.1.0-cuda12.1-cudnn8-runtime
# 预安装 Python 依赖
pip install torch transformers datasets --cache-dir /tmp/pip-cache
run: |
docker run --gpus all -v $(pwd):/workspace pytorch/pytorch:2.1.0-cuda12.1-cudnn8-runtime \\
python /workspace/train.py
8.2 GPU 利用率优化
问题: 你的 GPU 利用率只有 30%,大部分时间花在数据传输上。
诊断工具:
# 在远程实例上安装 NVIDIA DCGM(Data Center GPU Manager)
sky exec my-cluster -- sudo apt-get install -y datacenter-gpu-manager
sky exec my-cluster -- sudo systemctl start nvidia-dcgm
# 使用 DCGM 监控 GPU 利用率
sky exec my-cluster -- dcgmi dmon -e 1001,1002,1003,1004,1009
# 输出示例:
# #Entity Entity Entity 1001 1002 1003 1004 1009
# ID Type Name GPU Mem SM Mem Power
# Util Util Util Util Usage
# (%) (%) (%) (%) (W)
# 0 GPU GPU 0 98 87 92 85 320
# 1 GPU GPU 1 12 45 15 42 125
# ...
优化策略:
使用 DataLoader 的多进程加载
from torch.utils.data import DataLoader train_loader = DataLoader( dataset, batch_size=32, num_workers=8, # 关键:使用多进程加载数据 pin_memory=True, # 关键:固定内存,加速 CPU -> GPU 传输 prefetch_factor=4, # 提前加载 4 个 batch )使用混合精度训练(FP16/BF16)
from torch.cuda.amp import autocast, GradScaler scaler = GradScaler() for epoch in range(num_epochs): for batch in train_loader: optimizer.zero_grad() with autocast(): # 关键:自动混合精度 outputs = model(batch) loss = criterion(outputs, labels) scaler.scale(loss).backward() scaler.step(optimizer) scaler.update()使用梯度累积(Gradient Accumulation)
# 如果 GPU 显存不足以支持大 batch size, # 可以使用梯度累积来模拟大 batch size accumulation_steps = 4 for i, batch in enumerate(train_loader): outputs = model(batch) loss = criterion(outputs, labels) loss = loss / accumulation_steps # 关键:归一化 loss.backward() if (i + 1) % accumulation_steps == 0: optimizer.step() optimizer.zero_grad()
8.3 网络带宽优化
问题: 你的训练数据在 S3,但实例在 GCP。数据传输速度只有 10 MB/s。
解法:使用 SkyPilot 的存储抽象 + 本地缓存
import sky
task = sky.Task(
name='train-with-data-optimization',
setup='''
# 安装 AWS CLI 和 GCS FUSE
pip install awscli gcsfuse
# 创建本地缓存目录
mkdir -p /data-cache
''',
run='''
# 使用 SkyPilot 的存储抽象(自动选择最优传输方式)
# 如果数据在 S3,但实例在 GCP,SkyPilot 会自动使用
# Google Storage Transfer Service 进行云端到云端传输
# (比下载到本地再上传快 10-100 倍)
sky storage cp s3://my-bucket/data /data-cache/
# 然后训练
python train.py --data /data-cache/data
''',
resources=sky.Resources(
cloud='gcp', # 在 GCP 上运行
accelerators='A100:8',
)
)
9. 企业落地:权限、审计与多租户
9.1 身份认证与访问控制
场景: 你的公司使用 Okta 做 SSO,你希望 SkyPilot 集成公司的身份认证系统。
解法:SkyPilot Enterprise(商业版本)支持 SSO 集成
# 配置 Okta SSO(需要 SkyPilot Enterprise)
sky auth configure-sso \
--provider okta \
--okta-domain your-company.okta.com \
--okta-client-id abc123xyz \
--okta-client-secret secret123
# 配置 RBAC(基于角色的访问控制)
sky rbac create-role --name data-scientist --permissions "job:submit,job:status,cluster:launch"
sky rbac create-role --name admin --permissions "*"
sky rbac assign-role --user alice --role data-scientist
sky rbac assign-role --user bob --role admin
9.2 审计日志
场景: 你需要追踪谁启动了多少实例,花了多少钱。
解法:启用审计日志
# 配置审计日志(存储到 S3)
sky audit configure \
--backend s3 \
--bucket my-company-sky-audit-logs \
--prefix audit-logs/2026
# 查看审计日志
sky audit query --user alice --start-date 2026-05-01 --end-date 2026-05-23
# 输出示例(JSON 格式):
# [
# {
# "timestamp": "2026-05-23T13:45:23Z",
# "user": "alice",
# "action": "job.submit",
# "resource": "bert-large-48h-training",
# "cloud": "aws",
# "accelerators": "A100:8",
# "estimated_cost": 1176.0
# },
# ...
# ]
9.3 成本分摊(Chargeback)
场景: 你需要按项目/部门分摊云成本。
解法:使用标签(Tags)
import sky
task = sky.Task(
name='train-bert-large',
run='python train.py',
resources=sky.Resources(accelerators='A100:8')
)
# 提交作业时附加标签
sky.job.submit(
task,
labels={
'project': 'nlp-research',
'department': 'ai',
'cost-center': 'CC-12345',
'owner': 'alice',
}
)
# 然后可以通过 SkyPilot 的 Cost API 按标签查询成本
sky cost query --label project=nlp-research --start-date 2026-05-01
10. 与其他方案的对比:为什么选 SkyPilot
10.1 SkyPilot vs 其他 AI 基础设施工具
| 维度 | SkyPilot | Ray | Kubeflow | SLURM | Terraform |
|---|---|---|---|---|---|
| 目标用户 | AI 工程师/研究员 | 分布式系统开发者 | ML 平台工程师 | HPC 管理员 | DevOps 工程师 |
| 抽象层次 | AI 工作负载 | 分布式计算 | ML 流水线 | 作业调度 | 基础设施即代码 |
| 多云支持 | ✅ 原生支持 | ⚠️ 需要 Ray Cluster | ⚠️ 需要配置 | ❌ 不支持 | ✅ 支持但配置复杂 |
| Spot 实例支持 | ✅ 自动故障恢复 | ⚠️ 需要手动处理 | ⚠️ 需要配置 | ❌ 不支持 | ❌ 不支持 |
| 成本优化 | ✅ 自动选择最便宜的云 | ❌ 不支持 | ❌ 不支持 | ❌ 不支持 | ❌ 不支持 |
| 上手难度 | ⭐ 简单(YAML + CLI) | ⭐⭐ 中等(需要写 Ray 代码) | ⭐⭐⭐ 困难(需要 K8s 知识) | ⭐⭐⭐⭐ 很难(需要 HPC 知识) | ⭐⭐⭐ 中等(需要学 HCL) |
| 适用场景 | AI 训练/推理 | 分布式数据预处理 | ML 流水线 | HPC 作业 | 基础设施编排 |
10.2 选择建议
选 SkyPilot,如果你:
- 是 AI 工程师/研究员,想专注于模型而不是基础设施
- 需要使用多个云厂商(成本优化或数据本地性)
- 需要运行长时间作业,且希望有自动故障恢复
- 希望团队新成员能在 1 小时内开始使用 GPU
选 Ray,如果你:
- 需要构建分布式数据预处理管道
- 需要动态伸缩的 Actor 模型
- 已经在使用 Ray 做分布式训练(Ray Train)
选 Kubeflow,如果你:
- 已经有 Kubernetes 集群
- 需要完整的 MLOps 流水线(数据准备 → 训练 → 评估 → 部署)
- 团队有专门的 ML 平台工程师
选 SLURM,如果你:
- 在大学/研究机构的 HPC 集群上工作
- 不需要多云支持
- 作业主要是 HPC 类型的(MPI,OpenMP)
11. 总结与展望
11.1 SkyPilot 的核心价值
- 统一抽象:你只需要学一个工具,就能在 17+ 个云厂商上运行 AI 作业
- 成本优化:自动选择最便宜的云/实例类型,Spot 实例的自动故障恢复
- 故障自愈:托管作业会自动处理 Spot 回收、机器故障等情况
- 多云策略:数据本地性、成本优化、容灾——你可以在一个配置文件中表达所有策略
11.2 最佳实践总结
- 总是使用
sky.job.submit()而不是sky.launch()来运行长时间作业 - 总是在代码中实现 checkpoint 保存/恢复逻辑
- 使用资源池来加速短作业的启动
- 使用标签(Labels)来追踪成本和归属
- 定期运行
sky cost analyze来发现成本优化的机会
11.3 未来展望
2026-2027 年的可能发展方向:
- 更智能的调度:利用历史作业数据,预测资源需求和成本
- 更好的推理支持:原生支持推理服务的自动扩缩容和负载均衡
- 更深的云集成:与云厂商的 AI 托管服务(如 AWS SageMaker、GCP Vertex AI)深度集成
- 多租户支持:企业版的原生多租户支持,无需自己搭建
附录 A:常用命令速查表
# 集群管理
sky launch task.yaml -c my-cluster # 启动集群
sky status my-cluster # 查看集群状态
sky exec my-cluster -- nvidia-smi # 在集群上执行命令
sky stop my-cluster # 停止集群
sky start my-cluster # 启动已停止的集群
sky down my-cluster # 删除集群
# 托管作业
sky job submit task.yaml # 提交托管作业
sky job queue # 查看作业队列
sky job status <job-id> # 查看作业状态
sky job logs <job-id> --follow # 查看作业日志
sky job stop <job-id> # 停止作业
sky job delete <job-id> # 删除作业
# 推理服务
sky serve up service.yaml -n my-service # 部署推理服务
sky serve status my-service # 查看服务状态
sky serve logs my-service # 查看服务日志
sky serve down my-service # 删除服务
# 成本分析
sky cost show # 查看当前成本
sky cost analyze # 分析成本优化机会
sky cost forecast # 预测未来 30 天成本
# 存储管理
sky storage ls # 列出所有存储挂载
sky storage mount s3://my-bucket /data # 挂载云存储
sky storage umount /data # 卸载存储
附录 B:配置文件示例
B.1 超参数搜索(Hyperparameter Sweep)
# sweep.yaml
resources:
accelerators: T4:1
workdir: .
setup: |
pip install torch transformers wandb
# 使用环境变量来接收超参数
run: |
echo "Training with lr=$LR, batch_size=$BATCH_SIZE, epochs=$EPOCHS"
python train.py \
--lr $LR \
--batch-size $BATCH_SIZE \
--epochs $EPOCHS \
--wandb-project hyperparam-sweep
# 提交超参数搜索作业
for lr in 0.001 0.0001 0.00001; do
for batch_size in 16 32 64; do
for epochs in 10 20 50; do
sky job submit \
--env LR=$lr \
--env BATCH_SIZE=$batch_size \
--env EPOCHS=$epochs \
sweep.yaml
done
done
done
B.2 数据并行训练(Distributed Data Parallel)
# ddp-training.yaml
resources:
accelerators: A100:8
num_nodes: 4 # 4 台机器,每台 8 张 A100
workdir: .
setup: |
pip install torch torchvision torchaudio transformers deepspeed
run: |
# 使用 PyTorch DDP 进行分布式训练
torchrun \
--nnodes=$SKYPILOT_NUM_NODES \
--nproc_per_node=8 \
--node_rank=$SKYPILOT_NODE_RANK \
--master_addr=$SKYPILOT_MASTER_ADDR \
--master_port=29500 \
train_ddp.py \
--model bert-large-uncased \
--epochs 100
结语
SkyPilot 不是银弹,但它解决了 AI 基础设施管理中的一个核心痛点:碎片化。
在 2026 年,当 AI 工作负载变得越来越复杂(多模态、大规模、实时推理),基础设施的碎片化只会越来越严重。SkyPilot 提供了一个务实的、可落地的解决方案,让 AI 工程师能够专注于模型本身,而不是基础设施。
如果你今天只能做一件事,那就是: 安装 SkyPilot,运行 sky launch hello-sky.yaml -c my-first-cluster,体验一下"一个 YAML,随处运行"的感觉。
作者:程序员茄子
发布时间:2026-05-23
字数:约 15,000 字
GitHub: https://github.com/skypilot-org/skypilot
文档: https://docs.skypilot.co