在 Kubernetes 上开始使用#

快速入门#

有 kubeconfig 文件?只需 3 个命令即可开始使用 SkyPilot

# Install dependencies
$ brew install kubectl socat netcat
# Linux: sudo apt-get install kubectl socat netcat

# With a valid kubeconfig at ~/.kube/config, run:
$ sky check
# Shows "Kubernetes: enabled"

# Launch your SkyPilot cluster
$ sky launch --cpus 2+ -- echo hi

有关详细说明、前提条件和高级功能,请继续阅读。

前提条件#

要连接和使用 Kubernetes 集群,SkyPilot 需要

  • 一个运行 Kubernetes v1.20 或更高版本的现有 Kubernetes 集群。

  • 一个包含访问凭据和要使用的命名空间的 Kubeconfig 文件。

支持的 Kubernetes 部署

  • 托管式 Kubernetes 服务 (EKS, GKE)

  • 本地集群 (Kubeadm, Rancher, K3s)

  • 本地开发集群 (KinD, minikube)

在典型的工作流程中

  1. 集群管理员设置 Kubernetes 集群。请参考 Kubernetes 集群设置 的管理员指南,了解不同部署环境(Amazon EKS、Google GKE、本地和本地调试)。

  2. 希望在此集群上运行 SkyPilot 任务的用户会获得包含其凭据 (kube-context) 的 Kubeconfig 文件。SkyPilot 读取此 Kubeconfig 文件与集群通信。

启动你的第一个任务#

一旦你的集群管理员 设置好 Kubernetes 集群 并为你提供了 kubeconfig 文件

  1. 确保你的本地机器上安装了 kubectlsocatnc (netcat)。

    $ # MacOS
    $ brew install kubectl socat netcat
    
    $ # Linux (may have socat already installed)
    $ sudo apt-get install kubectl socat netcat
    
  2. 将你的 kubeconfig 文件放在 ~/.kube/config

    $ mkdir -p ~/.kube
    $ cp /path/to/kubeconfig ~/.kube/config
    

    通过运行 kubectl get pods 命令,你可以验证你的凭据是否已正确设置。

    注意

    如果你的集群管理员还为你提供了特定的服务账户,请在你的 ~/.sky/config.yaml 文件中进行设置。

    kubernetes:
      remote_identity: your-service-account-name
    
  3. 运行 sky check 命令并验证 SkyPilot 中是否启用了 Kubernetes。

    $ sky check
    
    Checking credentials to enable clouds for SkyPilot.
    ...
    Kubernetes: enabled
    ...
    

    注意

    sky check 还会检查你的集群是否支持 GPU。如果不支持 GPU,它会显示原因。要在集群上设置 GPU 支持,请参考 Kubernetes 集群设置指南

  1. 你现在可以在你的 Kubernetes 集群上运行任何 SkyPilot 任务了。

    $ sky launch --cpus 2+ task.yaml
    == Optimizer ==
    Target: minimizing cost
    Estimated cost: $0.0 / hour
    
    Considered resources (1 node):
    ---------------------------------------------------------------------------------------------------
     CLOUD        INSTANCE          vCPUs   Mem(GB)   ACCELERATORS   REGION/ZONE   COST ($)   CHOSEN
    ---------------------------------------------------------------------------------------------------
     Kubernetes   2CPU--2GB         2       2         -              kubernetes    0.00          ✔
     AWS          m6i.large         2       8         -              us-east-1     0.10
     Azure        Standard_D2s_v5   2       8         -              eastus        0.10
     GCP          n2-standard-2     2       8         -              us-central1   0.10
     IBM          bx2-8x32          8       32        -              us-east       0.38
     Lambda       gpu_1x_a10        30      200       A10:1          us-east-1     0.60
    ---------------------------------------------------------------------------------------------------.
    

注意

SkyPilot 将使用 kubeconfig 文件中 current-context 中设置的集群和命名空间。要管理你的 current-context

$ # See current context
$ kubectl config current-context

$ # Switch current-context
$ kubectl config use-context mycontext

$ # Set a specific namespace to be used in the current-context
$ kubectl config set-context --current --namespace=mynamespace

查看集群状态#

要查看 Kubernetes 集群中所有 SkyPilot 资源的状体,请运行 sky status --k8s 命令。

与只列出当前用户启动的 SkyPilot 资源的 sky status 不同,sky status --k8s 会列出 Kubernetes 集群中所有用户的 SkyPilot 资源。

$ sky status --k8s
Kubernetes cluster state (context: mycluster)
SkyPilot clusters
USER     NAME                           LAUNCHED    RESOURCES                                  STATUS
alice    infer-svc-1                    23 hrs ago  1x Kubernetes(cpus=1, mem=1, {'L4': 1})    UP
alice    sky-jobs-controller-80b50983   2 days ago  1x Kubernetes(cpus=4, mem=4)               UP
alice    sky-serve-controller-80b50983  23 hrs ago  1x Kubernetes(cpus=4, mem=4)               UP
bob      dev                            1 day ago   1x Kubernetes(cpus=2, mem=8, {'H100': 1})  UP
bob      multinode-dev                  1 day ago   2x Kubernetes(cpus=2, mem=2)               UP
bob      sky-jobs-controller-2ea485ea   2 days ago  1x Kubernetes(cpus=4, mem=4)               UP

Managed jobs
In progress tasks: 1 STARTING
USER     ID  TASK  NAME      RESOURCES   SUBMITTED   TOT. DURATION  JOB DURATION  #RECOVERIES  STATUS
alice    1   -     eval      1x[CPU:1+]  2 days ago  49s            8s            0            SUCCEEDED
bob      4   -     pretrain  1x[H100:4]  1 day ago   1h 1m 11s      1h 14s        0            SUCCEEDED
bob      3   -     bigjob    1x[CPU:16]  1 day ago   1d 21h 11m 4s  -             0            STARTING
bob      2   -     failjob   1x[CPU:1+]  1 day ago   54s            9s            0            FAILED
bob      1   -     shortjob  1x[CPU:1+]  2 days ago  1h 1m 19s      1h 16s        0            SUCCEEDED

你还可以使用 sky show-gpus --cloud k8s 命令查看集群上实时的 GPU 使用情况。

$ sky show-gpus --cloud k8s
Kubernetes GPUs
GPU   REQUESTABLE_QTY_PER_NODE  UTILIZATION
L4    1, 2, 4                   12 of 12 free
H100  1, 2, 4, 8                16 of 16 free

Kubernetes per node GPU availability
NODE                       GPU       UTILIZATION
my-cluster-0               L4        4 of 4 free
my-cluster-1               L4        4 of 4 free
my-cluster-2               L4        2 of 2 free
my-cluster-3               L4        2 of 2 free
my-cluster-4               H100      8 of 8 free
my-cluster-5               H100      8 of 8 free

使用自定义镜像#

默认情况下,我们维护并使用两个 SkyPilot 容器镜像用于 Kubernetes 集群:

  1. us-central1-docker.pkg.dev/skypilot-375900/skypilotk8s/skypilot:用于仅 CPU 集群 (Dockerfile)。

  2. us-central1-docker.pkg.dev/skypilot-375900/skypilotk8s/skypilot-gpu:用于 GPU 集群 (Dockerfile)。

这些镜像已预安装 SkyPilot 依赖项,以加快启动速度。

要使用你自己的镜像,请在你的任务 YAML 的 resources 部分添加 image_id: docker:<your image tag>

resources:
  image_id: docker:myrepo/myimage:latest
...

你的镜像必须满足以下要求:

  • 镜像必须是 基于 debian 的,并且必须安装 apt 包管理器。

  • 镜像中的默认用户必须具有 root 权限或无密码的 sudo 访问权限。

注意

如果你的集群运行在非 x86_64 架构(例如 Apple Silicon)上,你的镜像必须原生构建以支持该架构。否则,你的作业可能会卡在 Start streaming logs ...。有关更多信息,请参阅 GitHub 问题

使用私有仓库中的镜像#

要使用私有仓库(例如 Private DockerHub、Amazon ECR、Google Container Registry)中的镜像,请在你的 Kubernetes 集群中创建一个 secret,并编辑你的 ~/.sky/config.yaml 文件以如下方式指定 secret:

kubernetes:
  pod_config:
    spec:
      imagePullSecrets:
        - name: your-secret-here

提示

如果你使用 Amazon ECR,你的 secret 凭据可能每 12 小时过期一次。考虑使用 k8s-ecr-login-renew 自动刷新你的 secrets。

开放端口#

在 Kubernetes 上运行的 SkyPilot 集群支持通过两种模式开放端口:

  1. LoadBalancer 服务(默认)

  2. Nginx IngressController

你的集群必须支持并配置其中一种模式。关于如何进行设置,请参考 在 Kubernetes 上设置端口指南

提示

在 Google GKE、Amazon EKS 或其他云托管的 Kubernetes 服务中,默认的 LoadBalancer 服务模式开箱即用,无需额外配置。

配置好集群后,通过在任务 YAML 的 resources 部分添加 ports 来启动在端口上暴露服务的任务。

# task.yaml
resources:
  ports: 8888

run: |
  python -m http.server 8888

使用 sky launch -c myclus task.yaml 启动集群后,你可以使用 sky status --endpoints myclus 命令获取访问该端口的 URL。

# List all ports exposed by the cluster
$ sky status --endpoints myclus
8888: 34.173.13.241:8888

# curl a specific port's endpoint
$ curl $(sky status --endpoint 8888 myclus)
...

提示

要了解更多关于在 SkyPilot 任务中开放端口的信息,请参阅 开放端口

自定义 SkyPilot Pod#

你可以通过在 ~/.sky/config.yaml 文件中设置 pod_config 键来覆盖 SkyPilot 使用的 pod 配置。 pod_config 的值应该是一个遵循 Kubernetes Pod API 的字典。这将应用于 SkyPilot 创建的所有 pods。

例如,要设置自定义环境变量并使用 GPUDirect RDMA,你可以将以下内容添加到你的 ~/.sky/config.yaml 文件中:

# ~/.sky/config.yaml
kubernetes:
  pod_config:
    spec:
      containers:
        - env:                # Custom environment variables to set in pod
          - name: MY_ENV_VAR
            value: MY_ENV_VALUE
          resources:          # Custom resources for GPUDirect RDMA
            requests:
              rdma/rdma_shared_device_a: 1
            limits:
              rdma/rdma_shared_device_a: 1

提示

除了全局设置 pod_config 外,你还可以在任务 YAML 中直接通过 config 字段 按任务设置它。

# task.yaml
run: |
  python myscript.py

# Set pod_config for this task
config:
  kubernetes:
    pod_config:
      ...

挂载 NFS 和其他卷#

可以使用 pod_config 字段将 Kubernetes 卷 附加到 SkyPilot pods。这对于访问共享存储(如 NFS)或本地高性能存储(如 NVMe 驱动器)非常有用。

有关详细信息和示例,请参阅 设置 NFS 和其他卷

常见问题#

  • 我可以使用 SkyPilot 连接多个 Kubernetes 集群吗?

    SkyPilot 可以通过在 ~/.sky/config.yaml 文件中设置 allowed_contexts 键来使用 kubeconfig 文件中的多个 Kubernetes context。请参阅 多个 Kubernetes 集群

    如果未设置 allowed_contexts,SkyPilot 将使用当前的活动 context。要使用不同的 context,请使用 kubectl config use-context <context-name> 命令更改当前 context。

  • 是否支持自动扩缩的 Kubernetes 集群?

    要在自动扩缩集群上运行,请在 ~/.sky/config.yaml 文件中将 provision_timeout 键设置为较大的值,以便为集群自动扩缩器提供足够的时间来调配新节点。这将指示 SkyPilot 等待集群扩容,然后再故障转移到下一个候选资源(例如,下一个云)。

    如果你在 scale-to-zero 环境中使用 GPU,你还应该将 autoscaler 键设置为你的集群的自动扩缩器类型。更多详细信息请参阅 高级配置

    # ~/.sky/config.yaml
    kubernetes:
      provision_timeout: 900  # Wait 15 minutes for nodes to get provisioned before failover. Set to -1 to wait indefinitely.
      autoscaler: gke  # [gke, karpenter, generic]; required if using GPUs/TPUs in scale-to-zero setting
    
  • SkyPilot 可以为我调配 Kubernetes 集群吗?SkyPilot 会为我的 Kubernetes 集群添加更多节点吗?

    Kubernetes 支持的目标是在现有的 Kubernetes 集群上运行 SkyPilot 任务。它不会调配任何新的 Kubernetes 集群,也不会向现有的 Kubernetes 集群添加新节点。

  • 我的组织中有多个用户共享同一个 Kubernetes 集群。如何为他们的 SkyPilot 工作负载提供隔离?

    为了实现隔离,你可以创建独立的 Kubernetes 命名空间,并在分发给用户的 kubeconfig 文件中进行设置。SkyPilot 将使用 kubeconfig 文件中设置的命名空间来运行所有任务。

  • 如何查看 SkyPilot 在我的 Kubernetes 集群上创建的 pods?

    你可以使用现有的可观测性工具,通过标签 parent=skypilot (kubectl get pods -l 'parent=skypilot') 过滤资源。例如,按照 此处 的说明在你的集群上部署 Kubernetes Dashboard。

  • SkyPilot 支持 GKE 上的 TPU 吗?

    SkyPilot 支持 GKE 上的单主机 TPU 拓扑(例如,1x1、2x2、2x4)。要使用 TPU,请将其添加到任务 YAML 的 accelerator 字段中:

    resources:
      accelerators: tpu-v5-lite-podslice:1  # or tpu-v5-lite-device, tpu-v5p-slice
    
  • 我正在使用自定义镜像。如何加快 pod 启动时间?

    你可以在自定义镜像中预安装 SkyPilot 依赖项,以加快 pod 启动时间。只需在 Dockerfile 的末尾添加以下几行即可:

    FROM <your base image>
    
    # Install system dependencies
    RUN apt update -y && \
        apt install git gcc rsync sudo patch openssh-server pciutils fuse unzip socat netcat-openbsd curl -y && \
        rm -rf /var/lib/apt/lists/*
    
    # Install conda and other python dependencies
    RUN curl https://repo.anaconda.com/miniconda/Miniconda3-py310_23.11.0-2-Linux-x86_64.sh -o Miniconda3-Linux-x86_64.sh && \
        bash Miniconda3-Linux-x86_64.sh -b && \
        eval "$(~/miniconda3/bin/conda shell.bash hook)" && conda init && conda config --set auto_activate_base true && conda activate base && \
        grep "# >>> conda initialize >>>" ~/.bashrc || { conda init && source ~/.bashrc; } && \
        rm Miniconda3-Linux-x86_64.sh && \
        export PIP_DISABLE_PIP_VERSION_CHECK=1 && \
        python3 -m venv ~/skypilot-runtime && \
        PYTHON_EXEC=$(echo ~/skypilot-runtime)/bin/python && \
        $PYTHON_EXEC -m pip install 'skypilot-nightly[remote,kubernetes]' 'ray[default]==2.9.3' 'pycryptodome==3.12.0' && \
        $PYTHON_EXEC -m pip uninstall skypilot-nightly -y && \
        curl -LO "https://dl.k8s.io/release/v1.28.11/bin/linux/amd64/kubectl" && \
        sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl && \
        echo 'export PATH="$PATH:$HOME/.local/bin"' >> ~/.bashrc
    
  • Kubernetes 支持多节点作业吗?

    Kubernetes 支持 多节点作业。启动多节点作业时,SkyPilot 集群中的每个节点都将作为一个单独的 pod 进行调配。

    SkyPilot 将尝试将每个 pod 放置在集群中的不同节点上。

    SkyPilot 将尝试在给定集群上调度所有 pods。如果 SkyPilot 无法在给定集群上调度所有 pods(即部分或所有 pods 无法调度),SkyPilot 将故障转移到另一个集群或云。