托管作业#

提示

此功能非常适合横向扩展:长时间运行单个作业,或并行运行大量作业。

SkyPilot 支持托管作业sky jobs),它可以自动重试失败、从 Spot 实例抢占中恢复并在完成后清理。

要启动托管作业,请使用 sky jobs launch

$ sky jobs launch -n myjob hello_sky.yaml

Task from YAML spec: hello_sky.yaml
Managed job 'myjob' will be launched on (estimated):
Considered resources (1 node):
------------------------------------------------------------------------------------------
 CLOUD   INSTANCE      vCPUs   Mem(GB)   ACCELERATORS   REGION/ZONE   COST ($)   CHOSEN
------------------------------------------------------------------------------------------
 AWS     m6i.2xlarge   8       32        -              us-east-1     0.38          ✔
------------------------------------------------------------------------------------------
Launching a managed job 'myjob'. Proceed? [Y/n]: Y
... <job is submitted and launched>
(setup pid=2383) Running setup.
(myjob, pid=2383) Hello, SkyPilot!
✓ Managed job finished: 1 (status: SUCCEEDED).

Managed Job ID: 1
📋 Useful Commands
├── To cancel the job:                sky jobs cancel 1
├── To stream job logs:               sky jobs logs 1
├── To stream controller logs:        sky jobs logs --controller 1
├── To view all managed jobs:         sky jobs queue
└── To view managed job dashboard:    sky jobs dashboard

作业在临时 SkyPilot 集群上启动,进行端到端管理,并自动清理。

托管作业有以下几个优点

  1. 使用 Spot 实例:作业可以在自动恢复的 Spot 实例上运行。这通过使可抢占 Spot 实例对长时间运行的作业有用,从而显著节省成本(例如,GPU VM 可节省约 70%)。

  2. 跨区域和云服务商扩展:轻松同时运行和管理数千个作业,使用跨多个区域/云服务商的实例和 GPU。

  3. 从故障中恢复:当作业失败时,您可以自动在新集群上重试,消除不稳定失败。

  4. 托管管道:运行包含多个任务的管道。这对于运行相互依赖的一系列任务非常有用,例如数据处理、训练模型,然后在模型上运行推理。

创建托管作业#

托管作业是使用标准 SkyPilot YAML 创建的。例如

# bert_qa.yaml
name: bert-qa

resources:
  accelerators: V100:1
  use_spot: true  # Use spot instances to save cost.

envs:
  # Fill in your wandb key: copy from https://wandb.ai/authorize
  # Alternatively, you can use `--env WANDB_API_KEY=$WANDB_API_KEY`
  # to pass the key in the command line, during `sky jobs launch`.
  WANDB_API_KEY:

# Assume your working directory is under `~/transformers`.
# To get the code for this example, run:
# git clone https://github.com/huggingface/transformers.git ~/transformers -b v4.30.1
workdir: ~/transformers

setup: |
  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 examples/pytorch/question-answering/
  python 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 \
    --output_dir /tmp/bert_qa/

注意

工作目录 (Workdir)包含本地文件的文件挂载 (file mounts) 将被自动上传到云存储桶。作业完成后,存储桶将被清理。

要将此 YAML 作为托管作业启动,请使用 sky jobs launch

$ sky jobs launch -n bert-qa-job bert_qa.yaml

要查看所有标志,您可以运行 sky jobs launch --help 或查看CLI 参考获取更多信息。

SkyPilot 将启动并开始监控该作业。

  • 在后台,SkyPilot 会为作业启动一个临时集群。

  • 如果发生 Spot 抢占或任何机器故障,SkyPilot 将自动跨区域和云服务商搜索资源以重新启动作业。

  • 作业完成后,资源会立即清理。

提示

您可以在非托管的 sky launch 上测试您的 YAML,然后使用 sky jobs launch 进行生产运行作为托管作业。

sky launchsky jobs launch 界面相似,但在不同场景下有用。

sky launch(集群作业)

sky jobs launch(托管作业)

长期存在、手动管理的集群

为每个作业专门配置的自动管理的集群

Spot 抢占必须手动恢复

Spot 抢占自动恢复

并行作业数量受限于集群资源

轻松同时管理数百或数千个作业

适合交互式开发

适合横向扩展生产作业

使用托管作业#

要查看所有命令和选项的列表,请运行 sky jobs --help 或阅读CLI 参考

查看所有托管作业列表

$ sky jobs queue
Fetching managed jobs...
Managed jobs:
ID NAME     RESOURCES           SUBMITTED   TOT. DURATION   JOB DURATION   #RECOVERIES  STATUS
2  roberta  1x [A100:8][Spot]   2 hrs ago   2h 47m 18s      2h 36m 18s     0            RUNNING
1  bert-qa  1x [V100:1][Spot]   4 hrs ago   4h 24m 26s      4h 17m 54s     0            RUNNING

流式查看正在运行的托管作业的日志

$ sky jobs logs -n bert-qa  # by name
$ sky jobs logs 2           # by job ID

取消托管作业

$ sky jobs cancel -n bert-qa  # by name
$ sky jobs cancel 2           # by job ID

注意

如果托管作业发生任何故障,您可以查看 sky jobs queue -a 获取失败的简要原因。有关资源调配的更多详细信息,请查看 sky jobs logs --controller <job_id>

作业仪表盘#

使用 sky jobs dashboard 打开仪表盘查看所有作业

$ sky jobs dashboard

这将自动打开浏览器选项卡以显示仪表盘

../_images/managed-jobs-dashboard.png

UI 显示的信息与 CLI sky jobs queue -a 相同。当需要监控大量进行中的作业时,UI 特别有用,因为基于终端的 CLI 可能需要多页才能显示。

在 Spot 实例上运行#

托管作业可以在 Spot 实例上运行,SkyPilot 会自动恢复抢占。

要在 Spot 实例上运行,请使用 sky jobs launch --use-spot,或在您的 SkyPilot YAML 中指定 use_spot: true

name: spot-job

resources:
  accelerators: A100:8
  use_spot: true

run: ...

提示

Spot 实例是可能被“抢占”的云虚拟机。云服务商可以强制关闭底层虚拟机并移除您的访问权限,从而中断在该实例上运行的作业。

作为交换,Spot 实例比不受抢占影响的普通实例(所谓的“按需”实例)便宜得多。根据云服务商和虚拟机类型的不同,Spot 实例可以便宜 70-90%。

SkyPilot 会自动跨区域和云服务商查找可用的 Spot 实例以最大化可用性。任何 Spot 抢占都由 SkyPilot 自动处理,无需用户干预。

注意

默认情况下,每次抢占恢复后,作业将从头开始重启。为避免恢复后重复工作,请实现检查点和恢复。您的应用程序代码可以定期将其进度检查点保存到挂载的云存储桶中。程序在重启时可以重新加载最新的检查点。

这里是训练作业的示例,它可以在 AWS 和 GCP 的不同区域之间故障转移。

GIF for BERT training on Spot V100

托管 Spot 作业启动非托管 Spot 集群 快速对比

命令

是否托管?

可 SSH 连接?

最适合用于

sky jobs launch --use-spot

是,抢占自动恢复

横向扩展长时间运行的作业(例如,数据处理、训练、批量推理)

sky launch --use-spot

否,不处理抢占

在 Spot 实例上进行交互式开发(特别是对于抢占率低的硬件)

Spot 或按需/预留实例#

默认情况下,将使用按需实例(而非 Spot 实例)。要使用 Spot 实例,您必须在命令行上指定 --use-spot 或在您的 SkyPilot YAML 中指定 use_spot: true

但是,您也可以告诉 SkyPilot 根据可用性使用Spot 实例和按需实例。在您的 SkyPilot YAML 中,使用 any_of 指定 Spot 或按需/预留实例作为作业的候选资源。有关更多详细信息,请参阅此处的文档。

resources:
  accelerators: A100:8
  any_of:
    - use_spot: true
    - use_spot: false

在此示例中,SkyPilot 将选择最便宜的资源使用,这几乎肯定是 Spot 实例。如果 Spot 实例不可用,SkyPilot 将回退到启动按需/预留实例。

检查点和恢复#

为了从 Spot 实例抢占中快速恢复,通常需要一个云存储桶来存储作业的状态(例如,模型检查点)。未存储在云存储桶中的任何磁盘数据将在恢复过程中丢失。

下面是将存储桶挂载到 /checkpoint 的示例

file_mounts:
  /checkpoint:
    name: # NOTE: Fill in your bucket name
    mode: MOUNT_CACHED # or MOUNT

要了解不同模式的更多信息,请参阅SkyPilot 存储桶挂载高性能训练

实际示例#

有关更多训练示例和最佳实践,请参阅模型训练指南

用户代码失败时的作业重启#

抢占或硬件故障将自动恢复,但默认情况下,用户代码失败(非零退出码)不会自动恢复

在某些情况下,您可能希望即使应用程序代码失败也能自动重启作业。例如,如果训练作业由于 NVIDIA 驱动程序问题或 NCCL 超时而崩溃,应将其恢复。要指定此设置,您可以在作业 YAML 文件中的 resources.job_recovery 中设置 max_restarts_on_errors

resources:
  accelerators: A100:8
  job_recovery:
    # Restart the job up to 3 times on user code errors.
    max_restarts_on_errors: 3

如果您的代码有任何非零退出码,这将最多重启作业 3 次(总共 4 次尝试)。每次重启都在新调配的临时集群上运行。

我的作业何时会被恢复?#

以下是 SkyPilot 处理各种类型故障的方式

用户代码失败(setuprun 命令有非零退出码)

如果设置了 max_restarts_on_errors,最多重启设定的次数。如果未设置 max_restarts_on_errors,或者重启次数用尽,将作业设置为 FAILEDFAILED_SETUP

实例被抢占或底层硬件失败

拆除旧的临时集群,在另一区域调配新集群,然后重启作业。

因云配额或容量限制找不到可用资源

无限期地尝试其他区域和其他云服务商,直到找到资源。

云配置/认证问题或无效作业配置

将作业标记为 FAILED_PRECHECKS 并退出。不会重试。

要查看用户代码(setuprun 命令)的日志,请使用 sky jobs logs <job_id>。如果存在资源调配或恢复问题,您可以通过运行 sky jobs logs --controller <job_id> 查看资源调配日志。

提示

在后台,SkyPilot 使用一个“控制器”来调配、监控和恢复底层的临时集群。请参阅工作原理:作业控制器

扩展到大量作业#

您可以轻松地同时管理数十、数百或数千个托管作业。这非常适合批处理作业,例如数据处理批量推理超参数搜索。要查看并行启动大量作业的示例,请参阅大量并行作业

要增加可以同时运行的最大作业数量,请参阅扩展作业控制器的最佳实践

托管管道#

管道是一个包含按顺序运行的一系列任务的托管作业。

这对于运行相互依赖的一系列任务非常有用,例如训练模型,然后在模型上运行推理。不同的任务可以有不同的资源需求,以便为每个任务使用适当的资源,从而节省成本,同时减轻用户管理任务的负担。

注意

换句话说,托管作业要么是单个任务,要么是任务管道。所有托管作业都通过 sky jobs launch 提交。

要运行管道,请在 YAML 文件中指定任务序列。下面是一个示例

name: pipeline

---

name: train

resources:
  accelerators: V100:8
  any_of:
    - use_spot: true
    - use_spot: false

file_mounts:
  /checkpoint:
    name: train-eval # NOTE: Fill in your bucket name
    mode: MOUNT

setup: |
  echo setup for training

run: |
  echo run for training
  echo save checkpoints to /checkpoint

---

name: eval

resources:
  accelerators: T4:1
  use_spot: false

file_mounts:
  /checkpoint:
    name: train-eval # NOTE: Fill in your bucket name
    mode: MOUNT

setup: |
  echo setup for eval

run: |
  echo load trained model from /checkpoint
  echo eval model on test set

上面的 YAML 定义了一个包含两个任务的管道。第一个 name: pipeline 为管道命名。第一个任务名为 train,第二个任务名为 eval。任务之间由包含三个破折号 --- 的行分隔。每个任务都有自己的 resourcessetuprun 部分。任务按顺序执行。如果一个任务失败,后续任务将被跳过。

要在任务之间传递数据,请使用共享文件挂载。在此示例中,train 任务将其输出写入 /checkpoint 文件挂载,然后 eval 任务可以从中读取。

要提交管道,使用相同的命令 sky jobs launch。管道将由 SkyPilot 自动启动和监控。您可以使用 sky jobs queuesky jobs dashboard 检查管道的状态。

$ sky jobs launch -n pipeline pipeline.yaml

$ sky jobs queue

Fetching managed job statuses...
Managed jobs
In progress jobs: 1 RECOVERING
ID  TASK  NAME      RESOURCES                    SUBMITTED    TOT. DURATION  JOB DURATION  #RECOVERIES  STATUS
8         pipeline  -                            50 mins ago  47m 45s        -             1            RECOVERING
 ↳  0     train     1x [V100:8][Spot|On-demand]  50 mins ago  47m 45s        -             1            RECOVERING
 ↳  1     eval      1x [T4:1]                    -            -              -             0            PENDING

注意

环境变量 $SKYPILOT_TASK_ID 也可在每个任务的 run 部分使用。它对于管道中的每个任务都是唯一的。例如,上述 eval 任务的 $SKYPILOT_TASK_ID 是:“sky-managed-2022-10-06-05-17-09-750781_pipeline_eval_8-1”。

设置作业文件存储桶#

对于托管作业,SkyPilot 需要一个中间存储桶来存储任务中使用的文件,例如本地文件挂载、临时文件和工作目录。如果您未配置存储桶,SkyPilot 将为每次作业启动自动创建一个名为 skypilot-filemounts-{username}-{run_id} 的临时存储桶。作业完成后,SkyPilot 会自动删除该存储桶。

或者,您可以预先调配一个存储桶,并通过在 ~/.sky/config.yaml 中设置 jobs.bucket 将其用作文件存储的中间存储桶。

# ~/.sky/config.yaml
jobs:
  bucket: s3://my-bucket  # Supports s3://, gs://, https://<azure_storage_account>.blob.core.windows.net/<container>, r2://, cos://<region>/<bucket>

如果您选择指定存储桶,请确保该存储桶已存在并且您拥有必要的权限。

当使用预先调配的中间存储桶 jobs.bucket 时,SkyPilot 会在存储桶根目录下创建作业特定的目录来存储文件。它们的组织结构如下

# cloud bucket, s3://my-bucket/ for example
my-bucket/
├── job-15891b25/            # Job-specific directory
│   ├── local-file-mounts/   # Files from local file mounts
│   ├── tmp-files/           # Temporary files
│   └── workdir/             # Files from workdir
└── job-cae228be/            # Another job's directory
    ├── local-file-mounts/
    ├── tmp-files/
    └── workdir/

当使用自定义存储桶(jobs.bucket)时,作业完成时,SkyPilot 创建的作业特定目录(例如 job-15891b25/)将被移除。

提示

多个用户可以共享同一个中间存储桶。每个用户的作业将拥有自己唯一的作业特定目录,确保文件分开且井井有条。

工作原理:作业控制器#

作业控制器是在云中运行的小型按需 CPU 虚拟机或 Pod,用于管理用户的所有作业。在提交第一个托管作业时自动启动,并在空闲 10 分钟后自动停止(即,所有托管作业完成后且在此期间没有提交新的托管作业)。因此,管理其生命周期无需用户操作

您可以使用 sky status 查看控制器,并使用 -r/--refresh 标志刷新其状态。

虽然作业控制器的成本可以忽略不计(运行时约 0.25 美元/小时,停止时低于 0.004 美元/小时),您仍然可以使用 sky down <job-controller-name> 手动将其拆除,其中 <job-controller-name> 可以在 sky status 的输出中找到。

注意

拆除作业控制器将丢失所有已完成托管作业的日志和状态信息。只有在没有进行中的托管作业时才允许拆除,以确保不发生资源泄漏。

要调整作业控制器实例的大小,请参阅自定义作业控制器资源

设置和最佳实践#

使用长期凭证#

由于作业控制器是用于管理其他云实例的长期实例,因此最好使用不会过期的静态凭证。如果凭证过期,控制器可能无法清理作业,导致昂贵的云实例泄漏。因此,建议设置长期凭证访问,例如 AWS 上的 ~/.aws/credentials 文件,或 GCP 上的服务账户 JSON 密钥文件。

要为作业控制器使用长期静态凭证,只需确保 SkyPilot 正在使用正确的凭证即可。它们将自动上传到作业控制器。如果您已经在使用不会过期的本地凭证,则无需采取任何行动。

设置凭证

自定义作业控制器资源#

您可能出于多种原因需要自定义作业控制器的资源

  1. 增加可以同时运行的最大作业数量,这取决于控制器实例的大小。(默认:90,请参阅最佳实践

  2. 使用成本较低的控制器(如果您有少量并发托管作业)。

  3. 强制作业控制器在特定位置运行。(默认:最便宜的位置)

  4. 更改作业控制器的 disk_size 以存储更多日志。(默认:50GB)

为实现上述目标,您可以在 ~/.sky/config.yaml 中通过以下字段指定自定义配置

jobs:
  # NOTE: these settings only take effect for a new jobs controller, not if
  # you have an existing one.
  controller:
    resources:
      # All configs below are optional.
      # Specify the location of the jobs controller.
      cloud: gcp
      region: us-central1
      # Bump cpus to allow more managed jobs to be launched concurrently. (Default: 4+)
      cpus: 8+
      # Bump memory to allow more managed jobs to be running at once.
      # By default, it scales with CPU (8x).
      memory: 64+
      # Specify the disk_size in GB of the jobs controller.
      disk_size: 100

resources 字段的规范与普通 SkyPilot 作业相同;请参见此处

注意

如果您有现有控制器(无论是停止的还是正在运行的),这些设置将不会生效。要使其生效,首先需要拆除现有控制器,这要求所有进行中的作业完成或被取消。

要查看您当前的作业控制器,请使用 sky status

$ sky status --refresh

Clusters
NAME                          LAUNCHED     RESOURCES                          STATUS   AUTOSTOP  COMMAND
my-cluster-1                  1 week ago   1x AWS(m6i.4xlarge)                STOPPED  -         sky launch --cpus 16 --cloud...
my-other-cluster              1 week ago   1x GCP(n2-standard-16)             STOPPED  -         sky launch --cloud gcp --...
sky-jobs-controller-919df126  1 day ago    1x AWS(r6i.xlarge, disk_size=50)   STOPPED  10m       sky jobs launch --cpus 2 ...

Managed jobs
No in-progress managed jobs.

Services
No live services.

在此示例中,您可以看到作业控制器(sky-jobs-controller-919df126)是 AWS 上的 r6i.xlarge,这是默认大小。

要拆除当前控制器以便应用新的资源配置,请使用 sky down

$ sky down sky-jobs-controller-919df126

WARNING: Tearing down the managed jobs controller. Please be aware of the following:
 * All logs and status information of the managed jobs (output of `sky jobs queue`) will be lost.
 * No in-progress managed jobs found. It should be safe to terminate (see caveats above).
To proceed, please type 'delete': delete
Terminating cluster sky-jobs-controller-919df126...done.
Terminating 1 cluster ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:00

下次您使用 sky jobs launch 时,将创建一个具有更新资源的新控制器。

扩展作业控制器的最佳实践#

提示

对于托管作业,强烈建议使用用于云认证的长期凭证。这样作业控制器的凭证就不会过期。这在大型生产运行中尤为重要,可以避免资源泄漏。

控制器支持的活动作业数量取决于控制器的大小。有两个限制适用

  • 正在启动的作业数量:最多为 4 * vCPU 数量。作业在首次启动、启动实例或恢复时计入此限制。

    • 默认控制器大小有 4 个 CPU,意味着可以同时启动 16 个作业

  • 正在运行的作业数量:最多为 内存 / 350MiB,上限为 2000 个作业。

    • 默认控制器大小有 32GiB 内存,意味着可以并行运行约 90 个作业

默认大小适用于大多数中等使用场景,但如果您需要同时运行数百或数千个作业,则应增加控制器的大小。

为获得最大并行度,建议进行以下配置

jobs:
  controller:
    resources:
      # In our testing, aws > gcp > azure
      cloud: aws
      cpus: 128
      # Azure does not have 128+ CPU instances, so use 96 instead
      # cpus: 96
      memory: 600+
      disk_size: 500

注意

请记住按照上述说明拆除控制器以应用这些更改。

使用此配置,您将获得以下性能

云服务商

实例类型

启动中的作业

运行中的作业

AWS

r6i.32xlarge

同时启动 512 个

同时运行 2000 个

GCP

n2-highmem-128

同时启动 512 个

同时运行 2000 个

Azure

Standard_E96s_v5

同时启动 384 个

同时运行 1930 个